源xml文档:
<item>
<p languageCode="en">en</p>
<p languageCode="fr">fr</p>
<c languageCode="de">de</c>
<c languageCode="nl">nl</c>
</item>
转换所需的结果必须是这个xml文档:
<item>
<p pos="1">en</p>
<p pos="2">fr</p>
<c pos="1">de</c>
<c pos="2">nl</c>
</item>
使用xslt是否可以实现呢?
答案 0 :(得分:2)
在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="/item">
<xsl:copy>
<xsl:for-each-group select="*" group-adjacent="name()">
<xsl:apply-templates select="current-group()"/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="p | c">
<xsl:copy>
<xsl:attribute name="pos" select="position()"/>
<xsl:value-of select="."/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
XSLT 1.0:
<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="/*">
<item><xsl:apply-templates/></item>
</xsl:template>
<xsl:template match="/*/*">
<xsl:copy>
<xsl:attribute name="pos">
<xsl:value-of select="count(preceding-sibling::*[name()=name(current())])+1"/>
</xsl:attribute>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
XSLT 2.0 :
<xsl:stylesheet version="2.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="/*">
<item><xsl:apply-templates/></item>
</xsl:template>
<xsl:template match="/*/*">
<xsl:copy>
<xsl:attribute name="pos"
select="count(preceding-sibling::*[name()=name(current())])+1"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
另一个XSLT 2.0解决方案:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kByName" match="/*/*" use="name()"/>
<xsl:template match="/*">
<item><xsl:apply-templates/></item>
</xsl:template>
<xsl:template match="/*/*">
<xsl:copy>
<xsl:attribute name="pos"
select="index-of(key('kByName', name())/generate-id(), generate-id())"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档:
<item>
<p languageCode="en">en</p>
<p languageCode="fr">fr</p>
<c languageCode="de">de</c>
<c languageCode="nl">nl</c>
</item>
所有三个解决方案都会产生所需的正确结果:
<item>
<p pos="1">en</p>
<p pos="2">fr</p>
<c pos="1">de</c>
<c pos="2">nl</c>
</item>
请注意:
所有这些解决方案都是泛型 - 它们不依赖于名称,数量,名称数量或元素顺序。
例如,应用于以下XML文档时:
<item>
<p languageCode="en">en</p>
<p languageCode="fr">fr</p>
<c languageCode="de">de</c>
<c languageCode="nl">nl</c>
<d languageCode="es">es</d>
<d languageCode="bg">bg</d>
<d languageCode="pl">pl</d>
</item>
所有三种解决方案都能产生所需的正确结果:
<item>
<p pos="1">en</p>
<p pos="2">fr</p>
<c pos="1">de</c>
<c pos="2">nl</c>
<d pos="1">es</d>
<d pos="2">bg</d>
<d pos="3">pl</d>
</item>