2010-07-30 48 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