2011-03-16 65 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