区别:child :: node()和child :: *

时间:2011-03-22 16:04:20

标签: xslt

我刚刚编写了一个起初不起作用的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>

它可以将<Recordset>的所有孩子重命名为<C>。 但首先我在模板中的匹配看起来像这样:

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

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

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

2 个答案:

答案 0 :(得分:37)

child::node()匹配任何不属于属性节点,命名空间节点或文档节点的节点。这意味着它 匹配处理指令,注释和文本节点。

child::*仅匹配 元素。

请参阅规范的section 5.5.3

  

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

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

<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让我开始进行节点类型测试。 (特别适合迈克尔六年前的答案也出现在那里。)

答案 1 :(得分:19)

要扩展lwburk的答案,如果你的XML看起来像这样:

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

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