Я некоторое время работал над созданием простых PDF-файлов с помощью XSL-FO в RenderX XEP, но я относительно новичок в более сложных функциях XPath.
У меня есть XML, который выглядит так:
<?xml version="1.0" encoding="UTF-8"?>
<report>
<ticket>
<size>A</size>
<department>Dept 1</department>
<category>Cat 1</category>
<product>Product 1</product>
</ticket>
<ticket>
<size>A</size>
<department>Dept 1</department>
<category>Cat 2</category>
<product>Product 2</product>
</ticket>
<ticket>
<size>B</size>
<department>Dept 1</department>
<category>Cat 2</category>
<product>Product 3</product>
</ticket>
<ticket>
<size>B</size>
<department>Dept 1</department>
<category>Cat 1</category>
<product>Product 1</product>
</ticket>
<ticket>
<size>C</size>
<department>Dept 1</department>
<category>Cat 2</category>
<product>Product 2</product>
</ticket>
<ticket>
<size>D</size>
<department>Dept 3</department>
<category>Cat 1</category>
<product>Product 4</product>
</ticket>
<ticket>
<size>D</size>
<department>Dept 1</department>
<category>Cat 1</category>
<product>Product 1</product>
</ticket>
</report>
Мне нужно иметь возможность сортировать эти данные в таблицы в PDF, используя объекты форматирования XSLT1.0. Желаемый формат следующий:
Все билеты одного размера находятся в отдельных таблицах (отсортированных на странице в алфавитном порядке), в каждой из которых перечислены их продукты, содержащиеся в соответствующих категориях и отделах. Пример:
Я попробовал реализовать мюнхенскую группировку, но при использовании большого XML-выборка под отделы попадают неправильные категории, и я не смог перечислить соответствующие продукты под каждой категорией.
Мой, вероятно, довольно неопрятный XSL:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="keySize" match="ticket" use="size" />
<xsl:key name="keyDepartment" match="ticket" use="concat(size, ' ', department)" />
<xsl:key name="keyCategory" match="ticket" use="concat(size, ' ', department, ' ', category)" />
<xsl:template match="/report">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="simple" page-height="29.7cm" page-width="21cm" margin-top="2cm" margin-bottom="2cm" margin-left="2cm" margin-right="2cm">
<fo:region-body />
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="simple">
<fo:flow flow-name="xsl-region-body">
<xsl:for-each select="ticket[count(. | key('keySize', size)[1]) = 1]">
<xsl:sort select="size" order="ascending" />
<fo:block>
Size <xsl:value-of select="size" />
</fo:block>
<fo:block>
<xsl:variable name="sizes" select="key('keySize', size)" />
<xsl:for-each select="$sizes[generate-id() = generate-id(key('keyDepartment', concat(size, ' ', department))[1])]">
<xsl:sort select="department" order="ascending" />
<!--TABLES START-->
<fo:table-and-caption>
<fo:table border="0.2mm solid black" width="100%">
<fo:table-header>
<fo:table-row>
<fo:table-cell>
<fo:block font-weight="bold" margin="1mm 0mm 0mm 1mm">
<xsl:text>Department</xsl:text>
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block font-weight="bold" margin="1mm 0mm 0mm 1mm">
<xsl:value-of select="department" />
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-header>
<fo:table-body>
<fo:table-cell>
<fo:block margin="1mm 0mm 0mm 1mm" />
</fo:table-cell>
</fo:table-body>
</fo:table>
</fo:table-and-caption>
<!--BRINGS IN WRONG CATEGORIES-->
<xsl:for-each select="$sizes[generate-id() = generate-id(key('keyCategory', concat(size, ' ', department, ' ', category))[1])]">
<xsl:sort select="category" order="ascending" />
<fo:table-and-caption>
<fo:table border="0.2mm solid black" width="100%">
<fo:table-header>
<fo:table-row>
<fo:table-cell>
<fo:block font-weight="bold" margin="1mm 0mm 0mm 1mm">
<xsl:text>Category</xsl:text>
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block font-weight="bold" margin="1mm 0mm 0mm 1mm">
<xsl:value-of select="category" />
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-header>
<fo:table-body>
<fo:table-row>
<fo:table-cell>
<fo:block margin="1mm 0mm 0mm 1mm"><xsl:value-of select="description" /></fo:block>
</fo:table-cell>
</fo:table-row>
<!--
DESCRIPTIONS GO HERE?
-->
</fo:table-body>
</fo:table>
</fo:table-and-caption>
</xsl:for-each>
</xsl:for-each>
</fo:block>
</xsl:for-each>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>
Любая помощь с доставкой продуктов будет принята с благодарностью.