带密钥的XSLT 1.0多级分组

时间:2016-04-13 14:39:09

标签: xml xslt xslt-1.0 grouping

我正在尝试从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的总和。

然后为每个Office和Job执行相同的操作。工作不会很难,也不需要分组。

我将其输出为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>

不完全是我想要的。相同的ProductNames应该相加。

1 个答案:

答案 0 :(得分:0)

如果可以将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>

为乔布斯做上面的事情