我有一个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)向<p>
节点添加动态ID,其属性值为type="note"
2)在<newNode>
节点内名为<p>
的新节点,其属性值为type="note"
3)为新创建的<newNode>
4)在<Finish>
个节点结束之前添加一个<session>
节点,该节点至少包含节点<foot>
节点
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>
节点。
提前致谢
答案 0 :(得分:1)
我遇到的唯一问题是当我写
<xsl:template match="session//foot"/>
以删除它删除的原始<foot>
节点时 每个<foot>
也会复制到新的地方。
那是因为你正在使用:
<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
),因此您可能需要在更多地方添加类似的异常。