XSLT - 将节点复制到新位置并删除原始节点

XSLT - copy nodes to new location and remove original

我有一个 xml 如下,

<session>
    <foot>
        <p type="note">
            <link ref="http://www.facebook.com">
                <c type="Hyperlink">www.faceook.com</c>
            </link>
        </p>
    </foot>
    <foot>
        <p type="note">
            <link ref="http://www.google.com">
                <c type="Hyperlink">www.google.com</c>
            </link>
        </p>
    </foot>
    <middle>

    </middle>
    <middle>

    </middle>
</session>

我的要求是,

1) 添加动态id到属性值为type="note"

<p>节点

2) 和 <p> 节点内名为 <newNode> 的新节点,其属性值为 type="note"

3) 添加动态id到新创建的<newNode>

4) 在 <session> 个至少有节点 <foot> 节点

节点结束之前添加一个 <Finish> 节点

5)复制节点与节点

之间的所有<foot>个节点

6) 去掉原来的 <foot> 个节点

所以输出应该是,

<session>

    <middle>

    </middle>
    <middle>

    </middle>
    <Finish type="Endnotes">End</Finish><foot>
        <p id="id-1" type="note">
            <link ref="http://www.facebook.com">
                <c type="Hyperlink">www.faceook.com</c>
            </link>
            <newNode refType="middle" ref="id-1"/></p>
    </foot><foot>
        <p id="id-2" type="note">
            <link ref="http://www.google.com">
                <c type="Hyperlink">www.google.com</c>
            </link>
            <newNode refType="middle" ref="id-2"/></p>
    </foot>
   </session>

为了完成这个任务,我编写了以下 xsl,

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

    <!-- create dynamic id in <p> node -->
    <xsl:template match="p[@type='note']">
        <xsl:copy>
            <xsl:attribute name="id">
                <xsl:value-of select="'id-'"/> 
                <xsl:number count="p[@type='note']" level="any"/>
            </xsl:attribute>

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

            <!-- add new node named <newNode> in <foot> -->
            <newNode refType="middle">
                <xsl:attribute name="ref">
                    <xsl:value-of select="'id-'"/>
                    <xsl:number count="p[@type='note']" level="any"></xsl:number>
                </xsl:attribute>
            </newNode>
        </xsl:copy>
    </xsl:template>

    <!-- select session which has <foot> nodes -->
    <xsl:template match="session[.//foot]">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
            <!-- create <Finish> node just before </session> -->
            <Finish type="Endnotes">End</Finish>
            <!-- copy <foot> node between <Finish> and </session> -->
            <xsl:apply-templates select="current()//foot"/>
        </xsl:copy>
    </xsl:template>

    <!-- get rid of original <foot> nodes-->
    <xsl:template match="session//foot"/>

我遇到的唯一问题是,当我编写 <xsl:template match="session//foot"/> 来删除原始 <foot> 节点时,它也会删除每个 <foot> 节点,并将其复制到新位置。

任何人都可以建议一种方法来保留复制到新位置的 <foot> 节点并删除原始 <foot> 节点。

提前致谢

Only problem I have is when I write <xsl:template match="session//foot"/> to get rid of original <foot> nodes it removes every <foot> which copy to new place as well.

那是因为您正在使用:

<xsl:apply-templates select="current()//foot"/>

放置节点。这将再次应用您编写的空模板,因此不会输出任何内容。您应该使用:

<xsl:copy-of select="current()//foot"/>

或:

<xsl:apply-templates select="current()//foot" mode="move"/>

并用同样的方式编写另一个匹配foot的模板来处理它。

第三个选项是完全删除匹配 foot 的空模板,并在应用模板时更具选择性。而不是:

<!-- select session which has <foot> nodes -->
<xsl:template match="session[.//foot]">
    <xsl:copy>
        <xsl:apply-templates select="@*|node() "/>

做:

<!-- select session which has <foot> nodes -->
<xsl:template match="session[.//foot]">
    <xsl:copy>
        <xsl:apply-templates select="@*|node() except foot"/>

这假定 foot 始终是 session 的子代,如您的示例所示。您的样式表显然在其他地方也需要它(否则为什么要在 .//foot 中使用 //)所以您可能必须在更多地方添加类似的例外。