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
中使用 //
)所以您可能必须在更多地方添加类似的例外。
我有一个 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
中使用 //
)所以您可能必须在更多地方添加类似的例外。