我阅读了一些 XSLT 示例并找到了该代码:
<xsl:apply-template select="@*|node()"/>
这意味着什么?
XPath 表达式@* | node()
选择属性节点 ( ) 和所有其他类型的 XML 节点 ( ) 的并集。@*
node()
它是 的简写attribute::* | child::node()
。
在 XSLT 中,XPath 是相对于上下文节点的,默认选择轴是child
轴,所以表达式
select="..."
表达式时,例如 in <xsl:apply-templates>
)match=""
表达式时<xsl:template>
) - 请注意,选择节点和匹配它们之间存在差异:上下文节点仅对选择很重要。想象以下节点是上下文节点:
<xml attr="value">[
]<child />[
]<!-- comment -->[
]<child>
<descendant />
</child>[
]</xml>
该表达式node()
不仅会选择两个<child>
节点,还会选择四个纯空格文本节点(由可见性表示)和注释[
。]
未<descendant>
选中。
XML 的一个特殊特性是属性节点不是它们所属元素的子节点(尽管属性的父节点是它所属的元素)。
这种不对称关系使得有必要分别选择它们,因此@*
.
它匹配属于上下文节点的任何属性节点,因此attr="value"
也将被选中。
是|
XPath 联合运算符。它从两个单独的节点集创建单个节点集。
<xsl:apply-templates>
然后<xsl:template>
为每个选定的节点找到合适的并为该节点运行它。这就是我上面提到的模板匹配部分。
要添加到 Tomalak 的出色答案:
大多数情况下,人们会看到<xsl:apply-template select="@*|node()"/>
在这样的模板中使用:
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
这称为身份规则或“身份模板”。
最基本和最强大的 XSLT 设计模式之一是标识规则的使用和覆盖。
如果转换仅包含身份规则,则转换的结果是源 XML 文档本身——这就是模板被称为“身份规则”的原因。
为什么会产生这个结果?
简短的回答是:因为 XSLT 处理模型。
更详细的解释必须从顶部开始:
node()
匹配任何元素、文本节点、注释或处理指令。文档-(根)-节点也与 匹配node()
。
我们可以想象任何文档树的“叶”节点——这些节点本身没有子节点,例如文本节点、注释和处理指令。空元素也应被视为叶节点。
身份规则最初被选择用于对文档节点的所有子节点执行(应用)(这些是单个顶部元素和它可能具有的任何注释或处理指令兄弟)。匹配的节点是浅拷贝的,如果它是非元素叶节点,则<xsl:apply-templates select="node()|@*"/>
指令不会选择任何节点或属性。
如果匹配的节点是一个元素,那么它是浅拷贝的,那么<xsl:apply-templates select="node()|@*"/>
指令会导致将相同的模板(因为在转换代码中没有任何其他模板)应用于其每个属性及其每个子节点。
这是驱动处理 XML 文档的每个节点的递归,直到到达叶节点或属性,并且在该位置不<xsl:apply-templates select="node()|@*"/>
选择子节点或属性节点。
恭喜@Tomalak 获得第一个正确答案。打勾应该是他的回答。我只想对他的回答进行一些澄清。
... @* | node() 选择...的并集
该| 运算符不仅返回两个操作数的并集,而且按文档顺序排序并删除重复项。de-dup 部分在这里不相关,因为没有要删除的重复项,但排序部分值得注意。更正确的版本是说...
... @* | node() 选择联合,按文档顺序排序,...
...以及所有其他类型的 XML 子节点 (node())
这大体上是正确的,但具有误导性。当大多数人阅读“XML 子节点”时,他们会想到 DOM 意义上的子节点。但这不是被选中的。仅选择 XDM 节点。有关说明,请查看以下文档。
<?xml version="1.0" encoding="ISO-8859-1"?>
<root-element my-attrib="myattrib-vaue" xmlns:hi="www.abc.com"><child-element />
abc'def
</root-element>
现在假设上下文项是“根元素”。Tomalak 的回答的读者被问到一个问题:“@*|node()”选择了什么?对于那些思考 DOM 模型的人来说,Tomalak 的答案意味着选择了 6 件事:
但在 XSLT 中这实际上并非如此。实际选择的是...
所以更准确的说法是......
XPath 表达式@* | node() 选择按文档顺序排序的联合(上下文项的属性节点和 XDM 意义上的上下文项的 XML 子节点)。XD 模型忽略了 DOM 中的一些节点类型,例如实体定义,并且将连续的文本 DOM 节点连接成一个 XDM 文本节点。