2

我正在尝试将一个包罗万象的 xsl 样式表更改为两阶段样式表设置,其中 xml 在第一步中被转换为“理想”xml,第二步只是格式化。

最初,我们有这个 xml(删除了无关的部分)

<?xml-stylesheet type="text/xsl" href="xsl/storeFinancialReport.xsl" ?>
<storeFinancialReport>
  <ProductGroupEntry><ProductGroupCode>xz1</ProductGroupCode><ProductGroup>thing1</ProductGroup><Quantity>0.0000</Quantity><DiscountExcl>0.000000</DiscountExcl><SalesExcl>30.700000</SalesExcl><Sales>35.000000</Sales></ProductGroupEntry>
  <ProductGroupEntry><ProductGroupCode>xz2</ProductGroupCode><ProductGroup>thing2</ProductGroup><Quantity>13.0000</Quantity><DiscountExcl>0.000000</DiscountExcl><SalesExcl>1480.970000</SalesExcl><Sales>1688.310000</Sales></ProductGroupEntry>
  <ProductGroupEntry><ProductGroupCode>xz3</ProductGroupCode><ProductGroup>thing3</ProductGroup><Quantity>2.0000</Quantity><DiscountExcl>0.000000</DiscountExcl><SalesExcl>50.730000</SalesExcl><Sales>57.830000</Sales></ProductGroupEntry>
  <ProductGroupEntry><ProductGroupCode>xz4</ProductGroupCode><ProductGroup>thing4</ProductGroup><Quantity>2.0000</Quantity><DiscountExcl>0.000000</DiscountExcl><SalesExcl>40.450000</SalesExcl><Sales>46.110000</Sales></ProductGroupEntry>
  <ProductGroupEntry><ProductGroupCode>xz5</ProductGroupCode><ProductGroup>thing5</ProductGroup><Quantity>2.0000</Quantity><DiscountExcl>1.000000</DiscountExcl><SalesExcl>18.000000</SalesExcl><Sales>18.000000</Sales></ProductGroupEntry>
  <ProductGroupEntry><ProductGroupCode>xz6</ProductGroupCode><ProductGroup>thing6</ProductGroup><Quantity>4.0000</Quantity><DiscountExcl>10.080000</DiscountExcl><SalesExcl>62.900000</SalesExcl><Sales>68.420000</Sales></ProductGroupEntry>
</storeFinancialReport>

我现在正在尝试创建一个单独的模板来执行可以重复使用的翻译、求和、计算等,然后只在主文件中的第二个模板中使用 html 格式,该模板使用“丰富/理想化”导入文件模板

到目前为止,我有下面的,理论上调用一个模板,它将做总和等,将它存储在一个变量中,然后这个新转换的 xml 作为一个变量传递给执行 HTML 格式化的模板。

主/HTML 格式文件

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.1"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:set="http://exslt.org/sets"
extension-element-prefixes="set">
<xsl:output method="html" version="1.0" encoding="UTF-8"
    indent="yes" />

<xsl:include href="scrap_book_enrichment.xsl" />

<!-- call Product Group Block -->

<xsl:template name="ProductGroupBlock">
    <xsl:variable name="buildProductGroupResultXml"> <!-- store the results of this template call to this variable -->
        <xsl:call-template name="buildProductGroup">
            <xsl:with-param name="buildProductGroupResults" select="//storeFinancialReport"/>
        </xsl:call-template>
    </xsl:variable>

    <xsl:call-template name="displayProductGroupResults">
        <xsl:with-param name="buildProductGroupResults2" select="$buildProductGroupResultXml" />
    </xsl:call-template>
</xsl:template>

<xsl:template name="displayProductGroupResults">
    <xsl:param name="buildProductGroupResults2" />
    <xsl:for-each select="buildProductGroup">
        <tr>
            <td>
                <xsl:value-of select="/" />
            </td>
            <td colspan="3">
                <xsl:value-of
                    select="$buildProductGroupResults2/ProductGroupCodeText/text()" />
            </td>

            <td align="right">
                <xsl:value-of
                    select="$buildProductGroupResults2/ProductGroupQuantityText/text()" />
            </td>

            <td align="right">
                <xsl:value-of
                    select="$buildProductGroupResults2/ProductGroupDiscountExclText/text()" />
            </td>

            <td align="right">
                <xsl:value-of
                    select="$buildProductGroupResults2/ProductGroupSalesExclText/text()" />
            </td>

            <td align="right">
                <xsl:value-of
                    select="$buildProductGroupResults2/ProductGroupSalesText/text()" />
            </td>

            <td align="right">
                <xsl:value-of
                    select="$buildProductGroupResults2/ProductGroupSalesMinusSalesExclText/text()" />
            </td>

            <td align="right">
                <xsl:value-of
                    select="$buildProductGroupResults2/ProductGroupSalesExclPercentage/text()" />
            </td>

        </tr>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

第二个导入的文件,创建“理想”的 xml

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:set="http://exslt.org/sets" extension-element-prefixes="set">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>


<xsl:template name="buildProductGroup">
<xsl:param name="buildProductGroupResults" />
<xsl:for-each select="set:distinct($buildProductGroupResults/ProductGroupEntry/ProductGroup)">

        <xsl:variable name="ProductGroup">
                        <xsl:value-of select="text()" />
                    </xsl:variable>

                    <buildProductGroup>
                        <ProductGroupCodeText><xsl:value-of select="$buildProductGroupResults/ProductGroup[text()=$ProductGroup]/../ProductGroupCode/text()" /><xsl:text> - </xsl:text><xsl:value-of select="$ProductGroup" /></ProductGroupCodeText>

                        <ProductGroupQuantityText><xsl:value-of select="format-number(sum($buildProductGroupResults/ProductGroup[text()=$ProductGroup]/../Quantity/text()), '0')" />
                        </ProductGroupQuantityText>

                        <ProductGroupDiscountExclText><xsl:value-of
                                select="format-number(sum($buildProductGroupResults/ProductGroup[text()=$ProductGroup]/../DiscountExcl/text()), '###,##0.00')" />
                                </ProductGroupDiscountExclText>

                        <ProductGroupSalesExclText><xsl:value-of
                                select="format-number(sum($buildProductGroupResults/ProductGroup[text()=$ProductGroup]/../SalesExcl/text()), '###,##0.00')" />
                                </ProductGroupSalesExclText>

                        <ProductGroupSalesText><xsl:value-of
                                select="format-number(sum($buildProductGroupResults/ProductGroup[text()=$ProductGroup]/../Sales/text()), '###,##0.00')" />
                                </ProductGroupSalesText>

                      <ProductGroupSalesMinusSalesExclText><xsl:value-of select="format-number(sum($buildProductGroupResults/ProductGroup[text()=$ProductGroup]/../Sales/text()) - sum($buildProductGroupResults/ProductGroup[text()=$ProductGroup]/../SalesExcl/text()),'###,##0.00')" />
                      </ProductGroupSalesMinusSalesExclText>

                        <ProductGroupSalesExclPercentage>
                            <xsl:choose>
                                <xsl:when test="sum($buildProductGroupResults/ProductGroup[text()=$ProductGroup]/../SalesExcl)=0">
                                    <xsl:text>0.00</xsl:text>
                                </xsl:when>
                                <xsl:when test="sum($buildProductGroupResults/ProductGroup[text()=$ProductGroup]/../SalesExcl)!=0">
                                    <xsl:value-of
                                        select="format-number(number((  sum($buildProductGroupResults/ProductGroup[text()=$ProductGroup]/../SalesExcl)  div  (sum( $buildProductGroupResults/SalesExcl ) ) ) * 100), '###,##0.00')" />
                                </xsl:when>
                            </xsl:choose>
                            <xsl:text>%</xsl:text>
                        </ProductGroupSalesExclPercentage>

                    </buildProductGroup>
                </xsl:for-each>


</xsl:template>

</xsl:stylesheet>

我意识到这些很粗,但我相信我已经尽可能地减少了它,同时保持它真实我需要的东西。我们有十几个或更多这样的部分,但我显然错过了让它发挥作用的基本步骤。

目的是在“丰富”阶段创建一个不同的 xml,我所看到的称为“理想”xml,用于格式化 xsl 来处理。不幸的是,似乎当我在 Eclipse 中通过翻译器运行这些文件时,它只是将原始 xml 混搭并删除所有格式并将其聚集在一段文本中。我可能在这里误解了几个想法,但是一旦我把这一部分写下来,我想其他部分会更容易理解。

非常感谢

米奇。

[ 2013 年 8 月 6 日更新]

由于无法完成这项工作所花费的时间,以及我们将在其他领域获得的好处,我们决定花时间使我们的报告框架能够固有地处理流水线 xsls。因此,不再需要在一个样式表中使用此功能。

4

1 回答 1

2

您对这个问题的处理方法和 XSLT 通常是错误的。

  • 您的输入已经处于理想状态,无需进行“清理”转换步骤。
  • 不要使用命名模板,使用模板匹配。
  • 不要使用<xsl:for-each>,使用模板匹配。
  • 用于<xsl:key>分组。
  • 不要混合标记和布局。将与演示相关的内容 ( align="right") 移至 CSS。
  • 最后但同样重要的是:不要(!!!)使用浏览器端 XSLT。XSLT 用于在服务器上运行。(是的。我知道。从技术上讲,您可以在浏览器中运行 XSLT。浏览器端的 XSLT 支持充其量是不一致的,不要让自己头疼,不要这样做。)

我认为没有办法逐渐改进您的 XSLT,所以我从头开始重写它。

这就是你所需要的:

<xsl:stylesheet 
  version="1.1"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:set="http://exslt.org/sets"
  extension-element-prefixes="set"
  exclude-result-prefixes="set"
>
  <xsl:output method="html" version="4.0" encoding="UTF-8" indent="yes" />

  <xsl:variable name="currencyFormat" select="'###,##0.00'" />
  <xsl:variable name="percentageFormat" select="'0.00%'" />

  <xsl:key name="kProductGroup" match="ProductGroupEntry" use="ProductGroupCode" />

  <xsl:template match="storeFinancialReport">
    <table>
      <xsl:apply-templates select="ProductGroupEntry" mode="byGroupCode" />
    </table>
  </xsl:template>

  <xsl:template match="ProductGroupEntry" mode="byGroupCode">
    <xsl:variable name="inThisGroup" select="key('kProductGroup', ProductGroupCode)" />

    <xsl:if test="generate-id(.) = generate-id($inThisGroup[1])">
      <xsl:variable name="sumQuantity"     select="sum($inThisGroup/Quantity)" />
      <xsl:variable name="sumDiscountExcl" select="sum($inThisGroup/DiscountExcl)" />
      <xsl:variable name="sumSalesExcl"    select="sum($inThisGroup/SalesExcl)" />
      <xsl:variable name="sumSales"        select="sum($inThisGroup/Sales)" />
      <xsl:variable name="netSales"        select="$sumSales - $sumSalesExcl" />
      <xsl:variable name="pctSalesExcl">
        <xsl:choose>
          <xsl:when test="$sumSales">
            <xsl:value-of select="$sumSalesExcl div $sumSales" />
          </xsl:when>
          <xsl:otherwise>0</xsl:otherwise>
        </xsl:choose>
      </xsl:variable>

      <tr>
        <td colspan="3"><xsl:value-of select="concat(ProductGroup, ' - ', ProductGroupCode)" /></td>
        <td class="num"><xsl:value-of select="count($inThisGroup)" /></td>
        <td class="num"><xsl:value-of select="format-number($sumQuantity, '0')" /></td>
        <td class="num"><xsl:value-of select="format-number($sumDiscountExcl, $currencyFormat)" /></td>
        <td class="num"><xsl:value-of select="format-number($sumSalesExcl, $currencyFormat)" /></td>
        <td class="num"><xsl:value-of select="format-number($sumSales, $currencyFormat)" /></td>
        <td class="num"><xsl:value-of select="format-number($netSales, $currencyFormat)" /></td>
        <td class="num"><xsl:value-of select="format-number($pctSalesExcl, $percentageFormat)" /></td>
      </tr>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

输出:

事物1 - xz1 1 0 0.00 30.70 35.00 4.30 87.71%
事物2 - xz2 1 13 0.00 1,480.97 1,688.31 207.34 87.72%
事物3 - xz3 1 2 0.00 50.73 57.83 7.10 87.72%
事物4 - xz4 1 2 0.00 40.45 46.11 5.66 87.73%
事物5 - xz5 1 2 1.00 18.00 18.00 0.00 100.00%
事物6 - xz6 1 4 10.08 62.90 68.42 5.52 91.93%

现场观看:http ://www.xmlplayground.com/FmLo2Y

进一步阅读:

  • 此答案解释了 XSL 键的工作原理以及它们如何用于分组。
  • 这个答案解释了如何<xsl:apply-templates>工作。
于 2013-08-02T13:15:28.283 回答