我需要根据属性值合并某些xml节点,在合并节点上更改该属性值并对另一个属性求和。
我可以更改属性的值,但我无法弄清楚如何求和(@count)并将其分配给生成的xml上的@count
来源xml
<xml>
<books category="X" count="2">
<book name="bookx1"/>
<book name="bookx2"/>
</books>
<books category="Y" count="3">
<book name="booky1"/>
<book name="booky2"/>
<book name="booky3"/>
</books>
<books category="Z" count="2">
<book name="bookz1"/>
<book name="bookz2"/>
</books></xml>
xslt转换后,它需要像这样
<xml>
<books category="A" count="5">
<book name="bookx1"/>
<book name="bookx2"/>
<book name="booky1"/>
<book name="booky2"/>
<book name="booky3"/>
</books>
<books category="Z" count="2">
<book name="bookz1"/>
<book name="bookz2"/>
</books></xml>
这是我的部分xslt
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="@*">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="@category">
<xsl:attribute name="category">
<xsl:choose>
<xsl:when test=".='X'">
<xsl:text>A</xsl:text>
</xsl:when>
<xsl:when test=".='Y'">
<xsl:text>A</xsl:text>
</xsl:when>
<xsl:when test=".='Z'">
<xsl:text>B</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:template>
<xsl:template match="books[@category='X']"/>
<xsl:template match="books[@category='Y']"/></xsl:transform>
答案 0 :(得分:1)
此转化:
<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:key name="kBooksByCat" match="books"
use="@category = 'Z'"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<xml>
<xsl:variable name="vNonZ"
select="key('kBooksByCat', 'false')"/>
<xsl:variable name="vCatZ"
select="key('kBooksByCat', 'true')"/>
<xsl:if test="$vNonZ">
<books category="A" count="{sum($vNonZ/@count)}">
<xsl:apply-templates select="$vNonZ/node()"/>
</books>
</xsl:if>
<xsl:if test="$vCatZ">
<books category="B" count="{sum($vCatZ/@count)}">
<xsl:apply-templates select="$vCatZ/node()"/>
</books>
</xsl:if>
</xml>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档:
<xml>
<books category="X" count="2">
<book name="bookx1"/>
<book name="bookx2"/>
</books>
<books category="Y" count="3">
<book name="booky1"/>
<book name="booky2"/>
<book name="booky3"/>
</books>
<books category="Z" count="2">
<book name="bookz1"/>
<book name="bookz2"/>
</books>
</xml>
生成想要的正确结果:
<xml>
<books category="A" count="5">
<book name="bookx1"/>
<book name="bookx2"/>
<book name="booky1"/>
<book name="booky2"/>
<book name="booky3"/>
</books>
<books category="B" count="2">
<book name="bookz1"/>
<book name="bookz2"/>
</books>
</xml>
答案 1 :(得分:0)
另一个没有键的样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="books[@category='Z'][1]">
<xsl:variable name="us" select="../books[@category='Z']"/>
<books category="B" count="{sum($us/@count)}">
<xsl:apply-templates select="$us/node()"/>
</books>
</xsl:template>
<xsl:template match="books[@category!='Z'][1]">
<xsl:variable name="us" select="../books[@category!='Z']"/>
<books category="A" count="{sum($us/@count)}">
<xsl:apply-templates select="$us/node()"/>
</books>
</xsl:template>
<xsl:template match="books"/>
</xsl:stylesheet>
输出:
<xml>
<books category="A" count="5">
<book name="bookx1"></book>
<book name="bookx2"></book>
<book name="booky1"></book>
<book name="booky2"></book>
<book name="booky3"></book>
</books>
<books category="B" count="2">
<book name="bookz1"></book>
<book name="bookz2"></book>
</books>
</xml>
注意:只是为了好玩。这两本书的模板非常接近。也许有办法在一个模板中表达这些。一些复杂的translate
?