我在示例xslt上有这个代码,我无法准确地完成这部分。我想了解这部分seq_no[/*/*/seq_no[@num = following::seq_no/@num]]
。有什么想法吗?
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="seq_no[/*/*/seq_no[@num = following::seq_no/@num]]">
<seq_no num="[{count(preceding::seq_no)+1}]{.}">
<xsl:apply-templates/>
</seq_no>
</xsl:template>
</xsl:stylesheet>
这是输入
<xml>
<staff>
<seq_no num="0">0</seq_no>
<name>xyz</name>
</staff>
<staff>
<seq_no num="1">1</seq_no>
<name>xyz</name>
</staff>
<staff>
<seq_no num="1">2</seq_no>
<name>abc</name>
</staff>
<staff>
<seq_no num="3">3</seq_no>
<name>abc</name>
</staff>
</xml>
这是输出
<xml>
<staff>
<seq_no num="[1]0">0</seq_no>
<name>xyz</name>
</staff>
<staff>
<seq_no num="[2]1">1</seq_no>
<name>xyz</name>
</staff>
<staff>
<seq_no num="[3]2">2</seq_no>
<name>abc</name>
</staff>
<staff>
<seq_no num="[4]3">3</seq_no>
<name>abc</name>
</staff>
</xml>
答案 0 :(得分:2)
您正试图理解表达式seq_no[/*/*/seq_no[@num = following::seq_no/@num]]
。它有助于将其分解为单独的部分。请考虑以下事项:
/*/*/seq_no
因为此表达式以/
开头,所以这是一个绝对路径,并且将匹配文档中的任何 seq_no 元素,该元素是XML的根元素的子元素。您可以使用以下xpath表达式对其进行量化:
[@num = following::seq_no/@num]
因此,它正在寻找 seq_no 元素,其 num 属性与文档中跟随它的另一个 seq_no 元素具有相同的值。即它是否在XML中进一步具有重复属性。
但这是一个绝对路径,这意味着它与你匹配的 seq_no 无关。因此,如果文档中的任何位置确实存在重复,则表达式[/*/*/seq_no[@num = following::seq_no/@num]
将返回true,因此您的模板将匹配文档中的所有 seq_no 元素。
请注意,这不是很有效,因为您正在评估文档中每个 seq_no 元素的表达式,即使它对所有元素始终具有相同的值。将其作为变量进行一次评估可能会更好一些,然后在模板匹配中使用 xsl:choose 来确定是否需要更新属性值。
试试这个XSLT,例如
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="duplicate" select="/*/*/seq_no[@num = following::seq_no/@num]"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="seq_no/@num">
<xsl:choose>
<xsl:when test="$duplicate">
<xsl:attribute name="num">
<xsl:number count="seq_no" level="any"/>
<xsl:value-of select="concat('[', ., ']')"/>
</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:copy/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
注意我已经更改了模板以匹配 num 属性,因为这是您实际转换的XML的唯一部分。另外,我也使用 xsl:number 进行计数。