2011-03-16 102 views
0

嗨我有一個像xml結構樹...我想使用XSLT來轉換它來計算productPrices ...如果它是一個線性結構我可以使用一個簡單的sum函數與一個名稱上的過濾器...但是,因爲它像結構樹一樣需要某種遞歸轉換......有人可以建議我使用一些技術或方法來完成這種轉換......我試圖從我的結尾寫下它......它會如果你可以建議一些方法,請幫助...需要一個XSLT轉換

<?xml version="1.0" encoding="UTF-8"?> 
<Products> 
    <Product> 
     <Name>X2</Name> 
     <Price>1</Price> 
     <Product> 
      <Name>X1</Name> 
      <Price>1</Price> 
      <Product> 
       <Name>X1</Name> 
       <Price>1</Price> 
      </Product> 
      <Product> 
       <Name>X2</Name> 
       <Price>1</Price> 
      </Product> 
     </Product> 
     <Product> 
      <Name>X2</Name> 
      <Price>1</Price> 
      <Product> 
       <Name>X1</Name> 
       <Price>1</Price> 
      </Product> 
      <Product> 
       <Name>X1</Name> 
       <Price>1</Price> 
       <Product> 
        <Name>X2</Name> 
        <Price>1</Price> 
       </Product> 
      </Product> 
     </Product> 
    </Product> 
    <Description> 
     <text>dsd</text> 
    </Description> 
    <Description> 
     <text>dsd</text> 
    </Description> 
</Products> 

我需要它的最終結構。

<?xml version="1.0" encoding="UTF-8"?> 
<Products> 
    <Product> 
     <Name>X2</Name> 
     <Price>1</Price> 
     <!--Total Price of X2 Products--> 
     <TotalPrice>4</TotalPrice> 
     <Product> 
      <Name>X1</Name> 
      <Price>1</Price> 
      <!--Total Price of X1 Products--> 
      <TotalPrice>4</TotalPrice> 
      <Product> 
       <Name>X1</Name> 
       <Price>1</Price> 
       <!--Total Price of X1 Products--> 
       <TotalPrice>4</TotalPrice> 
      </Product> 
      <Product> 
       <Name>X2</Name> 
       <Price>1</Price> 
       <!--Total Price of X2 Products--> 
       <TotalPrice>4</TotalPrice> 
      </Product> 
     </Product> 
     <Product> 
      <Name>X2</Name> 
      <Price>1</Price> 
      <!--Total Price of X2 Products--> 
      <TotalPrice>4</TotalPrice> 
      <Product> 
       <Name>X1</Name> 
       <Price>1</Price> 
       <!--Total Price of X1 Products--> 
       <TotalPrice>4</TotalPrice> 
      </Product> 
      <Product> 
       <Name>X1</Name> 
       <Price>1</Price> 
       <!--Total Price of X1 Products--> 
       <TotalPrice>4</TotalPrice> 
       <Product> 
        <Name>X2</Name> 
        <Price>1</Price> 
        <!--Total Price of X2 Products--> 
        <TotalPrice>4</TotalPrice> 
       </Product> 
      </Product> 
     </Product> 
    </Product> 
    <Description> 
     <text>dsd</text> 
    </Description> 
    <Description> 
     <text>dsd</text> 
    </Description> 
</Products> 
+0

@bejoy:我可以提出一點改革嗎?您可以將'Name'和'Price'作爲'Product'元素的屬性。使嵌套可讀並且易於迭代。 – 2011-03-16 06:56:33

+0

@conqenator:感謝您的評論,但不可修改的結構... – Joy 2011-03-16 07:17:15

+0

@bejoy:那麼你想知道什麼?在你的「需求」上面沒有問題。根據常見問題,我被迫變得很好,但讓我說這不是一個你扔東西,讓別人完成你的工作的地方。如果您對文檔進行轉換時遇到具體問題,請隨時發佈您的問題,並確保獲得一個很好的答案。 – Chris 2011-03-16 07:34:29

回答

0

好了,給你方向..

你可以寫一個模板,一個Product元素開始。使用xsl:for-each並遞歸應用相同的模板。 (查看遞歸模板)

正如您所建議的,您將需要巧妙地使用xsl:variables以及sum()函數。

3

下面是一個完整的解決方案:

<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:variable name="vProd1TotalPrice" 
    select="sum(//Product[Name='X1']/Price)"/> 

<xsl:variable name="vProd2TotalPrice" 
    select="sum(//Product[Name='X2']/Price)"/> 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="Product"> 
    <xsl:copy> 
    <xsl:apply-templates select="*[not(self::Product)]"/> 
    <TotalPrice> 
    <xsl:value-of select= 
     "$vProd1TotalPrice *(Name='X1') 
     + 
     $vProd2TotalPrice *(Name='X2') 
     "/> 
    </TotalPrice> 
    <xsl:apply-templates select="Product"/> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 

當這個變換所提供的XML文檔應用:

<Products> 
    <Product> 
     <Name>X2</Name> 
     <Price>1</Price> 
     <Product> 
      <Name>X1</Name> 
      <Price>1</Price> 
      <Product> 
       <Name>X1</Name> 
       <Price>1</Price> 
      </Product> 
      <Product> 
       <Name>X2</Name> 
       <Price>1</Price> 
      </Product> 
     </Product> 
     <Product> 
      <Name>X2</Name> 
      <Price>1</Price> 
      <Product> 
       <Name>X1</Name> 
       <Price>1</Price> 
      </Product> 
      <Product> 
       <Name>X1</Name> 
       <Price>1</Price> 
       <Product> 
        <Name>X2</Name> 
        <Price>1</Price> 
       </Product> 
      </Product> 
     </Product> 
    </Product> 
    <Description> 
     <text>dsd</text> 
    </Description> 
    <Description> 
     <text>dsd</text> 
    </Description> 
</Products> 

有用,正確的結果產生:

<Products> 
    <Product> 
     <Name>X2</Name> 
     <Price>1</Price> 
     <TotalPrice>4</TotalPrice> 
     <Product> 
     <Name>X1</Name> 
     <Price>1</Price> 
     <TotalPrice>4</TotalPrice> 
     <Product> 
      <Name>X1</Name> 
      <Price>1</Price> 
      <TotalPrice>4</TotalPrice> 
     </Product> 
     <Product> 
      <Name>X2</Name> 
      <Price>1</Price> 
      <TotalPrice>4</TotalPrice> 
     </Product> 
     </Product> 
     <Product> 
     <Name>X2</Name> 
     <Price>1</Price> 
     <TotalPrice>4</TotalPrice> 
     <Product> 
      <Name>X1</Name> 
      <Price>1</Price> 
      <TotalPrice>4</TotalPrice> 
     </Product> 
     <Product> 
      <Name>X1</Name> 
      <Price>1</Price> 
      <TotalPrice>4</TotalPrice> 
      <Product> 
       <Name>X2</Name> 
       <Price>1</Price> 
       <TotalPrice>4</TotalPrice> 
      </Product> 
     </Product> 
     </Product> 
    </Product> 
    <Description> 
     <text>dsd</text> 
    </Description> 
    <Description> 
     <text>dsd</text> 
    </Description> 
</Products> 

說明

這是直截了當的,以指定在一個單一的XPath表達式Price元件的所需金額作爲代碼定義兩個全局變量時完成。

沒有遞歸是必要的。

+0

Excellant Dimitre ...非常感謝...我對它進行了一點修改,使其成爲通用...您是救星...再次感謝... – Joy 2011-03-16 13:41:28

+0

@bejoy:不客氣。 – 2011-03-16 13:43:56

+0

@bejoy,那麼你必須接受答案。 – Flack 2011-03-17 06:59:36

0

再次感謝Dimitre ......我修改了XSLT,使其一點點通用...現在它看起來像這樣...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" encoding="UTF-16" indent="yes"/> 
    <xsl:strip-space elements="*"/> 
    <xsl:template match="node()|@*"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="Product"> 
    <xsl:variable name="ProductLine" select="."/> 
     <xsl:copy> 
      <xsl:apply-templates select="*[not(self::Product)]"/> 
      <TotalPrice> 
       <xsl:value-of select="sum(//Product[Name=$ProductLine/Name]/Price)"/> 
      </TotalPrice> 
      <xsl:apply-templates select="Product"/> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

所以,如果我給一個修改後的XML如下。

<?xml version="1.0" encoding="UTF-8"?> 
<Products> 
    <Product> 
     <Name>X2</Name> 
     <Price>1</Price> 
     <Product> 
      <Name>X1</Name> 
      <Price>1</Price> 
      <Product> 
       <Name>X1</Name> 
       <Price>1</Price> 
      </Product> 
      <Product> 
       <Name>X3</Name> 
       <Price>1</Price> 
      </Product> 
     </Product> 
     <Product> 
      <Name>X2</Name> 
      <Price>1</Price> 
      <Product> 
       <Name>X3</Name> 
       <Price>1</Price> 
      </Product> 
      <Product> 
       <Name>X1</Name> 
       <Price>1</Price> 
       <Product> 
        <Name>X2</Name> 
        <Price>1</Price> 
       </Product> 
      </Product> 
     </Product> 
    </Product> 
    <Description> 
     <text>dsd</text> 
    </Description> 
    <Description> 
     <text>dsd</text> 
    </Description> 
</Products> 

它仍然給我的輸出如下。

<?xml version="1.0" encoding="UTF-16"?> 
<Products> 
    <Product> 
     <Name>X2</Name> 
     <Price>1</Price> 
     <TotalPrice>3</TotalPrice> 
     <Product> 
      <Name>X1</Name> 
      <Price>1</Price> 
      <TotalPrice>3</TotalPrice> 
      <Product> 
       <Name>X1</Name> 
       <Price>1</Price> 
       <TotalPrice>3</TotalPrice> 
      </Product> 
      <Product> 
       <Name>X3</Name> 
       <Price>1</Price> 
       <TotalPrice>2</TotalPrice> 
      </Product> 
     </Product> 
     <Product> 
      <Name>X2</Name> 
      <Price>1</Price> 
      <TotalPrice>3</TotalPrice> 
      <Product> 
       <Name>X3</Name> 
       <Price>1</Price> 
       <TotalPrice>2</TotalPrice> 
      </Product> 
      <Product> 
       <Name>X1</Name> 
       <Price>1</Price> 
       <TotalPrice>3</TotalPrice> 
       <Product> 
        <Name>X2</Name> 
        <Price>1</Price> 
        <TotalPrice>3</TotalPrice> 
       </Product> 
      </Product> 
     </Product> 
    </Product> 
    <Description> 
     <text>dsd</text> 
    </Description> 
    <Description> 
     <text>dsd</text> 
    </Description> 
</Products> 

#1和這裏的專家們真棒......再次感謝!

+0

由於'$ ProductLine/Name'是無環境的,因此您可以將'$ ProductName'聲明爲'Name'而不是'$ ProductLine'作爲'.' – 2011-03-16 17:54:58