聚合属性值和复制整个XML结构的问题

时间:2016-01-11 10:31:20

标签: xml xslt xslt-1.0

我有以下XML文档:

<PrintOut>
<Header DateCreated="20010101" Status="1" />
<CalcInfo NetPrice="30222" DiscountPercent="0.05"  />
<OrderRows>
    <OrderRow RowID="11297" NbrOf="1">
        <RowCalcInfo GrossProfit="33.01" ListPrice="1555"/>
        <OrderSettings>
            <OrderSetting ParameterValue="1"/>
            <OrderSetting ParameterValue="2"/>
        </OrderSettings>
        <Components>
            <ComponentData>
                <Component ComponentID="AAAAA" SortOrder="33"></Component>
                <Properties>
                    <Property FamilyID="Saftey" PropertyID="internal" PropertyValue="60.00"></Property>
                </Properties>                   
            </ComponentData>
            <ComponentData>
                 <Component ComponentID="aaaa" SortOrder="44"></Component>
                <Properties>
                    <Property FamilyID="Saftey" PropertyID="costprice1" PropertyValue="100.00"></Property>
                </Properties>
            </ComponentData>
            <ComponentData>
                 <Component ComponentID="BBBB" SortOrder="22"></Component>
                <Properties>
                    <Property FamilyID="Saftey" PropertyID="costprice1" PropertyValue="101.00"></Property>
                </Properties>
            </ComponentData>
        </Components>
    </OrderRow>
    <OrderRow RowID="11298"  NbrOf="1">
        <RowCalcInfo GrossProfit="33.02" ListPrice="1666"/>
        <OrderSettings>
            <OrderSetting ParameterValue="1"/>
            <OrderSetting ParameterValue="2"/>
        </OrderSettings>
        <Components>
            <ComponentData>
                <Component ComponentID="CCCCC" SortOrder="11"></Component>
                <Properties>
                    <Property FamilyID="Saftey" PropertyID="pricecost" PropertyValue="5.00"></Property>
                </Properties>
            </ComponentData>
        </Components>
    </OrderRow>
    <OrderRow RowID="11299" NbrOf="1">
        <RowCalcInfo GrossProfit="33.03" ListPrice="1777"/>
        <OrderSettings>
            <OrderSetting ParameterValue="1"/>
            <OrderSetting ParameterValue="2"/>
        </OrderSettings>
        <Components>
            <ComponentData>
                 <Component ComponentID="DDDDD" SortOrder="00"></Component>
                <Properties>
                    <Property FamilyID="Saftey" PropertyID="costprice1" PropertyValue="105.00"></Property>
                    <Property FamilyID="Saftey-Restriction" PropertyID="costprice1" PropertyValue="20000"></Property>
                </Properties>
            </ComponentData>
        </Components>
    </OrderRow>
    <OrderRow RowID="11300" NbrOf="1">
        <RowCalcInfo GrossProfit="33.04" ListPrice="1888"/>
        <OrderSettings>
            <OrderSetting ParameterValue="1"/>
            <OrderSetting ParameterValue="2"/>
        </OrderSettings>
        <Components>
            <ComponentData>
                 <Component ComponentID="EEEEE" SortOrder="-1"></Component>
                <Properties>
                    <Property FamilyID="Saftey" PropertyID="costprice1" PropertyValue="75.00"></Property>
                    <Property FamilyID="Saftey" PropertyID="internalprice" PropertyValue="270.00"></Property>
                </Properties>
            </ComponentData>
        </Components>
    </OrderRow>
    <OrderRow RowID="11301" NbrOf="1">
        <RowCalcInfo GrossProfit="33.05" ListPrice="0"/>
        <OrderSettings>
            <OrderSetting ParameterValue="1"/>
            <OrderSetting ParameterValue="2"/>
        </OrderSettings>
            <Components>
                <ComponentData>
                <Component ComponentID="FFFFF" SortOrder="-2"></Component>
                <Properties>
                    <Property FamilyID="Saftey" PropertyID="internalprice" PropertyValue="70.00"></Property>
                </Properties>
            </ComponentData>
        </Components>
    </OrderRow>
</OrderRows>
</PrintOut>

对于每个OrderRow,我想分组和汇总唯一的PropertyID的属性值(在element属性中找到)。每个PropertyID的PropertyValue的总数应该在元素OrderRow中创建为新属性,包括后缀&#34; _Sum&#34;。 解决方案应该能够提前处理PropertyID未知。 我正在寻找的是这样的:

    <PrintOut>
    <Header DateCreated="20010101" Status="1" />
    <CalcInfo NetPrice="30222" DiscountPercent="0.05"  />
    <OrderRows>
        <OrderRow RowID="11297" NbrOf="1" internal_Sum="60.00" costprice1_Sum="201.00">
            <RowCalcInfo GrossProfit="33.01" ListPrice="1555"/>
            <OrderSettings>
                <OrderSetting ParameterValue="1"/>
                <OrderSetting ParameterValue="2"/>
            </OrderSettings>
            <Components>
                <ComponentData>
                    <Component ComponentID="AAAAA" SortOrder="33"></Component>
                    <Properties>
                        <Property FamilyID="Saftey" PropertyID="internal" PropertyValue="60.00"></Property>
                    </Properties>                   
                </ComponentData>
                <ComponentData>
                     <Component ComponentID="aaaa" SortOrder="44"></Component>
                    <Properties>
                        <Property FamilyID="Saftey" PropertyID="costprice1" PropertyValue="100.00"></Property>
                    </Properties>
                </ComponentData>
                <ComponentData>
                     <Component ComponentID="BBBB" SortOrder="22"></Component>
                    <Properties>
                        <Property FamilyID="Saftey" PropertyID="costprice1" PropertyValue="101.00"></Property>
                    </Properties>
                </ComponentData>
            </Components>
        </OrderRow>
        <OrderRow RowID="11298"  NbrOf="1" pricecost_Sum="5.00">
            <RowCalcInfo GrossProfit="33.02" ListPrice="1666"/>
            <OrderSettings>
                <OrderSetting ParameterValue="1"/>
                <OrderSetting ParameterValue="2"/>
            </OrderSettings>
            <Components>
                <ComponentData>
                    <Component ComponentID="CCCCC" SortOrder="11"></Component>
                    <Properties>
                        <Property FamilyID="Saftey" PropertyID="pricecost" PropertyValue="5.00"></Property>
                    </Properties>
                </ComponentData>
            </Components>
        </OrderRow>
        <OrderRow RowID="11299" NbrOf="1" costprice1_Sum="20105.00">
            <RowCalcInfo GrossProfit="33.03" ListPrice="1777"/>
            <OrderSettings>
                <OrderSetting ParameterValue="1"/>
                <OrderSetting ParameterValue="2"/>
            </OrderSettings>
            <Components>
                <ComponentData>
                     <Component ComponentID="DDDDD" SortOrder="00"></Component>
                    <Properties>
                        <Property FamilyID="Saftey" PropertyID="costprice1" PropertyValue="105.00"></Property>
                        <Property FamilyID="Saftey-Restriction" PropertyID="costprice1" PropertyValue="20000.00"></Property>
                    </Properties>
                </ComponentData>
            </Components>
        </OrderRow>
        <OrderRow RowID="11300" NbrOf="1" costprice1_Sum="75.00" internalprice_Sum="270.00" >
            <RowCalcInfo GrossProfit="33.04" ListPrice="1888"/>
            <OrderSettings>
                <OrderSetting ParameterValue="1"/>
                <OrderSetting ParameterValue="2"/>
            </OrderSettings>
            <Components>
                <ComponentData>
                     <Component ComponentID="EEEEE" SortOrder="-1"></Component>
                    <Properties>
                        <Property FamilyID="Saftey" PropertyID="costprice1" PropertyValue="75.00"></Property>
                        <Property FamilyID="Saftey" PropertyID="internalprice" PropertyValue="270.00"></Property>
                    </Properties>
                </ComponentData>
            </Components>
        </OrderRow>
        <OrderRow RowID="11301" NbrOf="1">
            <RowCalcInfo GrossProfit="33.05" ListPrice="0"/>
            <OrderSettings>
                <OrderSetting ParameterValue="1"/>
                <OrderSetting ParameterValue="2"/>
            </OrderSettings>
                <Components>
                    <ComponentData>
                    <Component ComponentID="FFFFF" SortOrder="-2"></Component>
                    <Properties>
                        <Property FamilyID="Saftey" PropertyID="internalprice" PropertyValue="70.00"></Property>
                    </Properties>
                </ComponentData>
            </Components>
        </OrderRow>
    </OrderRows>
</PrintOut>

在这个例子中,我要总结的PropertyID是内部,costprice1,pricecost和internalprice。 我几乎得到了一个解决方案,我的xslt但不完全,因为摘要也最终作为元素属性的属性,可能不是XML文档的整个结构。我的XSLT:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>

    <xsl:key name="currency-key"
             match="/PrintOut/OrderRows/OrderRow/Components/ComponentData/Properties/Property"
             use="@PropertyID" />
<xsl:template match="node()|@*">
   <xsl:copy>
    <xsl:apply-templates select="node()|@*"/>
   </xsl:copy>
 </xsl:template>

    <xsl:template match="OrderRow">
        <xsl:copy>
            <xsl:apply-templates select="Components/ComponentData/Properties/Property[generate-id() = generate-id(key('currency-key', @PropertyID)[1])]" />
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Property">
        <xsl:attribute name="{concat(@PropertyID, '_Sum')}">
            <xsl:value-of select="sum(key('currency-key', @PropertyID)/@PropertyValue)" />
       </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

解决方案应该是XSLT 1.0版(但是,我也很好奇2.0版本的解决方案) 有人对此有所了解吗?

1 个答案:

答案 0 :(得分:0)

这样的事情对你有用吗?

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="property" match="Property" use="concat(@PropertyID, ancestor::OrderRow/@RowID)" />

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

<xsl:template match="OrderRow">
    <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:for-each select="Components/ComponentData/Properties/Property[generate-id()=generate-id(key('property', concat(@PropertyID, ancestor::OrderRow/@RowID))[1])]">
            <xsl:attribute name="{@PropertyID}_Sum">
                <xsl:value-of select="sum(key('property', concat(@PropertyID, ancestor::OrderRow/@RowID))/@PropertyValue)" />
            </xsl:attribute>
        </xsl:for-each>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

当应用于您的输入时,结果将是:

<?xml version="1.0" encoding="UTF-8"?>
<PrintOut>
   <Header DateCreated="20010101" Status="1"/>
   <CalcInfo NetPrice="30222" DiscountPercent="0.05"/>
   <OrderRows>
      <OrderRow RowID="11297" NbrOf="1" internal_Sum="60" costprice1_Sum="201">
         <RowCalcInfo GrossProfit="33.01" ListPrice="1555"/>
         <OrderSettings>
            <OrderSetting ParameterValue="1"/>
            <OrderSetting ParameterValue="2"/>
         </OrderSettings>
         <Components>
            <ComponentData>
               <Component ComponentID="AAAAA" SortOrder="33"/>
               <Properties>
                  <Property FamilyID="Saftey" PropertyID="internal" PropertyValue="60.00"/>
               </Properties>
            </ComponentData>
            <ComponentData>
               <Component ComponentID="aaaa" SortOrder="44"/>
               <Properties>
                  <Property FamilyID="Saftey" PropertyID="costprice1" PropertyValue="100.00"/>
               </Properties>
            </ComponentData>
            <ComponentData>
               <Component ComponentID="BBBB" SortOrder="22"/>
               <Properties>
                  <Property FamilyID="Saftey" PropertyID="costprice1" PropertyValue="101.00"/>
               </Properties>
            </ComponentData>
         </Components>
      </OrderRow>
      <OrderRow RowID="11298" NbrOf="1" pricecost_Sum="5">
         <RowCalcInfo GrossProfit="33.02" ListPrice="1666"/>
         <OrderSettings>
            <OrderSetting ParameterValue="1"/>
            <OrderSetting ParameterValue="2"/>
         </OrderSettings>
         <Components>
            <ComponentData>
               <Component ComponentID="CCCCC" SortOrder="11"/>
               <Properties>
                  <Property FamilyID="Saftey" PropertyID="pricecost" PropertyValue="5.00"/>
               </Properties>
            </ComponentData>
         </Components>
      </OrderRow>
      <OrderRow RowID="11299" NbrOf="1" costprice1_Sum="20105">
         <RowCalcInfo GrossProfit="33.03" ListPrice="1777"/>
         <OrderSettings>
            <OrderSetting ParameterValue="1"/>
            <OrderSetting ParameterValue="2"/>
         </OrderSettings>
         <Components>
            <ComponentData>
               <Component ComponentID="DDDDD" SortOrder="00"/>
               <Properties>
                  <Property FamilyID="Saftey" PropertyID="costprice1" PropertyValue="105.00"/>
                  <Property FamilyID="Saftey-Restriction" PropertyID="costprice1" PropertyValue="20000"/>
               </Properties>
            </ComponentData>
         </Components>
      </OrderRow>
      <OrderRow RowID="11300" NbrOf="1" costprice1_Sum="75" internalprice_Sum="270">
         <RowCalcInfo GrossProfit="33.04" ListPrice="1888"/>
         <OrderSettings>
            <OrderSetting ParameterValue="1"/>
            <OrderSetting ParameterValue="2"/>
         </OrderSettings>
         <Components>
            <ComponentData>
               <Component ComponentID="EEEEE" SortOrder="-1"/>
               <Properties>
                  <Property FamilyID="Saftey" PropertyID="costprice1" PropertyValue="75.00"/>
                  <Property FamilyID="Saftey" PropertyID="internalprice" PropertyValue="270.00"/>
               </Properties>
            </ComponentData>
         </Components>
      </OrderRow>
      <OrderRow RowID="11301" NbrOf="1" internalprice_Sum="70">
         <RowCalcInfo GrossProfit="33.05" ListPrice="0"/>
         <OrderSettings>
            <OrderSetting ParameterValue="1"/>
            <OrderSetting ParameterValue="2"/>
         </OrderSettings>
         <Components>
            <ComponentData>
               <Component ComponentID="FFFFF" SortOrder="-2"/>
               <Properties>
                  <Property FamilyID="Saftey" PropertyID="internalprice" PropertyValue="70.00"/>
               </Properties>
            </ComponentData>
         </Components>
      </OrderRow>
   </OrderRows>
</PrintOut>

在XSLT 2.0中,您将使用xsl:for-each-group进行分组,而不是使用Muenchian方法。