【问题标题】:XSLT 1.0 Multi-Level Grouping with KeysXSLT 1.0 带键的多级分组
【发布时间】:2016-04-13 14:39:09
【问题描述】:

我正在尝试从 AWS 分配文件生成报告。我已将适当的数据从 CSV 转换为 XML,但无法完全弄清楚如何在 XSLT 1.0 (.net) 中进行键/分组

这是 XML 文件。

<?xml version="1.0" encoding="utf-16"?>
<AWS>
    <BusinessUnit>
        <Name>BBII Western</Name>
        <Office>
            <Name>Fairfield</Name>
            <Job>
                <JobNumber>OH4299</JobNumber>
                <Phase> 35</Phase>
                <CostCode> 74500</CostCode>
                <Costs>
                    <Cost>
                        <ProductName>AWS Storage Gateway</ProductName>
                        <UsageQuantity>558.6793022</UsageQuantity>
                        <TotalCost>16.760536</TotalCost>
                    </Cost>
                    <Cost>
                        <ProductName>AWS Storage Gateway</ProductName>
                        <UsageQuantity>0.99999986</UsageQuantity>
                        <TotalCost>124.999981</TotalCost>
                    </Cost>
                </Costs>
            </Job>
        </Office>
        <Office>
            <Name>Riconanda</Name>
            <Job>
                <JobNumber>4228</JobNumber>
                <Phase> 92</Phase>
                <CostCode> 92110</CostCode>
                <Costs>
                    <Cost>
                        <ProductName>AWS Storage Gateway</ProductName>
                        <UsageQuantity>63.92940319</UsageQuantity>
                        <TotalCost>1.9179</TotalCost>
                    </Cost>
                    <Cost>
                        <ProductName>AWS Storage Gateway</ProductName>
                        <UsageQuantity>0.99999986</UsageQuantity>
                        <TotalCost>124.999981</TotalCost>
                    </Cost>
                </Costs>
            </Job>
        </Office>
    </BusinessUnit>
    <BusinessUnit>
        <Name>None</Name>
        <Office>
            <Name>None</Name>
            <Job>
                <JobNumber>None</JobNumber>
                <Phase> </Phase>
                <CostCode> </CostCode>
                <Costs>
                    <Cost>
                        <ProductName>AWS Storage Gateway</ProductName>
                        <UsageQuantity>0.33271862</UsageQuantity>
                        <TotalCost>0.009982</TotalCost>
                    </Cost>
                    <Cost>
                        <ProductName>Amazon Elastic Compute Cloud</ProductName>
                        <UsageQuantity>1929.089098</UsageQuantity>
                        <TotalCost>183.26</TotalCost>
                    </Cost>
                    <Cost>
                        <ProductName>Amazon Elastic Compute Cloud</ProductName>
                        <UsageQuantity>4.99999976</UsageQuantity>
                        <TotalCost>0.5</TotalCost>
                    </Cost>
                </Costs>
            </Job>
        </Office>
    </BusinessUnit>
    <BusinessUnit>
        <Name>BBII Alternative Delivery</Name>
        <Office>
            <Name>Denver-Heery</Name>
            <Job>
                <JobNumber>199900</JobNumber>
                <Phase> 16</Phase>
                <CostCode> 74500</CostCode>
                <Costs>
                    <Cost>
                        <ProductName>AWS Storage Gateway</ProductName>
                        <UsageQuantity>131.2051444</UsageQuantity>
                        <TotalCost>3.936191</TotalCost>
                    </Cost>
                    <Cost>
                        <ProductName>AWS Storage Gateway</ProductName>
                        <UsageQuantity>1.00000017</UsageQuantity>
                        <TotalCost>125.000019</TotalCost>
                    </Cost>
                </Costs>
            </Job>
        </Office>
    </BusinessUnit>
    <BusinessUnit>
        <Name>Transit</Name>
        <Office>
            <Name>Denver Estimating</Name>
            <Job>
                <JobNumber>RAILOH</JobNumber>
                <Phase> N/A</Phase>
                <CostCode> 74500</CostCode>
                <Costs>
                    <Cost>
                        <ProductName>AWS Storage Gateway</ProductName>
                        <UsageQuantity>758.8392434</UsageQuantity>
                        <TotalCost>22.765391</TotalCost>
                    </Cost>
                    <Cost>
                        <ProductName>AWS Storage Gateway</ProductName>
                        <UsageQuantity>1.00000017</UsageQuantity>
                        <TotalCost>125.000019</TotalCost>
                    </Cost>
                </Costs>
            </Job>
        </Office>
    </BusinessUnit>
</AWS>

我想要做的是在业务部门级别的第一个我想要每个 ProductName 的 UsageQuantity 和 TotalCost 的总和。

然后对每个办公室和工作执行相同的操作。工作不会很难,也不需要分组。

我正在将其输出到 HTML。

对于 BusinessUnit,我尝试了几个关键配置,但似乎都没有像我预期的那样工作。

我已经尝试过(仅限 BusinessUnit 级别):

    <?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
    <xsl:output method="html" indent="yes"/>

    <xsl:key name="BU_Product" 
        match="BusinessUnit" 
        use="concat(Name, '#', Office/Job/Costs/Cost/ProductName)"/>
    <xsl:template match="AWS">
        <html>
            <head>
                <style>
                    table {
                        font-family: Verdana;
                        font-size: 9pt;
                        border-collapse: collapse;
                        table-layout: fixed                 
                    }
                    th {
                        background-color: light-blue;
                        font-weight: bold;
                        border: 1px solid black;
                    }

                    th.columnHeader {
                        text-align: center
                    }
                    th.rowHeader {
                        text-align: right;
                        padding-right: 4px;
                    }

                    td {
                    border: 1px solid black;
                    }

                    td.num {
                        text-align: right;
                        paddin-right:4px;
                    }
                </style>                
            </head>
            <body>
                <xsl:apply-templates select="BusinessUnit"/>
            </body>
        </html>
    </xsl:template>
    <xsl:template match="BusinessUnit">
        <table>
            <tr>
                <th class="columnHeader">
                    Business Unit:
                </th>
                <td colspan="2">
                    <xsl:value-of select="Name"/>
                </td>
            </tr>
            <tr>
                <th class="columnHeader">Product</th>
                <th class="columnHeader">Usage Qty</th>
                <th class="columnHeader">Cost</th>
            </tr>
            <xsl:for-each select="Office/Job/Costs/Cost[count(. | key('BU_Product',concat(Name, '#', Office/Job/Costs/Cost/ProductName))[1]) = 1]">
                <tr>
                    <th class="rowHeader">
                        <xsl:value-of select="ProductName"/>
                    </th>
                    <td class="num">
                        <xsl:value-of select="format-number(sum(UsageQuantity),'##,##0.00')"/>                  
                    </td>
                    <td class="num">
                        <xsl:value-of select="format-number(sum(TotalCost), '##,##0.00')"/>                 
                    </td>
                </tr>           
            </xsl:for-each>
        </table>
    </xsl:template>

</xsl:stylesheet>

产生这个:

    <html>
  <head>
    <META http-equiv="Content-Type" content="text/html; charset=utf-8">
    <style>
                    table {
                        font-family: Verdana;
                        font-size: 9pt;
                        border-collapse: collapse;
                        table-layout: fixed                 
                    }
                    th {
                        background-color: light-blue;
                        font-weight: bold;
                        border: 1px solid black;
                    }

                    th.columnHeader {
                        text-align: center
                    }
                    th.rowHeader {
                        text-align: right;
                        padding-right: 4px;
                    }

                    td {
                    border: 1px solid black;
                    }

                    td.num {
                        text-align: right;
                        paddin-right:4px;
                    }
                </style>
  </head>
  <body>
    <table>
      <tr>
        <th class="columnHeader">
                    Business Unit:
                </th>
        <td colspan="2">BBII Western</td>
      </tr>
      <tr>
        <th class="columnHeader">Product</th>
        <th class="columnHeader">Usage Qty</th>
        <th class="columnHeader">Cost</th>
      </tr>
      <tr>
        <th class="rowHeader">AWS Storage Gateway</th>
        <td class="num">558.68</td>
        <td class="num">16.76</td>
      </tr>
      <tr>
        <th class="rowHeader">AWS Storage Gateway</th>
        <td class="num">1.00</td>
        <td class="num">125.00</td>
      </tr>
      <tr>
        <th class="rowHeader">AWS Storage Gateway</th>
        <td class="num">63.93</td>
        <td class="num">1.92</td>
      </tr>
      <tr>
        <th class="rowHeader">AWS Storage Gateway</th>
        <td class="num">1.00</td>
        <td class="num">125.00</td>
      </tr>
    </table>
    <table>
      <tr>
        <th class="columnHeader">
                    Business Unit:
                </th>
        <td colspan="2">None</td>
      </tr>
      <tr>
        <th class="columnHeader">Product</th>
        <th class="columnHeader">Usage Qty</th>
        <th class="columnHeader">Cost</th>
      </tr>
      <tr>
        <th class="rowHeader">AWS Storage Gateway</th>
        <td class="num">0.33</td>
        <td class="num">0.01</td>
      </tr>
      <tr>
        <th class="rowHeader">Amazon Elastic Compute Cloud</th>
        <td class="num">1,929.09</td>
        <td class="num">183.26</td>
      </tr>
      <tr>
        <th class="rowHeader">Amazon Elastic Compute Cloud</th>
        <td class="num">5.00</td>
        <td class="num">0.50</td>
      </tr>
    </table>
    <table>
      <tr>
        <th class="columnHeader">
                    Business Unit:
                </th>
        <td colspan="2">BBII Alternative Delivery</td>
      </tr>
      <tr>
        <th class="columnHeader">Product</th>
        <th class="columnHeader">Usage Qty</th>
        <th class="columnHeader">Cost</th>
      </tr>
      <tr>
        <th class="rowHeader">AWS Storage Gateway</th>
        <td class="num">131.21</td>
        <td class="num">3.94</td>
      </tr>
      <tr>
        <th class="rowHeader">AWS Storage Gateway</th>
        <td class="num">1.00</td>
        <td class="num">125.00</td>
      </tr>
    </table>
    <table>
      <tr>
        <th class="columnHeader">
                    Business Unit:
                </th>
        <td colspan="2">Transit</td>
      </tr>
      <tr>
        <th class="columnHeader">Product</th>
        <th class="columnHeader">Usage Qty</th>
        <th class="columnHeader">Cost</th>
      </tr>
      <tr>
        <th class="rowHeader">AWS Storage Gateway</th>
        <td class="num">758.84</td>
        <td class="num">22.77</td>
      </tr>
      <tr>
        <th class="rowHeader">AWS Storage Gateway</th>
        <td class="num">1.00</td>
        <td class="num">125.00</td>
      </tr>
    </table>
  </body>
</html>

不是我想要的。相同的产品名称应该加在一起。

【问题讨论】:

    标签: xml xslt xslt-1.0 grouping


    【解决方案1】:

    如果您可以将 xml 和 xslt 减少到问题部分,那么提供帮助会容易得多。但无论如何,这里有一些改变建议。

    海岸产品的关键

    <xsl:key name="kProduct" 
        match="Cost" 
        use="concat(ancestor::BusinessUnit/Name, '#', ProductName)"/>
    

    BusinessUnit 中产品组的循环

     <xsl:variable name="bu" select="." />
     <xsl:for-each 
                select="Office/Job/Costs/Cost[
                count(. | key('kProduct',concat($bu/Name, '#', ProductName))[1]) = 1]">
    

    本组内的费用

    <xsl:variable name="this_pg" select="." />
    <xsl:variable name="this_pgm" 
            select="key('kProduct',concat($bu/Name, '#', $this_pg/ProductName))" />
    

    然后用这个来求和:

     <xsl:value-of select="format-number(sum($this_pgm/UsageQuantity),'##,##0.00')"/> 
    

    会是这样的:

    <xsl:template match="BusinessUnit">
    
       <!-- .. table head -->
            <xsl:variable name="bu" select="." />
            <xsl:for-each 
                select="Office/Job/Costs/Cost[
                count(. | key('kProduct',concat($bu/Name, '#', ProductName))[1]) = 1]">
               <xsl:variable name="this_pg" select="." />
               <xsl:variable name="this_pgm" 
                      select="key('kProduct',concat($bu/Name, '#', $this_pg/ProductName))" />
                <tr>
                    <th class="rowHeader">
                        <xsl:value-of select="ProductName"/>
                    </th>
                    <td class="num">
                        <xsl:value-of select="format-number(sum($this_pgm/UsageQuantity),'##,##0.00')"/>                  
                    </td>
                    <td class="num">
                        <xsl:value-of select="format-number(sum($this_pgm/TotalCost), '##,##0.00')"/>                 
                    </td>
                </tr>           
            </xsl:for-each>
        <!-- table end -->
    </xsl:template>
    

    并为 Jobs 执行上述操作

    【讨论】:

      猜你喜欢
      • 2012-12-01
      • 2021-11-20
      • 2013-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-26
      相关资源
      最近更新 更多