【问题标题】:Difference between: child::node() and child::*区别:child::node() 和 child::*
【发布时间】:2011-07-20 15:11:56
【问题描述】:

我刚写了一个 XSLT,一开始没用。

我不得不将<Recordset> 的所有子代重命名为<C>

<?xml version="1.0" encoding="utf-8"?>
<Record>
<Recordset>
    <company>102</company>
    <store>1801</store>
    ....
</Recordset>
<Recordset>
....
</Recordset>
</Record>

我使用了以下 XSLT:

<xsl:template match="Record/Recordset/child::*">    
    <xsl:element name="C">
        <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
</xsl:template>

它可以工作并将&lt;Recordset&gt; 的所有子代重命名为&lt;C&gt;。 但首先我在模板中的匹配是这样的:

<xsl:template match="Record/Recordset/child::node()">

我的想法是&lt;Recordset&gt; 的每个孩子都是一个节点,因此node() 是合适的。 它也有效,但它为每个孩子插入了一个额外的&lt;C/&gt;

child::node()child::* 有什么区别?

【问题讨论】:

  • "我的想法是 的每个子节点都是一个节点" >> 这句话是正确的,但是您忘记了文本节点子节点,即使它们是在你的例子中只有空格。其他不是元素的子节点也是节点:cmets 和处理指令。命名空间节点和属性节点被特殊对待。
  • 感谢亚伯的评论。在此期间我已经想通了。

标签: xslt


【解决方案1】:

child::node() 匹配任何不是属性节点、命名空间节点或文档节点的节点。这意味着它确实匹配处理指令、cmets 和文本节点。

child::*只匹配个元素。

参见规范的section 5.5.3

模式 node() 匹配所有节点 由表达式选择 root(.)//(child-or-top::node()), 那 是,所有元素、文本、评论和 处理指令节点,是否 或者他们没有父母。它不是 匹配属性或命名空间节点 因为表达式没有选择 使用属性或命名空间的节点 轴。它与文档节点不匹配 因为为了向后兼容 child-or-top 轴没有的原因 匹配一个文档节点。

更新:迈克尔的回答启发了以下样式表。使用它来测试处理节点的类型:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/|node()">
        <xsl:call-template name="type" />
        <xsl:text>  [  </xsl:text>
        <xsl:value-of select="." />
        <xsl:text>&#10;</xsl:text>
        <xsl:apply-templates select="node()" />
        <xsl:text>  ]  </xsl:text>
    </xsl:template>
    <xsl:template name="type">
        <xsl:choose>
            <xsl:when test="count(.|/)=1">
                <xsl:text>Root</xsl:text>
            </xsl:when>
            <xsl:when test="self::*">
                <xsl:text>Element </xsl:text>
                <xsl:value-of select="name()" />
            </xsl:when>
            <xsl:when test="self::text()">
                <xsl:text>Text</xsl:text>
            </xsl:when>
            <xsl:when test="self::comment()">
                <xsl:text>Comment</xsl:text>
            </xsl:when>
            <xsl:when test="self::processing-instruction()">
                <xsl:text>PI</xsl:text>
            </xsl:when>
            <xsl:when test="count(.|../@*)=count(../@*)">
                <xsl:text>Attribute</xsl:text>
            </xsl:when>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

修改匹配/选择的内容以测试其他模式。例如,以下输入:

<A attr="test" other="val">
  <B/>
  <C>some value</C>
  <!-- a comment -->
  <D/>
</A>

产生以下输出:

Root  [  

  some value



Element A  [  

  some value



Text  [  

  ]  Element B  [  
  ]  Text  [  

  ]  Element C  [  some value
Text  [  some value
  ]    ]  Text  [  

  ]  Comment  [   a comment 
  ]  Text  [  

  ]  Element D  [  
  ]  Text  [  

  ]    ]    ]  

特别感谢 this page 让我开始进行节点类型测试。 (迈克尔六年前的一个答案也出现在此处,这尤其合适。)

【讨论】:

  • 非常感谢您提供节点测试示例!我一直对文本、节点和元素有点困惑……
【解决方案2】:

扩展 lwburk 的答案,如果您的 XML 如下所示:

<A>
  <B/>
  <C/>
  <D/>
</A>

那么A元素有7个子节点;其中三个是元素,四个是文本节点。表达式child::node() 匹配所有7,而child::* 只匹配元素。

【讨论】:

  • 谢谢迈克尔。我也将不得不玩弄它。我还没有“看到”这 4 个文本节点。
  • 每个"&gt;" 之后和下一个"&lt;" 之前都有一些空格。有四个这样的间隙,每一个都是一个只有空格的文本节点。
  • 你好 Michael,谢谢 - 我不知道空格是文本节点。现在我明白了,现在我也得到了插入的额外 元素的原始问题。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-25
  • 1970-01-01
  • 2014-08-30
相关资源
最近更新 更多