需要 XSLT 转换

发布于 2024-10-22 19:56:07 字数 3849 浏览 2 评论 0原文

嗨,我有一个类似 xml 结构的树...我想使用 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>

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

滥情哥ㄟ 2024-10-29 19:56:08

再次感谢 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 和这里的专家都很棒...再次感谢!

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!

乱世争霸 2024-10-29 19:56:07

这是一个完整的解决方案:

<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 元素总和非常简单,就像定义两个全局变量时的代码中所做的那样。

不需要递归。

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.

戴着白色围巾的女孩 2024-10-29 19:56:07

好吧,为您提供指导......

您可以从为 Product 元素编写模板开始。

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文