Muenchian Grouping with XSL-FO Table

邮差的信 提交于 2019-12-11 01:09:59

问题


I've been working with producing simple PDFs with XSL-FO in RenderX XEP for a while, but I'm relatively new to the more involved functions of XPath.

I have some XML which looks like this:

<?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>

I need to be able to sort this data into tables into a PDF using XSLT1.0 formatting objects. The desired format being the following:

All tickets of the same size being in separate tables (sorted on the page in alphabetical order), which each list their products, contained within their relevant categories and departments. Example:

I have had a go at implementing Muenchian grouping, but the wrong categories are falling under the departments when using a large XML extract, and I haven't been able to list the relevant products below each category.

My probably rather untidy 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>

Any help with bringing in the products would be greatly appreciated.


回答1:


I think the problem is with this line, where you try to iterate over all categories for a department

<xsl:for-each select="$sizes[generate-id() = generate-id(key('keyCategory', concat(size, ' ', department, ' ', category))[1])]">

The problem is the variable sizes contains details on different departments, not just the one you are interested in, leading to duplicates.

Try this instead, to restrict it to the current department

<xsl:variable name="depts" select="key('keyDepartment', concat(size, ' ', department))" />
<xsl:for-each select="$depts[generate-id() = generate-id(key('keyCategory', concat(size, ' ', department, ' ', category))[1])]">


来源:https://stackoverflow.com/questions/24411173/muenchian-grouping-with-xsl-fo-table

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!