在尝试使用XSL-FO,XSLT和Apache FOP生成格式化的pdf时尝试聚合xml重复项时遇到问题。
我已经阅读了一些关于如何实现这一点的帖子,特别注意发布:XSLT and xpath v1.0 find duplicates and aggregate以及文章Muenchian Grouping,但我仍然遇到问题。
我的XML如下:
<Document>
<RecordDetails>
<Record>
<contact id="0001" title="Mr" forename="John" surname="Smith" />
</Record>
<Record>
<contact id="0002" title="Dr" forename= "Amy" surname="Jones" />
</Record>
<Record>
<contact id="0003" title="Mr" forename="Jack" surname="Smith" />
</Record>
</RecordDetails>
</Document>
我想要实现的是在我的pdf格式输出上聚合所有与srname属性具有相同值的联系人项目。我当前的XSL代码如下:
<xsl:key name="contactsbysurname" match="contact" use="@surname"/>
<xsl:template match="Record">
*<xsl:for-each select="contact[generate-id(.)=generate-id(key('contactsbysurname',@surname)[1])]">
<xsl:for-each select="key('contactsbysurname',@surname)"> *
<fo:table-row font-size="6.5pt">
<xsl:apply-templates select="contact"/>
</fo:table-row>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
<xsl:template match="contact">
<fo:table-cell>
<fo:block text-align="center">
<xsl:value-of select="@title" />
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block text-align="center">
<xsl:value-of select="@Smith" />
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block text-align="center">
...
</fo:block>
</fo:table-cell>
</xsl:template>
似乎在模板Record中,当我尝试包含2个xsl:for-each循环以实现Muenchian方法时,FOP返回一个错误,其中涉及到没有fo:table-cell元素可以在里面找到fo:table-row标签。我理解这是因为FOP无法访问第一个xsl:for-each循环,我想知道我是否做错了。
如果我删除2 for-each标签,我会得到我的pdf但没有聚合。我在编写代码的方式上遗漏了什么吗?
非常感谢所有帮助! 谢谢。
答案 0 :(得分:1)
如果您只是更改此行,它应该可以正常工作:
<xsl:apply-templates select="contact"/>
到此:
<xsl:apply-templates select="."/>
但是,我建议更像这样构建你的XSLT:
<xsl:template match="Record">
<xsl:apply-templates
select="contact[generate-id() =
generate-id(key('contactsbysurname',@surname)[1])]"
mode="group" />
</xsl:template>
<xsl:template match="contact" mode="group">
<xsl:apply-templates select="key('contactsbysurname',@surname)" />
</xsl:template>
<xsl:template match="contact">
<fo:table-row font-size="6.5pt">
<fo:table-cell>
<fo:block text-align="center">
<xsl:value-of select="@title" />
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block text-align="center">
<xsl:value-of select="@surname" />
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block text-align="center">
...
</fo:block>
</fo:table-cell>
</fo:table-row>
</xsl:template>
修改强>
如果您只想为每个联系人显示一行信息,则无需拥有两个nestes for-each
es或两层contact
模板。在这种情况下,它甚至更简单:
<xsl:template match="Record">
<xsl:apply-templates
select="contact[generate-id() =
generate-id(key('contactsbysurname',@surname)[1])]" />
</xsl:template>
<xsl:template match="contact">
<fo:table-row font-size="6.5pt">
<fo:table-cell>
<fo:block text-align="center">
<xsl:value-of select="@title" />
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block text-align="center">
<xsl:value-of select="@surname" />
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block text-align="center">
...
</fo:block>
</fo:table-cell>
</fo:table-row>
</xsl:template>
答案 1 :(得分:0)
更改
<xsl:template match="Record">
*<xsl:for-each select="contact[generate-id(.)=generate-id(key('contactsbysurname',@surname)[1])]">
<xsl:for-each select="key('contactsbysurname',@surname)"> *
<fo:table-row font-size="6.5pt">
<xsl:apply-templates select="contact"/>
</fo:table-row>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
到
<xsl:template match="RecordDetails">
<xsl:for-each select="Record/contact[generate-id(.)=generate-id(key('contactsbysurname',@surname)[1])]">
<fo:table-row font-size="6.5pt">
<xsl:apply-templates select="key('contactsbysurname',@surname)"/>
</fo:table-row>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
对于contact
的每个@surname
组contact
,这应该为您提供一行。然后在每一行中使用匹配的模板处理所有<xsl:value-of select="@Smith" />
元素。
和
{{1}}
看起来不对,输入样本中没有该名称的属性。