2010-07-30 49 views
1

我需要根据属性值合并某些xml节点,在合并的节点上更改该属性值并相加另一个属性。需要根据属性值合并xml节点

我能够改变属性的值,但我无法弄清楚如何总结(@count)并将其分配给@count上生成的XML

源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

确保缩进整个代码块,而不仅仅是第一行。 – 2010-07-30 00:19:27

+0

好问题(+1)。看到我的答案是一个简短而简单的解决方案。 :) – 2010-07-30 03:57:26

回答

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> 
+0

哇,真棒!这正是我需要的。非常感谢 – gangt 2010-07-30 17:29:25

+0

@gangt:很高兴我的回答很有用。通过接受正确的答案和/或提出有用的答案来表达对你的感激之情。 – 2010-07-30 17:43:35

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

+0

感谢你们俩。这两个xslt都像一个魅力 – gangt 2010-07-30 17:29:52