我刚刚编写了一个起初不起作用的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::*
之间有什么区别?
答案 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> </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::*
仅匹配元素。