Need to create a static footer with xsl-fo - footer

At the bottom of my document, I have an address that I need to stay at the bottom so the address can be used in window mailers. I have tried using static-content tags to achieve this, but my document errors out every time. I am new to this, so I'm guessing I missing something. I want the "contractor" template to be static in the footer.
<xsl:template match="/" >
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<!-- Setup up page size (Can be in inches or centimeters)-->
<fo:simple-page-master
master-name="page"
page-width="8.50in"
page-height="11.00in"
margin-top="0.50in"
margin-bottom="0.50in"
margin-left="0.50in"
margin-right="0.50in">
<fo:region-body margin-top="0cm"/>
<fo:region-before extent="0cm"/>
<fo:region-after extent="0cm"/>
</fo:simple-page-master>
</fo:layout-master-set>
<xsl:apply-templates select="/Permits/Permit" />
</fo:root>
</xsl:template>
<xsl:template match="Permit">
<fo:page-sequence master-reference="page">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="10pt">
<xsl:call-template name="header"/>
<xsl:call-template name="permitdetails"/>
<xsl:call-template name="permitdetails2"/>
<xsl:call-template name="parties"/>
<xsl:call-template name="feesummary"/>
<xsl:call-template name="inspections"/>
<xsl:call-template name="contractor"/>
</fo:block>
</fo:flow>
</fo:page-sequence>
</xsl:template>

<fo:static-content> should be a child of <fo:page-sequence> It should not work if you were simply trying to wrap your <xsl:call-template name="contractor"/> above in static-content tags. Can you post your template with the error?
Something like this should work:
<xsl:template match="Permit">
<fo:page-sequence master-reference="page">
<fo:static-content flow-name="xsl-region-after">
<fo:block>
<xsl:call-template name="contractor"/>
</fo:block>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="10pt">
<xsl:call-template name="header"/>
<xsl:call-template name="permitdetails"/>
<xsl:call-template name="permitdetails2"/>
<xsl:call-template name="parties"/>
<xsl:call-template name="feesummary"/>
<xsl:call-template name="inspections"/>
</fo:block>
</fo:flow>
</fo:page-sequence>
</xsl:template>
</xsl:template>
<fo:static-content> should be declared before the body flow, even if it appears after the body in the output.

Related

Parsing a string using more than one delimiter XSLT 2 3

I have to insert a dot leader at the end of the first line of what could be several lines of text. If the string is over 37 characters, I display the first 37 characters, then the dot leader, and then the rest of the string flows to the following lines. I can get this to work using a space as a delimiter, but if there are no spaces the entire description gets pushed to the second line. So commas and hyphens need to be delimiters, as well, at the very least.
<xsl:template name="substring-before-last">
<xsl:param name="input" />
<xsl:variable name="del" select="'[,|-|\s]+'"/>
<xsl:variable name="string-tokens" select="tokenize($input, $del)"/>
<xsl:variable name="substring">
<xsl:value-of select="$string-tokens[not(. = $string-tokens[last()])]"/>
</xsl:variable>
<xsl:value-of select="$substring"/>
</xsl:template>
<xsl:template name="getFirstLine">
<xsl:param name="input" />
<xsl:variable name="remaining">
<xsl:call-template name="substring-before-last">
<xsl:with-param name="input" select="$input"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="string-length($remaining) >= 37">
<xsl:call-template name="getFirstLine">
<xsl:with-param name="input" select="$remaining"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$remaining"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="addDotLeader">
<xsl:variable name="descript" select="REMOVE-THIS-IS-A-TEST-LINE,XXX,XXXXXXXXXXXX XXXXX,XXX-XXX,XXXX-XXX,XXXXXXXXXXXXXX,XXXX,XXXXXXXX-XXXXXX-XXXXXXXXX" />
<xsl:variable name="length" select="string-length($descript)" as="xs:integer"/>
<xsl:choose>
<xsl:when test="$length >= 37">
<xsl:variable name="remaining">
<xsl:call-template name="getFirstLine">
<xsl:with-param name="input" select="$descript"/>
</xsl:call-template>
</xsl:variable>
<!-- print out first line -->
<xsl:value-of select="$remaining"/>
<!-- print out dot leader -->
<xsl:text> </xsl:text><fo:leader leader-pattern="dots"/><xsl:text> </xsl:text>
<fo:block text-align-last="left" margin-left="8px">
<xsl:value-of select="substring-after($descript,$remaining)"/>
</fo:block>
</xsl:when>
<xsl:otherwise>
<!-- Description fits on first line -->
<xsl:value-of select="$descript"/>
<xsl:text> </xsl:text><fo:leader leader-pattern="dots" /><xsl:text> </xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
This almost works, except the dashes and commas are stripped out when it gets tokenized. When I try to print out the rest of the string, the substring-after fails because of the missing delimiters.
Actual output:
. . REMOVE THIS IS A TEST...........................
The actual string was REMOVE-THIS-IS-A-TEST-LINE,XXX,XXXXXXXXXXXX XXXXX,XXX-XXX,XXX-XXXXX,XXXXXXXXXXXXXX,XXXX,XXXXXXXX-XXXXXX-XXXXXXXXX
The desired output is:
. . REMOVE-THIS-IS-A-TEST-..........................
LINE,XXX,XXXXXXXXXXXX XXXXX,XXX-XXX,XXX-XXXXX,
XXXXXXXXXXXXXX,XXXX,XXXXXXXX-XXXXXX-XXXXXXXXX
I'm sure there is a better way to do this, maybe start with capturing the first 37 characters before checking delimiters?

Is it possible to show subsections with page numbers in TOC using XSL:FO?

I am using XSL FO to generate PDF file. I am trying to show the chapter, section1, subsection1, subsubsection1 with Page numbers. But I am unable to do it. Here is the code that I am trying to achieve. But I can able to see the page number and internal link only for the "Chapter" part alone. See the below image. I want to show the page number and internal destination link for subsections too. Any help?
<xsl:template name="genTOC">
<fo:block break-before='page'>
<fo:block font-size="16pt" text-align="center" font-weight="bold">TABLE OF CONTENTS</fo:block>
<xsl:for-each select="//chapter|//section1|//subsection1|//subsubsection1">
<fo:block text-align-last="justify">
<fo:basic-link internal-destination="{generate-id(.)}">
<xsl:value-of select="index"/>
<xsl:text> </xsl:text>
<xsl:value-of select="title"/>
<fo:leader leader-pattern="dots"/>
<fo:page-number-citation ref-id="{generate-id(.)}"/>
</fo:basic-link>
</fo:block>
</xsl:for-each>
</fo:block>
</xsl:template>
<xsl:template match="chapter">
<fo:block id="{generate-id()}">
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="section1">
<fo:block id="{generate-id()}">
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="subsection1">
<fo:block id="{generate-id()}">
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="subsubsection1">
<fo:block id="{generate-id()}">
<xsl:apply-templates/>
</fo:block>
</xsl:template>

Transform only the last element of XML and copy the rest in XSLT

I have an XML like below -
<root>
<row>
<col1>16</col1>
<col2>466</col2>
<col3>144922</col3>
<col4>0</col4>
<col5>5668</col5>
<col6>475</col6>
</row>
</root>
The number of columns can vary inside the root element. It can also be up to col9. My requirement is to modify the last column and copy others as it is for an incoming XML.
I have something like this till now where I am assigning the value to used as the last element in a variable and then trying to call it when the last position is reached-
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs"
version="2.0">
<xsl:param name="line88.field2" />
<xsl:param name="rec16.col2" />
<xsl:variable name="col3">
<xsl:choose>
<xsl:when test="$rec16.col2 ='165'">
<xsl:value-of select="'Y'"/>
</xsl:when>
<xsl:when>
------
<xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"></xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="row[position() = last()]">
<col9>
<xsl:call-template name="AnotherTemplate">
<xsl:with-param name="inputData">
<xsl:value-of select="$col3" />
</xsl:with-param>
</xsl:call-template>
</col9>
</xsl:template>
<xsl:template name="AnotherTemplate">
<xsl:param name="inputData"></xsl:param>
<xsl:value-of select="$inputData" />
</xsl:template>
</xsl:stylesheet>
But this is not working for me. Just giving me one column with the modified value.Please help.
The desired outcome should be as below where the last column has the value from the variable.
<root>
<row>
<col1>16</col1>
<col2>466</col2>
<col3>144922</col3>
<col4>0</col4>
<col5>5668</col5>
<col6>Y</col6>
</row>
</root>
Without knowing your whole XSLT code. You can use this row template:
<xsl:template match="row/*[starts-with(local-name(),'col') and position() = last()]">
<xsl:element name="{concat('col',position() div 2)}">
<xsl:call-template name="AnotherTemplate">
<xsl:with-param name="inputData">
<xsl:value-of select="$col3" />
</xsl:with-param>
</xsl:call-template>
</xsl:element>
</xsl:template>
It replaces the last col? element by the given value (the result of the xsl:call-template code).

Using Saxon-ce to display filtered output via a combobox

I am trying to set up a combobox with Saxon-ce whose value filters the display of items in an xml. Here is a sample of the code I have so far.
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common"
xmlns:ixsl="http://saxonica.com/ns/interactiveXSLT"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
extension-element-prefixes="ixsl">
<xsl:template match="/">
<!-- set up combo box -->
<xsl:result-document href="#typeControl">
<xsl:text>Type: </xsl:text>
<select class="menuSub_monster" id="typeBox">
<option value="all" selected="'all'">Unsorted</option>
<option value="group">Sorted</option>
<option value="value1">Value1</option>
<option value="value2">Value2</option>
</select>
</xsl:result-document>
<!-- inital display -->
<xsl:call-template name="displayTemplates">
<xsl:with-param name="typeSel" select="'all'"/>
</xsl:call-template>
</xsl:template>
<!-- Change display when we change combo box -->
<xsl:template match="select[#id='typeBox']" mode="ixsl:onchange">
<xsl:variable name="control" select="."/>
<xsl:variable name="typeValue" select="ixsl:get($control,'value')" />
<xsl:call-template name="displayTemplates">
<xsl:with-param name="typeSel" select="$typeValue"/>
</xsl:call-template>
</xsl:template>
<!-- display routine -->
<xsl:template name="displayTemplates">
<xsl:param name="typeSel"/>
<xsl:result-document href="#display" method="ixsl:replace-content" >
<xsl:choose>
<xsl:when test="$typeSel='all'">
<xsl:for-each select="templates/template">
<xsl:sort select="sort_name"/>
... CODE FOR DISPLAY
</xsl:for-each>
</xsl:when>
<xsl:when test="$typeSel='group'">
... CODE FOR DISPLAY
</xsl:when>
<xsl:otherwise>
<xsl:for-each select="templates/template/types[type[text()=$typeSel]]">
<xsl:sort select="../sort_name"/>
...CODE FOR DISPLAY
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</div>
</xsl:result-document>
</xsl:template>
The issue I am having is calling the template displayTemplates when the combobox changes value. My transition to the context templates/template is not working since this is part of the XML I am calling with this style sheet. However, match="select[#id='typeBox']" sets the context to an object not in the XML. How can I change my context from the combobox to my XML so the for-each statements in the display routine work correctly?
One way: bind a variable to some node in your XML from which you can successfully navigate to where you need to go. Then use a reference to that variable to move the context back to the other document. (There may be more elegant ways.)

Dynamic line wraping- condition based in XSLT1&2

My output type is text.
I am preparing for Reports.
My text output got to accept only 50 character width after that which has to be wrapped in to the next line.
I have a solution to line wrap for the elements in the text.
Is there any way to to wrap for the entire reports instead of doing for the every line?
Can I do it for the whole document?
I have solutions for line wrap, my problem is that I have many conditions like below:
Firstname lastname route (condition1 ) (condition2) (condition3)
(condition4)..go on...
Let us assume:
First name fixedwidth is 15,
lastname fixed width is 15,city fixed width is 3...
after that condition1 will have 10 width ,condition2 have 15 fixed with then go on...
importantly these conditions are option only...
So 15+emptyspace+15+emptyspace+3 =36 My condition will start from 36 th column..
After the first wrap I got to continue from the same line for the upcoming conditions.
So for the next item i got find the start and end locations.
How to solve this problem ?
xml input:
<?xml version="1.0" encoding="UTF-8"?>
<passengerlist>
<passengers>
<Firstname>JOHNNNNNNNNNNNN</Firstname>
<lastname>MARKKKKKKKKKKKK</lastname>
<comments>abcdefh abc abcde abc dekf jl</comments>
<route>air</route>
</passengers>
<!-- <passengers>
<Firstname>ANTONYYYYYYYYYYY</Firstname>
<lastname>NORMAN</lastname>
<comments>abcdefddddddddghhhhhhhhhhhhhh</comments>
<route>air</route>
</passengers>
<passengers>
<Firstname>BRITTOOOOOOOOOO</Firstname>
<lastname>MARKKKKKKK</lastname>
<comments>abcdedfffghghghghghghghghghghghghgh</comments>
<route>cruise</route>
</passengers> -->
</passengerlist>
XSLT Code:
<!-- For line Wrapping -->
<xsl:template name="callEmpty">
<xsl:param name="callEmpty"/>
<xsl:variable name="LNemptyCheck" select="$callEmpty"></xsl:variable>
</xsl:template>
<xsl:template name="text_wrapper">
<xsl:param name="Text"/>
<xsl:choose>
<xsl:when test="string-length($Text)">
<xsl:value-of select="substring($Text,1,15)"/>
<xsl:if test="string-length($Text) > 15">
<xsl:value-of select="$newline"/>
</xsl:if>
<xsl:call-template name="wrapper_helper">
<xsl:with-param name="Text" select="substring($Text,16)"/>
</xsl:call-template>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template name="wrapper_helper">
<xsl:param name="Text"/>
<xsl:value-of select="substring($Text,1,15)"/>
<xsl:text>
</xsl:text>
<xsl:call-template name="text_wrapper">
<xsl:with-param name="Text" select="substring($Text,15)"/>
</xsl:call-template>
</xsl:template>
<!-- Template for Line wrapping -->
<xsl:template match="/">
<xsl:for-each select="passengerlist/passengers">
<xsl:value-of select="Firstname"/>
<xsl:text> </xsl:text>
<xsl:value-of select="lastname"/>
<xsl:text> </xsl:text>
<xsl:value-of select="route"/>
<xsl:text> </xsl:text>
<xsl:variable name="firstwrap">
<xsl:if test="route='air'">
<xsl:value-of select="Firstname"/>
<xsl:text> </xsl:text>
<xsl:value-of select="comments"/>
</xsl:if>
</xsl:variable>
<xsl:call-template name="text_wrapper">
<xsl:with-param name="Text" select="$firstwrap"/>
</xsl:call-template>
Output:
JOHNNNNNNNNNNNN MARKKKKKKKKKKKK air JOHNNNNNNNNNNNN
abcdefh abc ab
bcde abc dekf jl
MARKKKKKKKKKKKK abcdefh abc ab bcde abc dekf jl
Expected out:
JOHNNNNNNNNNNNN MARKKKKKKKKKKKK air JOHNNNNNNNNNNNN abcdefh abc ab
bcde abc dekf jl MARKKKKKKKKKKKK abcdefh abc abbcde abc dekf jl
Please help me to sort out my problem or tell me Is it possible in XSLT?
I'm not sure what exactly your problem is (I cannot see any significant difference between output you got and output you expected). But I think it is possible make it simpler. I prepared some testing input xml (just very simple for demonstration).
<?xml version="1.0" encoding="UTF-8"?>
<Input>
<Line>Some long text is on the first line.</Line>
<Line>Some longer text is on the second line.</Line>
<Line>But the longest text occures on the third line.</Line>
</Input>
In following xslt I store the result of processing of each line (i.e. copy of its text and append additional text based on some conditions) into a variable. Then I wrap this variable at once using a user function (it could be done with named template as well).
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:my="my-ns">
<xsl:output method="text" />
<xsl:variable name="newLineCharacter" select="'
'" />
<xsl:variable name="maxLineWidth" select="50" />
<xsl:template match="/">
<xsl:apply-templates select="Input/Line" />
</xsl:template>
<xsl:template match="Line">
<!-- Process the line and store the result into variable-->
<xsl:variable name="processedText">
<xsl:value-of select="." />
<xsl:text> </xsl:text>
<xsl:if test="position() >= 1">
<xsl:text>First condition is true. </xsl:text>
</xsl:if>
<xsl:if test="position() >= 2">
<xsl:text>Second condition is true. </xsl:text>
</xsl:if>
<xsl:if test="position() >= 3">
<xsl:text>Third condition is true. </xsl:text>
</xsl:if>
<!-- et cetera, et cetera ...-->
</xsl:variable>
<!-- Wrap the text stored in a variable -->
<xsl:value-of select="my:wrapText($processedText, $maxLineWidth)" />
</xsl:template>
<xsl:function name="my:wrapText">
<xsl:param name="textToBeWrapped" />
<xsl:param name="maximumWidth" />
<xsl:value-of select="substring($textToBeWrapped,1,$maximumWidth)" />
<xsl:value-of select="$newLineCharacter" />
<xsl:if test="string-length($textToBeWrapped) > $maximumWidth">
<!-- Recursive call of my:wrapText to wrap the rest of the text -->
<xsl:value-of select="my:wrapText(substring($textToBeWrapped,$maximumWidth+1), $maximumWidth)" />
</xsl:if>
</xsl:function>
</xsl:stylesheet>
And the output is
Some long text is on the first line. First conditi
on is true.
Some longer text is on the second line. First cond
ition is true. Second condition is true.
But the longest text occures on the third line. Fi
rst condition is true. Second condition is true. T
hird condition is true.
I hope it will meet your needs.

Resources