我试图找出子元素相对于其父元素的位置。
我有以下输入 XML:
<Begin>
<tag1>g</tag1>
<tag2>b</tag2>
<tag3>c</tag3>
<tag5>e</tag5>
</Begin>
我需要知道<tag3>
相对于<Begin>
的位置,即 3
这可以在 XSLT 中完成吗?
我当前的 XSLT 如下所示:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Begin[count(tag4)=0]">
<xsl:copy>
<!-- Need to find the position of /Begin/tag3" here -->
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
基本上,我试图做的是在输入XML
中找到<tag3>
的位置并在使用该位置<tag3>
后准确地插入<tag4>
。
所以我的问题是:
如何在<tag3>
和<tag5>
之间的位置插入<tag4>
元素?
这就是我的意图!
插入按字母顺序排序的新元素的一种简单方法是在标识模板中使用<xsl:sort>
,如下所示:
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*">
<xsl:sort select="local-name()" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
此修改会复制按本地名称/标记名称/元素名称按字母顺序排序的所有元素。
您可以使用 xsl:number
或 count(preceding-sibling::*)
找出孩子的位置。
但这对问题的下一部分没有帮助: insert <tag4> exactly after <tag3> using the position
.在 XSLT 中,始终将新数据添加到结果树中的当前写入位置,不能将其添加到特定位置。所以我认为我们需要知道你真正想要实现什么,而不是你提出的实现方法。
您无需知道节点的位置即可在节点之后(或之前(插入另一个节点。在给定的示例中,您可以使用:
XSLT
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="tag3">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
<tag4>d</tag4>
</xsl:template>
</xsl:stylesheet>
要返回:
<?xml version="1.0" encoding="UTF-8"?>
<Begin>
<tag1>g</tag1>
<tag2>b</tag2>
<tag3>c</tag3>
<tag4>d</tag4>
<tag5>e</tag5>
</Begin>
当然,如果提供的输入中没有tag3
元素,则不会发生任何事情。如果有几个,每个元素之后都会插入新元素。
就像我的评论中提到的,与 @michael.hor257k 的答案非常相似,而不是检查位置,只需将您的匹配更改为 Begin[not(tag4)]/tag3
,然后输出tag3
和新tag4
......
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Begin[not(tag4)]/tag3">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
<tag4>d</tag4>
</xsl:template>
</xsl:stylesheet>
嗨@DanielHaley- :)这确实有效。但只是好奇..我们怎么能 找到 tag3 w.r.t 开始的位置?
如果您使用的是 XSLT 2.0,则可以只使用 <xsl:number select="tag3" count="*"/>
(1.0 不允许在 xsl:number 上使用 select
元素(。
在 1.0 中,您可以使用使用 xsl:number
或 count(preceding-sibling::*)
的模式模板(如 @michael-kay 建议的那样(...
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Begin[not(tag4)]">
<xsl:copy>
<!-- Need to find the position of /Begin/tag3" here -->
<xsl:apply-templates select="tag3" mode="getPos"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*" mode="getPos">
<xsl:number count="*"/>
<!-- alternative to xsl:number:
<xsl:value-of select="count(preceding-sibling::*) + 1"/>
-->
</xsl:template>
</xsl:stylesheet>
输出将是:
<Begin>3</Begin>