开发者

Need an XSLT transformation

开发者 https://www.devze.com 2023-02-17 06:39 出处:网络
Hi I have a tree like xml structure... I want to transform it using XSLT to calculate productPrices...if it was a linear structure I could have used a simple sum function witha a filter on name...But

Hi I have a tree like xml structure... I want to transform it using XSLT to calculate productPrices...if it was a linear structure I could have used a simple sum function witha a filter on name...But as its a tree like structure it needs some kind of recursive transformation...Can somebody suggest me some technique or an approach to do this tranformation...I am trying to write it from my end...It would be helpfull if you can suggest some approaches...

<?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>
              开发者_JAVA技巧  <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>

The final structure that I need it to be.

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


Here is a complete solution:

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

when this transformation is applied on the provided XML document:

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

the wanted, correct result is produced:

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

Explanation:

It is straight-forward to specify the required sum of Price elements in a single XPath expression as done in the code when defining the two global variables.

No recursion is necessary.


Well, to give you direction..

You could start off by writing a template for a Product element.

Use the xsl:for-each and recursively apply the same template. (check out recursive templates)

And as you suggested, you will need to use xsl:variables smartly alongwith the sum() function.


Thanks Again Dimitre...I modified the xslt to make it a little generic...now it looks like this...

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

So if I give a modified xml as below.

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

It still gives me the output as below.

<?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 and the experts here are awesome...Thanks again!

0

精彩评论

暂无评论...
验证码 换一张
取 消