基于匹配值 XSLT-1.0 求和



我目前正在尝试在XSLT 1.0中使用分组。我有类似于下面的XML:

<table>
    <row>
        <PRODUCER type="VARCHAR" value="PRODUCER 1"/>
        <PUBLICATION_CODE_-_NAME type="VARCHAR" value="PUBLICATION A"/>
        <DOMESTIC type="DECIMAL" value="20"/>
        <FOREIGN type="DECIMAL" value="4"/>
    </row>
    <row>
        <PRODUCER type="VARCHAR" value="PRODUCER 1"/>
        <PUBLICATION_CODE_-_NAME type="VARCHAR" value="PUBLICATION B"/>
        <DOMESTIC type="DECIMAL" value="57"/>
        <FOREIGN type="DECIMAL" value="10"/>
    </row>
    <row>
        <PRODUCER type="VARCHAR" value="PRODUCER 2"/>
        <PUBLICATION_CODE_-_NAME type="VARCHAR" value="PUBLICATION C"/>
        <DOMESTIC type="DECIMAL" value="35"/>
        <FOREIGN type="DECIMAL" value="20"/>
    </row>
    <row>
        <PRODUCER type="VARCHAR" value="PRODUCER 2"/>
        <PUBLICATION_CODE_-_NAME type="VARCHAR" value="PUBLICATION D"/>
        <DOMESTIC type="DECIMAL" value="23"/>
        <FOREIGN type="DECIMAL" value="18"/>
    </row>
</table>

到目前为止,我已经能够实现我希望的一切,除了根据生产者获得国内和国外的总和。我已经阅读了Muenchian分组等,但是我无法将其应用于我的XML。我相信我必须创建一个基于生产者的密钥,例如以下内容。

<xsl:key name="producerkey" match="/table/row/" use="PRODUCER/@value"/>

正是在这一点上,我遇到了一个问题。我相信我必须生成 ID 并使用这些 id 对我的值进行分组。

到目前为止,我能够生成与此类似的PDF。

| PRODUCER || PUBLICATION ||DOMESTIC||FOREIGN|
------------------------------------------
|PRODUCER 1||PUBLICATION A||   20   ||   4   |
|          ||PUBLICATION B||   57   ||  10   | 
|          ||TOTALS       || DTOTAL || FTOTAL|
|PRODUCER 2||PUBLICATION C||   35   ||  20   |
|          ||PUBLICATION D||   23   ||  18   |
|          ||TOTALS       || DTOTAL || FTOTAL|

我正在尝试用适当的生产者分组将"DTOTAL"和"FTOTAL"替换为"国内"和"国外"列的总和。

以下是我认为我们工作 XSLT 中最相关的部分,它生成的布局类似于上表。

<xsl:template match="row">
    <fo:table>
        <fo:table-body  font-size="10pt"
                        font-family="sans-serif"
                        line-height="10pt"
                        space-after.optimum="3pt">
            <xsl:for-each select="current()">
                <xsl:variable name="testnext" select="following-sibling::*[1]"/>
                <xsl:choose>
                    <xsl:when test="$testnext">
                        <xsl:choose>
                            <xsl:when test="$testnext/PRODUCER/@value = child::PRODUCER/@value">
                                <fo:table-row>
                                    <xsl:apply-templates select="PRODUCER"/>
                                    <xsl:apply-templates select="PUBLICATION_CODE_-_NAME"/>
                                    <xsl:apply-templates select="DOMESTIC"/>
                                    <xsl:apply-templates select="FOREIGN"/>
                                </fo:table-row>
                            </xsl:when>
                            <xsl:otherwise>
                                <fo:table-row>
                            <xsl:apply-templates select="PRODUCER"/>
                            <xsl:apply-templates select="PUBLICATION_CODE_-_NAME"/>
                            <xsl:apply-templates select="DOMESTIC"/>
                            <xsl:apply-templates select="FOREIGN"/>
                        </fo:table-row> 
                        <fo:table-row>
                            <fo:table-cell  width="2.125in"
                                             height="0.4in">
                                <fo:block>
                                    <fo:leader/>
                                </fo:block>
                            </fo:table-cell>
                            <fo:table-cell  width="3.25in"
                                            height="0.4in">
                                <fo:block>
                                    PRODUCER TOTAL
                                </fo:block>
                            </fo:table-cell>
                            <fo:table-cell  width="0.95in"
                                            height="0.4in">
                                <fo:block>
                                    DTOTAL
                                </fo:block>
                            </fo:table-cell>
                            <fo:table-cell  width="0.95in"
                                            height="0.4in">
                                <fo:block>
                                    FTOTAL
                                </fo:block>
                            </fo:table-cell>
                        </fo:table-row>
                            </xsl:otherwise>
                        </xsl:choose>
                    </xsl:when>
                    <xsl:otherwise>
                        <fo:table-row>
                            <xsl:apply-templates select="PRODUCER"/>
                            <xsl:apply-templates select="PUBLICATION_CODE_-_NAME"/>
                            <xsl:apply-templates select="DOMESTIC"/>
                            <xsl:apply-templates select="FOREIGN"/>
                        </fo:table-row> 
                        <fo:table-row>
                            <fo:table-cell  width="2.125in"
                                             height="0.4in">
                                <fo:block>
                                    <fo:leader/>
                                </fo:block>
                            </fo:table-cell>
                            <fo:table-cell  width="3.25in"
                                            height="0.4in">
                                <fo:block>
                                    PRODUCER TOTAL
                                </fo:block>
                            </fo:table-cell>
                            <fo:table-cell  width="0.95in"
                                            height="0.4in">
                                <fo:block>
                                    DTOTAL
                                </fo:block>
                            </fo:table-cell>
                            <fo:table-cell  width="0.95in"
                                            height="0.4in">
                                <fo:block>
                                    FTOTAL
                                </fo:block>
                            </fo:table-cell>
                        </fo:table-row>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each>
        </fo:table-body>
    </fo:table>
</xsl:template>
<xsl:template match="PRODUCER">
    <fo:table-cell  width="2.125in"
                    height="0.2in">
        <fo:block>
            <xsl:variable name="test" select="parent::row/preceding-sibling::row[1]"/>
            <xsl:choose>
                <xsl:when test="$test">
                    <xsl:choose>
                        <xsl:when test="$test/PRODUCER/@value = @value">
                            <fo:leader/>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:value-of select="@value"/>
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="@value"/>
                </xsl:otherwise>
            </xsl:choose>
        </fo:block>
    </fo:table-cell>
</xsl:template>
<xsl:template match="PUBLICATION_CODE_-_NAME">
    <fo:table-cell  width="3.25in"
                    height="0.2in">
        <fo:block>
            <xsl:value-of select="@value"/>
        </fo:block>
    </fo:table-cell>
</xsl:template>
<xsl:template match="DOMESTIC">
    <fo:table-cell  width="0.95in"
                    height="0.2in">
        <fo:block>
            <xsl:value-of select="@value"/>
        </fo:block>
    </fo:table-cell>
</xsl:template>
<xsl:template match="FOREIGN">
    <fo:table-cell  width="0.95in"
                    height="0.2in">
        <fo:block>
            <xsl:value-of select="@value"/>
        </fo:block>
    </fo:table-cell>
</xsl:template>

我正在做的事情的基础是检查每一行的生产者,并使用该比较来确定何时在第一列中包含 PRODUCER 值,以及何时创建包含列总和和额外空间的行。我确定我的代码有点混乱,但我刚刚开始使用这项技术,发现自学的学习曲线有点陡峭。此外,如果它是第一行,则包括生产者,如果它是最后一行,则总计行将包含在旁边以完成报告。对于它的价值,生产者已经按适当的顺序分组。

任何和所有的帮助/建议/批评将不胜感激。

这在

XSLT 2 中要容易得多,但为了旧时间的缘故:

<xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsl:key name="producerkey" match="row" use="PRODUCER/@value"/>
 <xsl:template match="table">
  <table>
   <thead>
    <tr>
     <th>Producer</th>
     <th>Publication</th>
     <th>Domestic</th>
     <th>Foreigh</th>
    </tr>
   </thead>
   <tbody>
    <xsl:for-each select="row[
              generate-id(.)
              =
              generate-id(key('producerkey',PRODUCER/@value))[1]
              ]">
     <xsl:for-each select="key('producerkey',PRODUCER/@value)">
      <tr>
       <td>-
       <xsl:if test="position()=1">
    <xsl:value-of select="PRODUCER/@value"/>
       </xsl:if>
       </td>
       <td><xsl:value-of select="PUBLICATION_CODE_-_NAME/@value"/></td>
       <td><xsl:value-of select="DOMESTIC/@value"/></td>
       <td><xsl:value-of select="FOREIGN/@value"/></td>
      </tr>
     </xsl:for-each>
     <tr>
      <td>-</td>
      <td>Totals</td>
      <td><xsl:value-of select="sum(key('producerkey',PRODUCER/@value)/DOMESTIC/@value)"/></td>
      <td><xsl:value-of select="sum(key('producerkey',PRODUCER/@value)/FOREIGN/@value)"/></td>
     </tr>
    </xsl:for-each>
   </tbody>
  </table>
 </xsl:template>
</xsl:stylesheet>

生产

<table><thead>
    <tr><th>Producer</th><th>Publication</th><th>Domestic</th><th>Foreigh</th></tr></thead><tbody>
    <tr>
      <td>-PRODUCER 1</td><td>PUBLICATION A</td><td>20</td><td>4</td></tr> 
<tr><td>-</td><td>PUBLICATION B</td><td>57</td><td>10</td></tr>
<tr><td>-</td><td>Totals</td><td>77</td><td>14</td></tr>
<tr><td>-
       PRODUCER 2</td><td>PUBLICATION C</td><td>35</td><td>20</td></tr>
<tr><td>-</td><td>PUBLICATION D</td><td>23</td><td>18</td></tr>
    <tr><td>-</td><td>Totals</td><td>58</td><td>38</td></tr>
  </tbody>
</table>

最新更新