Splitting a particular column with a simple horizontal line - xslt

I am trying to split a particular column with a simple horizontal line .
<fo:table>
<fo:table-body>
<fo:table-row>
<fo:table-cell border-color="white" padding-top="5px" padding-bottom="5px">
<fo:block>
<xsl:choose>
<xsl:when test=>
<fo:block border-bottom-width="0.1mm" border-bottom-style="solid" border-bottom-color="black" font-weight="bold">
First I tried to make another table in a column for splitting of data but its not working. border-bottom inside <fo:block > is also not helping .
The line doesn't seem to properly split the column .How can I do this .

On my comment above, the best solution is change your logic to apply appropriate spanning. Here is some FO to get you thinking:
<fo:table font-size="18pt">
<fo:table-body>
<fo:table-row>
<fo:table-cell number-rows-spanned="2" border="1pt solid black" padding="3pt">
<fo:block>I am all in one spanned cell</fo:block>
</fo:table-cell>
<fo:table-cell border="1pt solid black" padding="3pt">
<fo:block>I am in top half of the cell</fo:block>
</fo:table-cell>
<fo:table-cell number-rows-spanned="2" border="1pt solid black" padding="3pt">
<fo:block>I am all in one spanned cell</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell border="1pt solid black" padding="3pt">
<fo:block>I am in bottom half of the cell</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
The result is:

Related

How to wirte a part of <fo:table> in a function

I have to create many <fo:table-row> in a <fo:table-body>. I think it's not nice if I write almost 5 lines of code several times (Maybe 50 times) to create the rows.
Like this:
<fo:table-body>
<fo:table-row>
<fo:table-cell padding-bottom="6pt">
<fo:value-of select="row1"/>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell padding-bottom="6pt">
<fo:value-of select="row2"/>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell padding-bottom="6pt">
<fo:value-of select="row3"/>
</fo:table-cell>
</fo:table-row>
....
</fo:table-body>
I tried to write a function that writes the <fo:table-row> for me. And I have to call the function every time and pass a parameter.
<xsl:function name="fn:createRow">
<xsl:param name="string1"/>
<fo:table-row>
<fo:table-cell padding-bottom="6pt">
<fo:value-of select="$string1"/>
</fo:table-cell>
</fo:table-row>
</xsl:function>
And now my XSLT look like this.
<fo:table-body>
<fo:block>
<fo:value-of select="fn:createRow('row1')"/>
<fo:value-of select="fn:createRow('row2')"/>
</fo:block>
</fo:table-body>
But I get the error:
"fo:block" is not a valid child of "fo:table-body"!
But when I work without <fo:block> I get nothing in the PDF:
<fo:table-body>
<fo:value-of select="fn:createRow('row1')"/>
<fo:value-of select="fn:createRow('row2')"/>
</fo:table-body>
Is there any opportunity to do it?
Thanks!
fo:table-cell can contain one or more block-level FOs, including fo:block. (See https://www.w3.org/TR/xsl11/#fo_table-cell)
You don't show your XML, but if all of the row* elements are contained by one element, then in the template for that element, you could do something like:
<fo:table>
<fo:table-body>
<xsl:for-each select="*">
<fo:table-row>
<fo:table-cell padding-bottom="6pt">
<fo:block>
<!-- The row* element is the current element here. -->
<xsl:apply-templates />
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:for-each>
</fo:table-body>
</fo:table>
Alternatively, you could make a template for all of the row* elements:
<xsl:template match="*[starts-with(local-name(), 'row')]">
<fo:table-row>
...
(From this distance, it's not clear why the row elements need separate element names.)
When you know the names of the elements that you want to format, you can do:
<xsl:apply-templates select="row1, row2, row3" />
and:
<xsl:template match="row1 | row2 | row3">
<fo:table-row>
...
I think instead of <fo:value-of select="$string1"/> you want <xsl:value-of select="$string1"/>. I would also check whether a fo:table-cell allows inline content, it might be necessary to put a fo:block container in the cell which has the xsl:value-of element as a child.
Also, for the function calls, don't use <fo:value-of select="fn:createRow('row1')"/>, instead, use <xsl:sequence select="fn:createRow('row1')"/>.
Also, fn is a reserved prefix, for your own functions declare and use your own namespace (e.g. xmlns:mf="http://example.com/mf" and <xsl:function name="mf:createRow" ...>...</xsl:function>, then use <xsl:sequence select="mf:createRow('row1')"/>.
So an example of the function would be
<xsl:function name="mf:createRow">
<xsl:param name="input"/>
<fo:table-row>
<fo:table-cell padding-bottom="6pt">
<fo:block>
<xsl:value-of select="$input"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
</xsl:function>
and you could call it as e.g.
<fo:table-body>
<xsl:sequence select="(1 to 3) ! ('Row ' || . ) ! mf:createRow(.)"/>
</fo:table-body>

howto set xsl fo table height to 100%?

I have created a pdf template with a table.
The table has a border; after rendering all the data, the content covers only half of the page, so the table border covers only the content.
But I want the table border to cover the entire page regardless of the height of the content, like this:
I have tried to set height of table to 100%, but no luck.
I have also tried to put block-progression-dimension.optimum="100%"
on last table cell; let me know if that's the right place
<fo:page-sequence master-reference="A4-portrait">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="14pt" margin-bottom="11pt" height="100%">
<fo:table border-width="1pt" border-style="solid" height="100%" border-color="grey" margin-top="-110pt" font-family="Gotham Narrow A, Gotham Narrow B, Helvetica, Arial, sans-serif">
<fo:table-body>
<fo:table-row>
<fo:table-cell number-columns-spanned="2" margin-left="20pt">
<fo:block text-align="left" font-weight="bold" font-size="13pt" color="black" margin-bottom="2pt" margin-top="15pt" margin-left="-5pt">
${ctx.messages.repairInstructionTitle}
</fo:block>
<fo:block text-align="left" font-size="9pt" color="black">
${ctx.messages.repairInstructionMessage1}
</fo:block>
<fo:block text-align="left" font-size="9pt" color="black">
${ctx.messages.repairInstructionMessage2}
</fo:block>
<fo:block text-align="left" font-size="9pt" color="black">
${ctx.messages.repairInstructionMessage3}
</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:table margin-top="10pt" margin-bottom="15pt">
<fo:table-column column-width="50%"/>
<fo:table-column column-width="50%"/>
<fo:table-body>
<fo:table-row>
#if ($ctx.orderData.deliveryAddress.country.isocode == 'US')
<fo:table-cell margin-left="30pt" number-columns-spanned="1">
<fo:block text-align="left" font-weight="bold" font-size="9pt" color="black">
${ctx.messages.repairQuestionForLocationMainland}
</fo:block>
<fo:block text-align="left" font-size="9pt" color="black">
${ctx.messages.mauijimIncMainland}
</fo:block>
<fo:block text-align="left" font-size="9pt" color="black">
${ctx.messages.repairDepartmentLable}
</fo:block>
<fo:block text-align="left" font-size="9pt" color="black">
${ctx.messages.repairDepartmentMainlandAddressLine1}
</fo:block>
<fo:block text-align="left" font-size="9pt" color="black">
${ctx.messages.repairDepartmentMainlandAddressLine2}
</fo:block>
</fo:table-cell>
<fo:table-cell margin-left="20pt">
<fo:block text-align="left" font-weight="bold" font-size="9pt" color="black">
${ctx.messages.repairQuestionForLocationHawaii}
</fo:block>
<fo:block text-align="left" font-size="9pt" color="black">
${ctx.messages.mauijimIncHawaii}
</fo:block>
<fo:block text-align="left" font-size="9pt" color="black">
${ctx.messages.repairDepartmentLable}
</fo:block>
<fo:block text-align="left" font-size="9pt" color="black">
${ctx.messages.repairDepartmentHawaiiAddressLine1}
</fo:block>
<fo:block text-align="left" font-size="9pt" color="black">
${ctx.messages.repairDepartmentHawaiiAddressLine2}
</fo:block>
</fo:table-cell>
#end
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell margin-left="15pt" block-progression-dimension.optimum="100%">
<fo:block text-align="left" font-size="13pt" color="black" font-weight="bold">
${ctx.messages.repairAnyQuestionText}
</fo:block>
#if (${ctx.orderData.deliveryAddress.country.isocode} == 'US')
<fo:block text-align="left" font-size="9pt" color="black">
${ctx.messages.repairContactInfo}
</fo:block>
#end
#if (${ctx.orderData.deliveryAddress.country.isocode} != 'US')
<fo:block text-align="left" font-size="9pt" color="black">
#set($repairContactInfo = "repairContactInfo")
#set($isocode = $ctx.orderData.deliveryAddress.country.isocode )
#set($addMessage = "$repairContactInfo$isocode")
${ctx.messages.getMessage($addMessage)}
</fo:block>
#end
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:block>
</fo:flow>
</fo:page-sequence>
I am not sure what effect you are trying to achieve. The height="100%" on the fo:table makes it 100% of the height of its containing block, but the fo:block has margin-bottom="11pt", which reduces the height available for the fo:block and, therefore, for the fo:table.
The height="100%" gives the table a fixed height, but the margin-top="-110pt" shifts the table up by 110pt so that I'm currently seeing 110pt of blank space after the table.
If you want something really is 100% of the page height, use height="100pvh". See https://www.antenna.co.jp/AHF/help/en/ahf-ext.html#pvh
(Also, margin-left does not apply to fo:table-cell.)
From the image of the expected output, it looks like you want to have a border around the main page region, regardless of the actual height of its content.
So, it may be enough to move the definition of the border in the fo:region-body element and remove it from the fo:table; you may also consider removing the table altogether and leaving only the blocks it contains, as it does not seem to have any function other than drawing the border.
A couple of points worth mentioning:
strictly speaking, this would not be allowed by the XSL-FO Recommendation ("The values of the padding and border-width traits must be "0"."), but is generally allowed by the formatters (AntennaHouse Formatter allows it);
this solution is easy to implement if all pages must have a border around the main region; otherwise, you have to modify your templates so that a page sequence with a bordered region-body is created for the content that needs it, and different page sequences using a page master with not borders are created for the rest of the content.

How to add a continued label in a static table with XSL/XSL-FO?

I am using an xml data similar to the sample below. There is a list of possible risks, and each of them can have a name and a description.
<risks>
<freezeDeductible name="item1" description="desc 1"/>
<moneySecLimit name="item2" description="desc 2"/>
<unscheduledLimit name="item3" description="desc 3"/>
...
</risks>
The structure of my template looks as below:
<xsl:template name="displayRisks">
<fo:block>
<fo:table>
<fo:table-column column-width="proportional-column-width(33.333)" column-number="1"/>
<fo:table-column column-width="proportional-column-width(33.333)" column-number="2"/>
<fo:table-column column-width="proportional-column-width(33.333)" column-number="3"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell>
<fo:block font-weight="bold">ALL RISKS</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block><xsl:value-of select="/risks/freezeDeductible/#name"/></fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block><xsl:value-of select="/risks/freezeDeductible/#description"/></fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell>
<fo:block> </fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block><xsl:value-of select="/risks/moneySecLimit/#name"/></fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block><xsl:value-of select="/risks/moneySecLimit/#description"/></fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:block>
</xsl:template>
From the above template, I am generating PDF outputs. Because of the risk description size, and the number of risks elements is unknown, the table can go over multiple one or pages.
On the column1 x row1, there is displayed on first page, the title - "ALL RISKS". It needs to be on the same line as first risk name and description, so cannot move it to the table-header.
Is there any way that, when the table gets to page2, page3, etc. , to display the title (ALL RISKS) on the first row of the new page, with a label - for example: (continue..) ?
For example:
Page1: should display the title, on first table-row, as follows: ALL RISKS
If there is a Page2: display the title on the first table-row on Pag2, as follows: ALL RISKS(continued..)
Thanks!
There is an fo:retrieve-table-marker example in the 'XSL-FO Samples Collection' at https://www.antennahouse.com/xsl-fo-samples#table-retrieve-table-marker-1. (You may need to scroll up after you follow the link because of the banner on the page.)
There's also an example of the axf:repeat-content-at-break and axf:table-cell-repeated-marker AH Formatter extensions at https://www.antennahouse.com/xsl-fo-samples#axf-table-cell-repeated-marker-1 that demonstrates both the repetition and a '(Continued)' marker like what you want.

XSL-FOP text decoration extend line

I'm still a newbiew when it comes to XML, XSL, FOP.
How can I obtain an output having a long line with a text underneath it? something like:
<fo:inline text-decoration> Signature </fo:inline>
The only problem on this is that the line is too small. I want the line to be longer.
I want to have 2 sets of this on the same line. One is Signature and the other is Date
Please help. :)
If you want a simple signature block like you are trying to create, just use a table like this:
<fo:table>
<fo:table-column column-width="2.5in"/>
<fo:table-column column-width="1in"/>
<fo:table-column column-width="2.5in"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell border-top="1pt solid black">
<fo:block>Signature</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block/>
</fo:table-cell>
<fo:table-cell border-top="1pt solid black">
<fo:block>Date</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
Which gives you this:

setting up dynamic row height in xsl fo

I am using below line to achive dynamic row height i.e the height should match with the left column .
But I also need to split the row into different cells ? When I am using simple fo:block-cell attrbutes ,I am not getting dynamic row hight . How can achive both dynamic row hieght and cells ??
<fo:table-row display-align="center">
<xsl:for-each select="xalan:distinct(Number)">
<fo:table-cell block-progression-dimension="auto" >
<fo:block-container height="10mm">
<fo:block font-size="9pt" border-right-width="0.1mm" border-right-style="solid" border-right-color="red" >
<xsl:value-of select="">
<xsl:variable name="">
<xsl:value-of select="">
</xsl:variable>
<xsl:if test="">
<xsl:value-of select=""/>
</xsl:if>
</fo:block>
</fo:block-container>
</fo:table-cell>
snapshot
Update -
I think one way that it could be done is to insert a vertical line after every cell value .Tried this , but somehow vertical line is not printing .
<fo:table-cell number-columns-spanned="2" xsl:use-attribute-sets="myBorder" display-align="center">
<fo:block font-size="10pt" text-align="center">
<fo:table>
<fo:table-body>
<fo:table-row>
<xsl:for-each select="../../../rateDetails[toGeography/sequence = $currentSequence]">
<fo:table-cell><!-- block-progression-dimension="auto" border-right-width="0.1mm" border-right-style="solid" border-right-color="black" text-align="center"> -->
<fo:block-container>
<fo:block font-size="9pt"><!-- border-right-width="0.1mm" border-right-style="solid" border-right-color="black" text-align="center"> -->
<xsl:call-template name="currencySymbol">
<xsl:with-param name="currencyCode" select="$currencyCode" />
</xsl:call-template>
<xsl:value-of select="util:formatCurrency(rate,$language,$countryCode)" />
</fo:block>
</fo:block-container>
<fo:block-container reference-orientation="90">
<fo:block>
<fo:leader leader-pattern="rule" leader-length="100%" rule-style="solid" rule-thickness="0.1mm" color="black"/>
</fo:block>
</fo:block-container>
</fo:table-cell>
</xsl:for-each>
Is there anything that I am missing for vertical line insertion .
snapshot2
If you move the border and padding properties to the fo:table-cell, the border will be the full height of the cell:
<fo:table-cell border-right="0.1mm solid red">
By setting fo:block-container/#height, you're probably finding that the text in a cell can overflow the 10mm but only the 10mm is being used to determine the row height. If you remove the fo:block-container, you should get a variable-height table row.
The new code sample makes things a bit clearer: you're using 2 nested tables.
That's another complication you don't need.
Just use 1 table.
In the first column, place all the geography codes into the first cell. It does not matter how many there are: if you have 1 geography code, the cell will be one line high. If you have 16 geography codes in this cell, the cell will automatically resize to be 3 lines high.
The rest of the row contains cells with the price information. On these cells, define the right border to generate the red vertical line.
<fo:table>
<fo:table-column column-width="..mm" column-number="1"/>
<fo:table-column column-width="..mm" column-number="2"/>
...you'll have to add some code here to add the correct number of columns to your table...
<fo:table-body>
<fo:table-row>
<fo:table-cell>
...place the code to insert the country codes here....
</fo:table-cell>
<xsl:for-each select="../../../rateDetails[toGeography/sequence = $currentSequence]">
<fo:table-cell block-progression-dimension="auto" border-right-width="0.1mm" border-right-style="solid" border-right-color="black" text-align="center">
<fo:block-container>
<fo:block font-size="9pt">
<xsl:call-template name="currencySymbol">
<xsl:with-param name="currencyCode" select="$currencyCode" />
</xsl:call-template>
<xsl:value-of select="util:formatCurrency(rate,$language,$countryCode)" />
</fo:block>
</fo:block-container>
</fo:table-cell>
</xsl:for-each>