Search code examples
xsl-foapache-fop

XSL-FO: How to set dynamic table width?


I have this problem: I need a FO-table, which is just as wide as the width of the content (cells). But when I add a table in my FO-markup, it is always acting like a Block-Level-Element and using the width of the wohle row.

Confusing for me: If I wrap it into an Inline-Element (which has the expected behavior), the Table has not the behavior of the Inline-Element but turns again to be a Block-Element.

Does someone has an idea of how to solve that?

Here my markup:

<inline width="auto">
    <table table-layout="fixed">
        <table-column column-width="6.36mm"/>
        <table-column/>
        <table-column column-width="6.36mm"/>
        <table-column/>
        <table-column column-width="6.36mm"/>
        <table-column/>
        <table-column column-width="6.36mm"/>
        <table-column/>
        <table-body>
            <table-row>
                <table-cell padding-right="1.6mm">
                    <block-container height="3mm" width="4.76mm" overflow="hidden">
                        <block>
                            <external-graphic content-height="3mm" src="image1.jpg"/>
                        </block>
                    </block-container>
                </table-cell>
                <table-cell>
                    <block>
                        Image name 1
                    </block>
                </table-cell>
                <table-cell padding-right="1.6mm">
                    <block-container height="3mm" width="4.76mm" overflow="hidden">
                        <block>
                            <external-graphic content-height="3mm" src="image2.jpg"/>
                        </block>
                    </block-container>
                </table-cell>
                <table-cell>
                    <block>
                        Image name 2
                    </block>
                </table-cell>
                <table-cell padding-right="1.6mm">
                    <block-container height="3mm" width="4.76mm" overflow="hidden">
                        <block>
                            <external-graphic content-height="3mm" src="image3.jpg"/>
                        </block>
                    </block-container>
                </table-cell>
                <table-cell>
                    <block>
                        Image name 3
                    </block>
                </table-cell>
                <table-cell padding-right="1.6mm">
                    <block-container height="3mm" width="4.76mm" overflow="hidden">
                        <block>
                            <external-graphic content-height="3mm" src="image4.jpg"/>
                        </block>
                    </block-container>
                </table-cell>
                <table-cell>
                    <block>
                        image name4
                    </block>
                </table-cell>
            </table-row>
        </table-body>
    </table>
</inline>

(Maybe important notice: My columns need to be toggling with fixed and auto-width)

Thank you already!!!


Solution

  • What you need is called automatic table layout and is theoretically achieved setting inline-progression-dimension and table-layout to auto:

    <fo:table inline-progression-dimension="auto" table-layout="auto">
       ... columns, table-body ...
    </fo:table>
    

    However, FOP does not support auto layout yet; if you don't set a width for the table the whole line width will be used, and will be divided between the columns according to their column-width (either fixed or as a percentage), or in equal parts if columns don't have an explicitly set width.

    Confusing for me: If I wrap it into an Inline-Element (which has the expected behavior), the Table has not the behavior of the Inline-Element but turns again to be a Block-Element.

    An fo:table always creates block areas, and wrapping it inside an fo:inline is not going to change that.

    Edit: workaround

    In the specific case of a single row of objects (as in the question) a table might not be needed at all, and the desired output could be achievable using just inline objects:

    <inline keep-together.within-line="always">
        <external-graphic height="3mm" width="4.76mm" overflow="hidden" 
            content-height="3mm" src="image1.jpg"/>
        Image name 1
        <external-graphic height="3mm" width="4.76mm" overflow="hidden" 
            content-height="3mm" src="image2.jpg"/>
        Image name 2
        <external-graphic height="3mm" width="4.76mm" overflow="hidden" 
            content-height="3mm" src="image3.jpg"/>
        Image name 3
        <external-graphic height="3mm" width="4.76mm" overflow="hidden" 
            content-height="3mm" src="image4.jpg"/>
        Image name 4
    </inline>