我目前正在尝试在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>