我有一个包含id的元素的xml属性,其中一些id可能会出现多次。在这种情况下,我想将_copy附加到除了具有该id的第一个元素之外的所有元素。
所以我的xml文件如下所示:
<elems>
<elem id="123"/>
<elem id="2832"/>
<elem id="2272"/>
<elem id="123"/>
<elem id="123"/>
</elems>
期望的输出:
<elems>
<elem id="123"/>
<elem id="2832"/>
<elem id="2272"/>
<elem id="123_copy"/>
<elem id="123_copy"/>
</elems>
最好的方法是什么?我正在考虑将文档读入变量,然后检查id是否出现多次......
感谢您的帮助和提示!
答案 0 :(得分:3)
这个XSLT会解决你的问题:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="element" match="elem" use="@id"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@*, node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="elem[count(key('element', @id)[1] | .) = 2]">
<elem id="{concat(@id, '_copy')}"/>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:2)
我会键入属性本身并使用XPath 2.0 is
运算符编写条件:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:param name="marker" select="'_copy'"/>
<xsl:key name="id" match="@id" use="."/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* , node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@id[not(. is key('id', .)[1])]">
<xsl:attribute name="{name()}" select="concat(., $marker)"/>
</xsl:template>
</xsl:stylesheet>
答案 2 :(得分:2)
我刚试过for-each-group。我如何附加&#34; _copy&#34;?
怎么样:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/elems">
<xsl:copy>
<xsl:for-each-group select="elem" group-by="@id">
<xsl:for-each select="current-group()">
<elem id="{@id}{if(position() gt 1) then '_copy' else ''}"/>
</xsl:for-each>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>