我正在使用一个程序来生成报告。该程序使用 XSL 文件生成 PDF 报告。我正在尝试创建自定义 XSL 文件。
在我的示例中,我尝试仅为 3.5 英寸软盘或 5.25 英寸软盘(单独)的项目生成报告。除此之外,我正在尝试将结果放在每个索引卡的两列中 - 用于打印。
我不是 XSL 专家,但我做过研究,并为我想要实现的目标找到了几种可能的解决方案(主要是这个问题),但是最终结果总是不是我想要的 - 我可能对 XSL 部分有一个错误的概念,我将不胜感激任何输入/指针。
以下是 XML 的一部分:
?xml version="1.0" encoding="UTF-8" ?>
<catalog-objects xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="temp.xsd">
<software-item>
<item>Software</item>
<media-types>
<storage-medium>
<name>5.25" Floppy</name>
</storage-medium>
</media-types>
<title>Title 1</title>
</software-item>
<software-item>
<item>Software</item>
<media-types>
<storage-medium>
<name>3.5" Floppy</name>
</storage-medium>
</media-types>
<title>Title 2</title>
</software-item>
<software-item>
<item>Software</item>
<media-types>
<storage-medium>
<name>3.5" Floppy</name>
</storage-medium>
<storage-medium>
<name>5.25" Floppy</name>
</storage-medium>
</media-types>
<title>Title 3</title>
</software-item>
<software-item>
<item>Software</item>
<media-types>
<storage-medium>
<name>CD-Rom</name>
</storage-medium>
</media-types>
<title>Title 4</title>
</software-item>
以下是我创建的 XSL 的一部分:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.1"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"
exclude-result-prefixes="fo">
<xsl:import href="../../_stylesheets/pdf_desert.xsl" />
<xsl:output method="xml" version="1.0" omit-xml-declaration="no" indent="yes" />
<xsl:param name="versionParam" select="'1.0'" />
<xsl:template match="/">
<xsl:param name="size" select="count(catalog-objects/software-item)"/>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="Index Card 4X6"
page-height="4in" page-width="6in" margin-top="4mm"
margin-bottom=".65in" margin-left="4mm" margin-right="4mm">
<fo:region-body />
<fo:region-after />
</fo:simple-page-master>
</fo:layout-master-set>
<xsl:variable name="individualFloppies" select="catalog-objects/software-item[(contains(media-types, '5.25') and not(contains(media-types, '3.5') or contains(media-types, 'ROM') or contains(media-types, 'Disc') or contains(media-types, 'CD') or contains(media-types, 'DVD') or contains(media-types, 'ray'))) or (contains(media-types, '3.5') and not(contains(media-types, '5.25') or contains(media-types, 'ROM') or contains(media-types, 'Disc') or contains(media-types, 'CD') or contains(media-types, 'DVD') or contains(media-types, 'ray')))]" />
<xsl:param name="size" select="$individualFloppies"/>
<xsl:for-each select="$individualFloppies[ceiling($size div 2) >= position()]">
<fo:page-sequence master-reference="Index Card 4X6">
<fo:static-content flow-name="xsl-region-after">
<fo:block font-size="{$fontSize}">
</fo:block>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="{$fontSize}">
<fo:table table-layout="fixed" width="100%" border-collapse="collapse">
<fo:table-column column-width="45%" />
<fo:table-column column-width="45%" />
<fo:table-body>
<fo:table-row>
<fo:table-cell>
<fo:block text-align="right" font-size="8"><fo:inline font-weight="bold">ID </fo:inline><xsl:value-of select='format-number(archive-id, "000000")' /></fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block text-align="right" font-size="8"><fo:inline font-weight="bold">ID </fo:inline><xsl:value-of select='format-number(following::software-item[ceiling($size div 2)]/archive-id, "000000")' /></fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell border-bottom="1px solid #000000">
<fo:block text-align="center" padding-top="0.2in" font-size="12" font-weight="bold">
<xsl:value-of select="title" />
</fo:block>
</fo:table-cell>
<fo:table-cell border-bottom="1px solid #000000">
<fo:block text-align="center" padding-top="0.2in" font-size="12" font-weight="bold">
<xsl:value-of select="following::software-item[ceiling($size div 2)]/title" />
</fo:block>
</fo:table-cell>
</fo:table-row>
程序生成的PDF报告是错误的,因为我还会得到标题与过滤器不匹配的单元格。此外,有时至少不显示一个项目标题。 我尝试了"逆向工程"来检查我的变量($individualFloppies
)过滤器是否正确,但是当不使用两列方法时,我得到了很好的结果,但是每个结果都在自己的行中。
感觉好像following::
导致了问题,但这只是一个猜测。
我也尝试了following-sibling::
,position() mod 2 = 1
以及最小化我拥有的过滤器。
如果有人能告诉我我离我想要实现的目标有多远,以及我错在哪里,我将不胜感激。
作为第一次在这里的海报,我希望我提供了所有重要信息。
编辑:我不确定如何在此处附加所需和当前输出的PDF文件,所以我只将其ASCII压缩:
从上面的 XML 中,所需的输出应该只有一页:
╔═══════════════════════════╗ ║ 标题 1 │ 标题 2 ║ ╠════════════╪════════════╣ ║ │ ║ ║ │ ║ ║ │ ║ ╚
═══════════╧════════════════╝生成报告后得到的是两页:
页 1: ╔════════════╤════════════╗ ║ 标题 1 │ 标题 3 ║ ╠════════════╪════════════╣ ║ │ ║ ║ │ ║ ║ │ ║ ╚════════════╧════════════╝ 第 2 页: ╔════════════╤════════════╗ ║ 标题 2 │ 标题 4 ║ ╠════════════╪════════════╣ ║ │ ║ ║ │ ║ ║ │ ║ ╚
════════════╧══════════════╝把逻辑写下来: 由于"标题 1"只有"5.25"软盘"和"标题 2"只有"3.5"软盘",因此它们是唯一应该出现的两个。 "标题 3"是"5.25"软盘",但也是"3.5"软盘",所以它不应该显示。 "标题 4"是"CD-Rom",因此它也不应显示为列。
写这篇文章让我意识到我正在使用的过滤器不起作用 - 考虑到我在某些不同方面使用了一些类似的过滤器并且它确实有效,这很奇怪。
我希望这些编辑是预期的"示例",并且它们进一步澄清了这个问题。
AFAICT,这里的问题在于表达式:
<xsl:value-of select="following::software-item[ceiling($size div 2)]/title" />
尽管您处于循环遍历筛选变量的上下文中,但following::
轴是在源文档的上下文中计算的。下面是一个小样式表,它单独演示了问题以及可能的解决方案:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="individualFloppies" select="catalog-objects/software-item[(contains(media-types, '5.25') and not(contains(media-types, '3.5') or contains(media-types, 'ROM') or contains(media-types, 'Disc') or contains(media-types, 'CD') or contains(media-types, 'DVD') or contains(media-types, 'ray'))) or (contains(media-types, '3.5') and not(contains(media-types, '5.25') or contains(media-types, 'ROM') or contains(media-types, 'Disc') or contains(media-types, 'CD') or contains(media-types, 'DVD') or contains(media-types, 'ray')))]" />
<out>
<wrong>
<xsl:for-each select="$individualFloppies">
<pair>
<left><xsl:value-of select="title" /></left>
<right><xsl:value-of select="following::software-item[1]/title"/></right>
</pair>
</xsl:for-each>
</wrong>
<right>
<xsl:for-each select="$individualFloppies">
<xsl:variable name="pos" select="position()" />
<pair>
<left><xsl:value-of select="title" /></left>
<right><xsl:value-of select="$individualFloppies[$pos+1]/title"/></right>
</pair>
</xsl:for-each>
</right>
</out>
</xsl:template>
</xsl:stylesheet>
在 michael.hor257k 的帮助下(再次感谢!我设法添加和更改了必要的代码行,以便生成我想要的报告。
以下是更新的代码(从应用第一个更改的位置开始):
<xsl:variable name="individualFloppies" select="catalog-objects/software-item[normalize-space(media-types)='3.5" Floppy' or normalize-space(media-types)='5.25" Floppy']" />
<xsl:param name="size" select="$individualFloppies"/>
<xsl:for-each select="$individualFloppies">
<xsl:variable name="pos" select="position()" />
<xsl:if test="position() mod 2 = 1">
<fo:page-sequence master-reference="Index Card 4X6">
<fo:static-content flow-name="xsl-region-after">
<fo:block font-size="{$fontSize}">
</fo:block>
</fo:static-content>
<!--Table Begins-->
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="{$fontSize}">
<fo:table table-layout="fixed" width="100%" border-collapse="collapse">
<fo:table-column column-width="2.5%" />
<fo:table-column column-width="45%" />
<fo:table-column column-width="2.5%" />
<fo:table-column column-width="2.5%" />
<fo:table-column column-width="45%" />
<fo:table-column column-width="2.5%" />
<fo:table-body>
<fo:table-row>
<fo:table-cell number-columns-spanned="3">
<fo:block text-align="right" font-size="8"><fo:inline font-weight="bold">ID </fo:inline><xsl:value-of select='format-number(archive-id, "000000")' /></fo:block>
</fo:table-cell>
<xsl:choose>
<xsl:when test="position() != last()">
<fo:table-cell number-columns-spanned="3">
<fo:block text-align="right" font-size="8"><fo:inline font-weight="bold">ID </fo:inline><xsl:value-of select='format-number($individualFloppies[$pos+1]/archive-id, "000000")' /></fo:block>
</fo:table-cell>
</xsl:when>
<xsl:otherwise>
<fo:table-cell number-columns-spanned="3"><fo:block></fo:block></fo:table-cell>
</xsl:otherwise>
</xsl:choose>
</fo:table-row>
<fo:table-row>
<fo:table-cell><fo:block></fo:block></fo:table-cell>
<fo:table-cell border-bottom="1px solid #000000">
<fo:block text-align="center" padding-top="0.2in" font-size="12" font-weight="bold">
<xsl:value-of select="title" />
</fo:block>
</fo:table-cell>
<fo:table-cell><fo:block></fo:block></fo:table-cell>
<fo:table-cell><fo:block></fo:block></fo:table-cell>
<xsl:choose>
<xsl:when test="position() != last()">
<fo:table-cell border-bottom="1px solid #000000">
<fo:block text-align="center" padding-top="0.2in" font-size="12" font-weight="bold">
<xsl:value-of select="$individualFloppies[$pos+1]/title" />
</fo:block>
</fo:table-cell>
</xsl:when>
<xsl:otherwise>
<fo:table-cell><fo:block></fo:block></fo:table-cell>
</xsl:otherwise>
</xsl:choose>
<fo:table-cell><fo:block></fo:block></fo:table-cell>
</fo:table-row>
指出更新的行:
第 1 行:更干净,我相信,将数据过滤到变量中的更好方法。
第 3-4 行:实现 michael.hor257k 示例的第一部分
第 5 行:使循环仅在奇数节点上工作(不确定我的术语是否正确)
第 26-35/46-57 行:实现 michael.hor257k' 示例中的第二部分,并检查当前位置是否是最后一个。