需要XSLT转换

时间:2011-03-16 06:51:48

标签: xml xslt tree

嗨我有一个像xml结构的树......我想用XSLT来转换它来计算productPrices ...如果它是一个线性结构我可以使用一个简单的求和函数,名字上有一个过滤器......但是作为一个树状结构,它需要某种递归转换...有人可以建议我做一些技术或方法来进行这种转换...我试图从我的结尾写出它...如果你有帮助可以提出一些方法......

<?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>

3 个答案:

答案 0 :(得分: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元素总和是直截了当的。

不需要递归。

答案 1 :(得分:0)

好吧,给你指路..

您可以先为Product元素编写模板。

使用xsl:for-each并递归应用相同的模板。 (查看递归模板)

正如您所建议的那样,您需要巧妙地使用xsl:variables sum()功能。

答案 2 :(得分: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>

Stackoverflow和这里的专家很棒......再次感谢!