首页 文章

XSLT标识转换逻辑

提问于
浏览
1

根据我的理解,XSLT Identity转换模板通过迭代XML结构并复制所有子节点和属性来工作 . 但是当我尝试使用带有 <xsl:template>match 来覆盖节点以进行一些更改时,我无法理解为什么需要在覆盖模板中添加 <xsl:apply-templates/> ,因为理想情况下,身份变换应该处理递归逻辑 .

例如:

对于XML结构:

<page site="TestSite" name="Test_QuestionAnswer1">
<testNode1>
<testNode2>
</page>

我有以下XSL转换:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="page">
<refbody>
    <xsl:attribute name="id">
        <xsl:value-of select="@name"></xsl:value-of>
    </xsl:attribute>
    <xsl:apply-templates></xsl:apply-templates> <!-- ---why is this line needed? Shouldn't the Identity transform template handle the recursion logic? -->
</refbody>
</xsl:template>
</xsl:stylesheet>

用于产生以下输出:

<?xml version="1.0" encoding="UTF-8"?>
<refbody id="Test_QuestionAnswer1">
<testNode1>
<testNode2>
</refbody>

在不添加 xsl:apply-templates 部分的情况下,它只生成第一个节点,并且没有读取Identity变换将整个XML文档映射到类似的XML文档作为输出 . 为什么在这种情况下它不起作用?

2 回答

  • 1

    您要覆盖的身份模板,

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    

    按照设计, explicitly 使用 xsl:apply-templates 继续匹配节点的子节点之间的模式匹配 . 如果任何重写模板也希望其子项受模板模式匹配,则必须遵循相同的形式 .

    这比您建议的子节点匹配的处理模型更有意义,因为有些情况下您不希望继续以递归方式应用匹配 . 一个简单的例子是你想删除一个元素(包括它的后代):

    <xsl:template match="ElementToDelete"/>
    

    有机会控制子节点是否被处理是一个优点,因为它提供了通常方便的控制机会 .

  • 2

    身份转换使用一组模板实现 . 当您添加一个匹配某些具有更高优先级的输入的模板时,它是您的模板,用于确定评估模板时会发生什么 . 如果你想跳过一些或所有孩子,你的模板可以做到这一点;如果你想在某个遥远的位置处理一个元素,你的模板可以做到这一点 . 执行身份转换的模板不处理您匹配的元素:您的模板是 . 他们无法确定模板中发生的情况,包括应评估apply-templates指令的位置和时间 . (如果可以的话,你会如何修改身份转换以抑制一个元素及其所有后代?或者在frontmatter元素的末尾插入一个目录?)

相关问题