Need to dynamically change the simple-page-master's master-name - xslt

I have an xml document as shown below. Each repeating doc is a page in PDF file
<AFPXMLFile>
<docs>
<regList>
<region>1</region>
<secList>
<col>1</col>
<lines></lines>
</secList>
</regList>
<regList>
<region>2</region>
<secList>
<col>2</col>
<lines>
<line>IBM BELGIUM xxx</line>
<line>xxxxxx</line>
<line>xxxx</line>
</lines>
</secList>
</regList>
<regList></regList>
<regList></regList>
</docs>
<docs></docs>
</AFPXMLFile>
My XSL is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"
exclude-result-prefixes="fo">
<xsl:template match="AFPXMLFile">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master page-width="21cm" page-height="29.7cm" margin-top="1.27cm" margin-bottom="1.27cm" margin-left="1.75cm" master-name="A4">
<fo:region-body margin-top="1mm" margin-bottom="1mm"/>
<fo:region-before extent="0mm"/>
<fo:region-after extent="0mm"/>
<fo:region-start writing-mode="tb-rl" precedence="true" extent="10mm" />
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4" font-family="sans-serif">
<xsl:for-each select="docs">
<xsl:for-each select="./regList">
<xsl:choose>
<xsl:when test="region = 1">
<fo:static-content flow-name="xsl-region-before">
<xsl:for-each select="./secList/lines">
<xsl:for-each select="node()">
<fo:block font-size="8pt" color="purple">
<xsl:value-of select="."/>
</fo:block>
</xsl:for-each>
</xsl:for-each>
</fo:static-content>
</xsl:when>
<xsl:when test="region = 2">
<fo:static-content flow-name="xsl-region-start">
<xsl:for-each select="./secList/lines">
<xsl:for-each select="node()">
<fo:block font-size="4pt" padding-before="4pt" text-align="left" color="green">
<xsl:value-of select="."/>
</fo:block>
</xsl:for-each>
</xsl:for-each>
</fo:static-content>
</xsl:when>
<xsl:when test="region = 3">
<fo:static-content flow-name="xsl-region-body">
<xsl:for-each select="./secList/lines">
<xsl:for-each select="node()">
<fo:block font-size="8pt" color="blue">
<xsl:value-of select="."/>
</fo:block>
</xsl:for-each>
</xsl:for-each>
</fo:static-content>
</xsl:when>
<xsl:when test="region = 4">
<fo:flow flow-name="xsl-region-after">
<xsl:for-each select="./secList">
<xsl:for-each select="./lines">
<xsl:for-each select="node()">
<fo:block font-size="8pt" color="orange">
<xsl:value-of select="."/>
</fo:block>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</fo:flow>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:for-each>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>
When I run the transformation I get the following error:
org.apache.fop.fo.ValidationException: For "fo:page-sequence", "fo:static-content" must be declared before "fo:flow"! (No context info available)
This I suspect because it is repeating the static content region for each page. So I believe I need to change the simple-page-master:master-name for every page
I need help with that.

According to the XSL-FO recommendation, the contents of 'fo:page-sequence' is:
(title?,folio-prefix?,folio-suffix?,static-content*,flow+)
which means that all the fo:static-content elements must be before the fo:flow elements.
Your stylesheet dynamically creates either fo:static-content (if region is 1, 2 or 3) or fo:flow (if region is 4). From the reduced input file in your question it is not possible to see whether the regList elements are alway correctly sorted, so that they produce a valid output when sequentially processed.
Moreover, as each docs element represents a different document with different headers/footers, you have to create distinct fo:page-sequences instead of a single one (otherwise you get too many static contents and flows for a single page sequence):
<xsl:for-each select="docs">
<fo:page-sequence master-reference="A4" font-family="sans-serif">
<xsl:for-each select="./regList">
....
</xsl:for-each>
</fo:page-sequence>
</xsl:for-each>
Moreover, there is a strange thing in the stylesheet: you map an fo:static-content to the xsl-region-body region, and the fo:flow to the xsl-region-after region, which is quite unusual. If the "real" content for the body region is the one with region = 3, you must process region 1, 2 and 4 first, and then region 3:
<xsl:for-each select="docs">
<fo:page-sequence master-reference="A4" font-family="sans-serif">
<!-- create static contents -->
<xsl:apply-templates select="./regList[region != '3']"/>
<!-- create flow -->
<xsl:apply-templates select="./regList[region = '3']"/>
</fo:page-sequence>
</xsl:for-each>
with an additional template to match reglist:
<xsl:template match="regList">
<xsl:choose>
<xsl:when test="region = '1'">
<fo:static-content flow-name="xsl-region-before">
<xsl:for-each select="./secList/lines">
<xsl:for-each select="node()">
<fo:block font-size="8pt" color="purple">
<xsl:value-of select="."/>
</fo:block>
</xsl:for-each>
</xsl:for-each>
</fo:static-content>
</xsl:when>
<xsl:when test="region = '2'">
<fo:static-content flow-name="xsl-region-start">
<xsl:for-each select="./secList/lines">
<xsl:for-each select="node()">
<fo:block font-size="4pt" padding-before="4pt" text-align="left" color="green">
<xsl:value-of select="."/>
</fo:block>
</xsl:for-each>
</xsl:for-each>
</fo:static-content>
</xsl:when>
<xsl:when test="region = '3'">
<fo:flow flow-name="xsl-region-body">
<xsl:for-each select="./secList/lines">
<xsl:for-each select="node()">
<fo:block font-size="8pt" color="blue">
<xsl:value-of select="."/>
</fo:block>
</xsl:for-each>
</xsl:for-each>
</fo:flow>
</xsl:when>
<xsl:when test="region = '4'">
<fo:static-content flow-name="xsl-region-after">
<xsl:for-each select="./secList">
<xsl:for-each select="./lines">
<xsl:for-each select="node()">
<fo:block font-size="8pt" color="orange">
<xsl:value-of select="."/>
</fo:block>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</fo:static-content>
</xsl:when>
</xsl:choose>
</xsl:template>
or several, smaller templates:
<xsl:template match="reglist[region = '1']">
<fo:static-content flow-name="xsl-region-before">
<xsl:for-each select="./secList/lines">
<xsl:for-each select="node()">
<fo:block font-size="8pt" color="purple">
<xsl:value-of select="."/>
</fo:block>
</xsl:for-each>
</xsl:for-each>
</fo:static-content>
</xsl:template>
<xsl:template match="reglist[region = '2']">
...
</xsl:template>
...

Related

PDF Alignment issues when upgrading from fop-0.95 to fop-2.3

I'm new to the XSLT FO world and came across an issue. I have my XSLT that works well with the fop-0.95 processor and generates the PDF, but after I upgraded to fop-2.3, it left my first page blank and started the PDF body from the second page (my PDF has a header that appears fine on the first page).
I figured out where the issue was, and it was because I had the margin-top value set to 3 inches in the "fo:region-body" tag within the "fo:layout-master-set" (please see screenshot). I had to change the margin-top from 3 inches to 2.5 inches for the body of my PDF to appear like it was while using fop-0.95.
<?xml version="1.0" encoding="UTF-8"?>
<!--Designed and generated by Altova StyleVision Enterprise Edition 2013 (x64) - see http://www.altova.com/stylevision for more information.-->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:altova="http://www.altova.com" xmlns:altovaext="http://www.altova.com/xslt-extensions" xmlns:clitype="clitype" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:iso4217="http://www.xbrl.org/2003/iso4217" xmlns:ix="http://www.xbrl.org/2008/inlineXBRL" xmlns:java="java" xmlns:link="http://www.xbrl.org/2003/linkbase" xmlns:sps="http://www.altova.com/StyleVision/user-xpath-functions" xmlns:xbrldi="http://xbrl.org/2006/xbrldi" xmlns:xbrli="http://www.xbrl.org/2003/instance" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg" exclude-result-prefixes="altova altovaext clitype fn iso4217 ix java link sps xbrldi xbrli xlink xs xsi">
<xsl:output version="1.0" method="xml" encoding="UTF-8" indent="no"/>
<xsl:param name="SV_OutputFormat" select="'PDF'"/>
<xsl:variable name="XML" select="/"/>
<xsl:variable name="fo:layout-master-set">
<fo:layout-master-set>
<fo:simple-page-master master-name="page-master-0-even" margin-left="0.50in" margin-right="0.50in" page-height="11in" page-width="8.50in" margin-top="0.30in" margin-bottom="0.30in">
<fo:region-body margin-top="0.45in" margin-bottom="0.45in" column-count="1" column-gap="0.50in"/>
<fo:region-before region-name="even-page-header" overflow="hidden" extent="0.45in"/>
<fo:region-after region-name="even-page-footer" overflow="hidden" extent="0.45in"/>
</fo:simple-page-master>
<fo:simple-page-master master-name="page-master-0-odd" margin-left="0.50in" margin-right="0.50in" page-height="11in" page-width="8.50in" margin-top="0.30in" margin-bottom="0.30in">
<fo:region-body margin-top="0.45in" margin-bottom="0.45in" column-count="1" column-gap="0.50in"/>
<fo:region-before region-name="odd-page-header" overflow="hidden" extent="0.45in"/>
<fo:region-after region-name="odd-page-footer" overflow="hidden" extent="0.45in"/>
</fo:simple-page-master>
<fo:simple-page-master master-name="page-master-0-even-first" margin-left="0.50in" margin-right="0.50in" page-height="11in" page-width="8.50in" margin-top="0.30in" margin-bottom="0.30in">
<fo:region-body margin-top="3in" margin-bottom="0.45in" column-count="1" column-gap="0.50in"/>
<fo:region-before region-name="even-page-header-first" overflow="hidden" extent="3in"/>
<fo:region-after region-name="even-page-footer" overflow="hidden" extent="0.45in"/>
</fo:simple-page-master>
<fo:simple-page-master master-name="page-master-0-odd-first" margin-left="0.50in" margin-right="0.50in" page-height="11in" page-width="8.50in" margin-top="0.30in" margin-bottom="0.30in">
<fo:region-body margin-top="3in" margin-bottom="0.45in" column-count="1" column-gap="0.50in"/>
<fo:region-before region-name="odd-page-header-first" overflow="hidden" extent="3in"/>
<fo:region-after region-name="odd-page-footer" overflow="hidden" extent="0.45in"/>
</fo:simple-page-master>
<fo:page-sequence-master master-name="page-master-0">
<fo:repeatable-page-master-alternatives>
<fo:conditional-page-master-reference master-reference="page-master-0-even-first" odd-or-even="even" page-position="first"/>
<fo:conditional-page-master-reference master-reference="page-master-0-odd-first" odd-or-even="odd" page-position="first"/>
<fo:conditional-page-master-reference master-reference="page-master-0-even" odd-or-even="even"/>
<fo:conditional-page-master-reference master-reference="page-master-0-odd" odd-or-even="odd"/>
</fo:repeatable-page-master-alternatives>
</fo:page-sequence-master>
</fo:layout-master-set>
</xsl:variable>
<xsl:variable name="altova:nPxPerIn" select="96"/>
<xsl:template match="/">
<fo:root>
<xsl:copy-of select="$fo:layout-master-set"/>
<fo:declarations>
<x:xmpmeta xmlns:x="adobe:ns:meta/">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/">
<xmp:CreatorTool>Altova StyleVision Enterprise Edition 2013 (x64) (http://www.altova.com)</xmp:CreatorTool>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
</fo:declarations>
<fo:page-sequence force-page-count="no-force" master-reference="page-master-0" initial-page-number="auto" format="1">
<fo:static-content flow-name="odd-page-header-first">
<fo:block-container overflow="hidden" display-align="before">
<fo:block>
<xsl:for-each select="$XML">
<xsl:for-each select="DOCUMENT">
<xsl:for-each select="DATA">
<xsl:for-each select="STRUCT">
<xsl:for-each select="FIELD[FNAME=&apos;nfHeaderDtls&apos;]">
<xsl:for-each select="STRUCT">
<fo:block-container font-family="Arial" font-size="10pt" width="7.490000in" height="3.000000in" overflow="hidden">
<fo:block-container absolute-position="absolute" font-family="Arial" font-size="9pt" height="1.21in" left="4.55in" top="1.75in" width="2.90in" overflow="hidden">
<fo:block>
<xsl:for-each select="FIELD[FNAME=&apos;Name&apos;]">
<xsl:for-each select="VALUE">
<xsl:variable name="value-of-template_1">
<xsl:apply-templates/>
</xsl:variable>
<xsl:choose>
<xsl:when test="contains(string($value-of-template_1),'​')">
<fo:block>
<xsl:copy-of select="$value-of-template_1"/>
</fo:block>
</xsl:when>
<xsl:otherwise>
<fo:inline>
<xsl:copy-of select="$value-of-template_1"/>
</fo:inline>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:for-each>
<fo:block/>
</fo:block>
</fo:block-container>
</fo:block-container>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</fo:block>
</fo:block-container>
</fo:static-content>
<fo:static-content flow-name="even-page-header-first">
<fo:block-container overflow="hidden" display-align="before">
<fo:block>
<xsl:for-each select="$XML">
<xsl:for-each select="DOCUMENT">
<xsl:for-each select="DATA">
<xsl:for-each select="STRUCT">
<xsl:for-each select="FIELD[FNAME=&apos;nfHeaderDtls&apos;]">
<xsl:for-each select="STRUCT">
<fo:block-container font-family="Arial" font-size="10pt" width="7.490000in" height="3.000000in" overflow="hidden">
<fo:block-container absolute-position="absolute" font-family="Arial" font-size="9pt" height="1.21in" left="4.55in" top="1.75in" width="2.90in" overflow="hidden">
<fo:block>
<xsl:for-each select="FIELD[FNAME=&apos;Name&apos;]">
<xsl:for-each select="VALUE">
<xsl:variable name="value-of-template_1">
<xsl:apply-templates/>
</xsl:variable>
<xsl:choose>
<xsl:when test="contains(string($value-of-template_1),'​')">
<fo:block>
<xsl:copy-of select="$value-of-template_1"/>
</fo:block>
</xsl:when>
<xsl:otherwise>
<fo:inline>
<xsl:copy-of select="$value-of-template_1"/>
</fo:inline>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:for-each>
<fo:block/>
</fo:block>
</fo:block-container>
</fo:block-container>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</fo:block>
</fo:block-container>
</fo:static-content>
<fo:static-content flow-name="odd-page-header">
<fo:block-container overflow="hidden" display-align="before">
<fo:block>
<xsl:for-each select="$XML">
<xsl:for-each select="DOCUMENT">
<xsl:for-each select="DATA">
<xsl:for-each select="STRUCT">
<xsl:for-each select="FIELD[FNAME=&apos;nfHeaderDtls&apos;]">
<xsl:for-each select="STRUCT">
<fo:block-container font-family="Arial" font-size="10pt" width="7.500000in" height="0.500000in" overflow="hidden">
<fo:block-container absolute-position="absolute" height="0.19in" left="0in" top="0in" width="2.78in" overflow="hidden">
<fo:block>
<fo:inline>
<xsl:text>Identifier: </xsl:text>
</fo:inline>
<xsl:for-each select="FIELD[FNAME=&apos;caseReference&apos;]">
<xsl:for-each select="VALUE">
<xsl:variable name="value-of-template_27">
<xsl:apply-templates/>
</xsl:variable>
<xsl:choose>
<xsl:when test="contains(string($value-of-template_27),'​')">
<fo:block>
<xsl:copy-of select="$value-of-template_27"/>
</fo:block>
</xsl:when>
<xsl:otherwise>
<fo:inline>
<xsl:copy-of select="$value-of-template_27"/>
</fo:inline>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:for-each>
</fo:block>
</fo:block-container>
</fo:block-container>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</fo:block>
</fo:block-container>
</fo:static-content>
<fo:static-content flow-name="even-page-header">
<fo:block-container overflow="hidden" display-align="before">
<fo:block>
<xsl:for-each select="$XML">
<xsl:for-each select="DOCUMENT">
<xsl:for-each select="DATA">
<xsl:for-each select="STRUCT">
<xsl:for-each select="FIELD[FNAME=&apos;nfHeaderDtls&apos;]">
<xsl:for-each select="STRUCT">
<fo:block-container font-family="Arial" font-size="10pt" width="7.500000in" height="0.500000in" overflow="hidden">
<fo:block-container absolute-position="absolute" height="0.19in" left="0in" top="0in" width="2.78in" overflow="hidden">
<fo:block>
<fo:inline>
<xsl:text>Identifier: </xsl:text>
</fo:inline>
<xsl:for-each select="FIELD[FNAME=&apos;caseReference&apos;]">
<xsl:for-each select="VALUE">
<xsl:variable name="value-of-template_27">
<xsl:apply-templates/>
</xsl:variable>
<xsl:choose>
<xsl:when test="contains(string($value-of-template_27),'​')">
<fo:block>
<xsl:copy-of select="$value-of-template_27"/>
</fo:block>
</xsl:when>
<xsl:otherwise>
<fo:inline>
<xsl:copy-of select="$value-of-template_27"/>
</fo:inline>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:for-each>
</fo:block>
</fo:block-container>
</fo:block-container>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</fo:block>
</fo:block-container>
</fo:static-content>
<fo:static-content flow-name="odd-page-footer">
<fo:block-container height="0.45in" overflow="hidden" display-align="after">
<fo:block>
<fo:block-container font-family="Arial" font-size="10pt" width="7.490000in" height="0.500000in" overflow="hidden">
<fo:block-container absolute-position="absolute" height="0.40in" left="0in" top="0in" width="4.04in" overflow="hidden">
<fo:block>
<fo:inline>
<xsl:text>My Test Form</xsl:text>
</fo:inline>
<fo:block/>
<fo:inline>
<xsl:text>Test Text</xsl:text>
</fo:inline>
</fo:block>
</fo:block-container>
<fo:block-container absolute-position="absolute" height="0.38in" left="4.82in" text-align="right" top="0in" width="2.63in" overflow="hidden">
<fo:block>
<fo:inline font-weight="bold">
<xsl:text>Page: </xsl:text>
</fo:inline>
<fo:page-number font-weight="bold"/>
<fo:inline font-weight="bold">
<xsl:text> of </xsl:text>
</fo:inline>
<fo:page-number-citation ref-id="SV_RefID_PageTotal" font-weight="bold"/>
</fo:block>
</fo:block-container>
</fo:block-container>
</fo:block>
</fo:block-container>
</fo:static-content>
<fo:static-content flow-name="even-page-footer">
<fo:block-container height="0.45in" overflow="hidden" display-align="after">
<fo:block>
<fo:block-container font-family="Arial" font-size="10pt" width="7.490000in" height="0.500000in" overflow="hidden">
<fo:block-container absolute-position="absolute" height="0.40in" left="0in" top="0in" width="4.04in" overflow="hidden">
<fo:block>
<fo:inline>
<xsl:text>My Test Form</xsl:text>
</fo:inline>
<fo:block/>
<fo:inline>
<xsl:text>Test Text</xsl:text>
</fo:inline>
</fo:block>
</fo:block-container>
<fo:block-container absolute-position="absolute" height="0.38in" left="4.82in" text-align="right" top="0in" width="2.63in" overflow="hidden">
<fo:block>
<fo:inline font-weight="bold">
<xsl:text>Page: </xsl:text>
</fo:inline>
<fo:page-number font-weight="bold"/>
<fo:inline font-weight="bold">
<xsl:text> of </xsl:text>
</fo:inline>
<fo:page-number-citation ref-id="SV_RefID_PageTotal" font-weight="bold"/>
</fo:block>
</fo:block-container>
</fo:block-container>
</fo:block>
</fo:block-container>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block>
<xsl:for-each select="$XML">
<xsl:for-each select="DOCUMENT">
<xsl:for-each select="DATA">
<xsl:for-each select="STRUCT">
<fo:block-container font-family="Arial" font-size="10pt" width="7.500000in" height="7.040000in" overflow="hidden">
<fo:block-container absolute-position="absolute" font-family="Arial" font-size="13pt" font-weight="bold" height="0.28in" left="0in" text-align="center" top="0in" width="7.46in" overflow="hidden">
<fo:block>
<fo:inline>
<xsl:text>Form Body Starts Here </xsl:text>
</fo:inline>
<xsl:for-each select="FIELD[FNAME=&apos;nfFormTitle&apos;]">
<xsl:for-each select="VALUE">
<xsl:variable name="value-of-template_28">
<xsl:apply-templates/>
</xsl:variable>
<xsl:choose>
<xsl:when test="contains(string($value-of-template_28),'​')">
<fo:block>
<xsl:copy-of select="$value-of-template_28"/>
</fo:block>
</xsl:when>
<xsl:otherwise>
<fo:inline>
<xsl:copy-of select="$value-of-template_28"/>
</fo:inline>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:for-each>
<fo:inline>
<xsl:text> Test Test</xsl:text>
</fo:inline>
</fo:block>
</fo:block-container>
</fo:block-container>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</fo:block>
<fo:block id="SV_RefID_PageTotal"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template name="altova:double-backslash">
<xsl:param name="text"/>
<xsl:param name="text-length"/>
<xsl:variable name="text-after-bs" select="substring-after($text, '\')"/>
<xsl:variable name="text-after-bs-length" select="string-length($text-after-bs)"/>
<xsl:choose>
<xsl:when test="$text-after-bs-length = 0">
<xsl:choose>
<xsl:when test="substring($text, $text-length) = '\'">
<xsl:value-of select="concat(substring($text,1,$text-length - 1), '\\')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(substring($text,1,$text-length - $text-after-bs-length - 1), '\\')"/>
<xsl:call-template name="altova:double-backslash">
<xsl:with-param name="text" select="$text-after-bs"/>
<xsl:with-param name="text-length" select="$text-after-bs-length"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="altova:MakeValueAbsoluteIfPixels">
<xsl:param name="sValue"/>
<xsl:variable name="sBeforePx" select="substring-before($sValue, 'px')"/>
<xsl:choose>
<xsl:when test="$sBeforePx">
<xsl:variable name="nLengthOfInteger">
<xsl:call-template name="altova:GetCharCountOfIntegerAtEndOfString">
<xsl:with-param name="sText" select="$sBeforePx"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="nPosOfInteger" select="string-length($sBeforePx) - $nLengthOfInteger + 1"/>
<xsl:variable name="nValuePx" select="substring($sBeforePx, $nPosOfInteger)"/>
<xsl:variable name="nValueIn" select="number($nValuePx) div number($altova:nPxPerIn)"/>
<xsl:variable name="nLengthBeforeInteger" select="string-length($sBeforePx) - $nLengthOfInteger"/>
<xsl:variable name="sRest">
<xsl:call-template name="altova:MakeValueAbsoluteIfPixels">
<xsl:with-param name="sValue" select="substring-after($sValue, 'px')"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="concat(substring($sBeforePx, 1, $nLengthBeforeInteger), string($nValueIn), 'in', $sRest)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$sValue"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="altova:GetCharCountOfIntegerAtEndOfString">
<xsl:param name="sText"/>
<xsl:variable name="sLen" select="string-length($sText)"/>
<xsl:variable name="cLast" select="substring($sText, $sLen)"/>
<xsl:choose>
<xsl:when test="number($cLast) >= 0 and number($cLast) <= 9">
<xsl:variable name="nResultOfRest">
<xsl:call-template name="altova:GetCharCountOfIntegerAtEndOfString">
<xsl:with-param name="sText" select="substring($sText, 1, $sLen - 1)"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$nResultOfRest + 1"/>
</xsl:when>
<xsl:otherwise>
<xsl:text>0</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Does anyone know why this is happening?
I have multiple PDFs with the same layout, so if I need to upgrade to fop-2.3 do I have to make this change to all of my PDFs?
EDIT- 1. Thank you for the comments and the answer. Sorry it took a while to reply back, as I was working on getting approvals to post this xslt.
2. I edited the xslt as it was too big to adhere to the word limit of this post. But it still has all the important parts like beginning of the PDF body etc.
Sorry, but the best way to work out why something is different between different versions of the same software is to look through the release notes for the releases since your older version.
FOP has release notes on its website. When I was confirming that, I found this at https://xmlgraphics.apache.org/fop/1.0/changes_1.0.html, which might be what you are looking for:
Allowing non-zero borders and padding on page regions when relaxed validation is turned on. Committed by LF.
If that is the cause, then the solution would be to remove the margin-top from the fo:simple-page-master. Otherwise, there's plenty more release notes for you to look through, I'm afraid.

Using node-set with Antenna House XSL-FO XSLT

I would like to use node-set() in Antenna House so I can access preceding-siblings in a sorted list. (I'm trying to follow this example: [using preceding-sibling with with xsl:sort)
I'm not sure what the syntax is for declaring the namespace to access node-set(). AH is not giving any errors, but my call to node-set() fails. I've tried:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" extension-element-prefixes="msxsl" version="1.0">
Here is the XML:
<illustratedPartsCatalog>
<figure id="fig1">...</figure>
<catalogSeqNumber assyCode="00" figureNumber="01" indenture="0" item="000" itemVariant="A" subSubSystemCode="0" subSystemCode="0" systemCode="00">
<itemSeqNumber itemSeqNumberValue="000">
<quantityPerNextHigherAssy>XX</quantityPerNextHigherAssy>
<partRef manufacturerCodeValue="00000" partNumberValue="11111-111">
</partRef>
<partSegment>
<itemIdentData>
<descrForPart>VALVE ASSEMBLY</descrForPart></itemIdentData>
</partSegment><applicabilitySegment><usableOnCodeAssy>X</usableOnCodeAssy>
</applicabilitySegment></itemSeqNumber></catalogSeqNumber>
<catalogSeqNumber>...</catalogSeqNumber>
<catalogSeqNumber>...</catalogSeqNumber>
<catalogSeqNumber>...</catalogSeqNumber>
<catalogSeqNumber>...</catalogSeqNumber>
<figure id="fig2">...</figure>
<catalogSeqNumber>...</catalogSeqNumber>
<catalogSeqNumber>...</catalogSeqNumber>
<catalogSeqNumber>...</catalogSeqNumber>
<catalogSeqNumber>...</catalogSeqNumber>
<catalogSeqNumber>...</catalogSeqNumber>
</illustratedPartsCatalog>
XSLT:
<xsl:variable name="sortedCSN">
<xsl:for-each select="illustratedPartsCatalog/catalogSeqNumber">
<xsl:sort select="concat(itemSeqNumber/partRef/#partNumberValue, #figureNumber,#item)"/>
<xsl:copy-of select="." />
</xsl:for-each>
</xsl:variable>
<xsl:template name="SortParts2" >
<xsl:for-each select="msxsl:node-set($sortedCSN)/catalogSeqNumber">
<xsl:sort select="concat(itemSeqNumber/partRef/#partNumberValue, #figureNumber,#item)"/>
<xsl:call-template name="catalogSeqNumber-NI">
<xsl:with-param name="figNo" select="concat(#figureNumber,#figureNumberVariant)"/>
<xsl:with-param name="prfigNo" select="concat(preceding-sibling::catalogSeqNumber/#figureNumber,preceding-sibling::catalogSeqNumber/#figureNumberVariant)" />
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:template name="catalogSeqNumber-NI">
<xsl:param name="figNo"/>
<xsl:param name="prfigNo" />
<fo:table-row keep-together.within-page="always" wrap-option="wrap">
<fo:table-cell xsl:use-attribute-sets="table.cell.padding" text-transform="uppercase" wrap-option="wrap">
<fo:block wrap-option="wrap">
<xsl:value-of select=" ./itemSeqNumber/partRef/#partNumberValue"/>
</fo:block>
</fo:table-cell>
<fo:table-cell xsl:use-attribute-sets="table.cell.padding" text-align="start">
<xsl:choose>
<xsl:when test="$figNo">
<fo:block>
<xsl:text> </xsl:text><xsl:value-of select="$figNo"/><xsl:text> </xsl:text> <xsl:value-of select="$prfigNo"/>
</fo:block>
</xsl:when>
<xsl:otherwise>
<fo:block />
</xsl:otherwise>
</xsl:choose>
</fo:table-cell>
<fo:table-cell xsl:use-attribute-sets="table.cell.padding" text-align="start">
<fo:block>
<xsl:if test="./itemSeqNumber/partLocationSegment/notIllustrated">
<xsl:text>-</xsl:text>
</xsl:if>
<xsl:choose>
<xsl:when test="#item">
<xsl:variable name="itemNo">
<xsl:call-template name="suppressZero" >
<xsl:with-param name="pText" select="#item"/>
</xsl:call-template>
</xsl:variable>
<xsl:text> </xsl:text>
<xsl:value-of select="concat($itemNo,#itemVariant)"/>
</xsl:when>
<xsl:otherwise />
</xsl:choose>
</fo:block>
</fo:table-cell>
<fo:table-cell xsl:use-attribute-sets="table.cell.padding">
<fo:block>
<xsl:value-of select="./itemSeqNumber/quantityPerNextHigherAssy"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
</xsl:template>
I think the default for Antenna House on Windows is to use MSXML so the attempt with xmlns:msxsl="urn:schemas-microsoft-com:xslt" is fine as far as using the node-set extension function.
I think you simply need to change the XSLT to
<xsl:variable name="sortedCSN">
<xsl:for-each select="illustratedPartsCatalog/catalogSeqNumber">
<xsl:sort select="concat(itemSeqNumber/partRef/#partNumberValue, #figureNumber,#item)"/>
<xsl:copy-of select="." />
</xsl:for-each>
</xsl:variable>
<xsl:template name="SortParts2" >
<xsl:for-each select="msxsl:node-set($sortedCSN)/catalogSeqNumber">
<xsl:sort select="concat(itemSeqNumber/partRef/#partNumberValue, #figureNumber,#item)"/>
<xsl:call-template name="catalogSeqNumber-NI">
<xsl:with-param name="figNo" select="concat(#figureNumber,#figureNumberVariant)"/>
<xsl:with-param name="prfigNo" select="concat(preceding-sibling::catalogSeqNumber/#figureNumber,preceding-sibling::catalogSeqNumber/#figureNumberVariant)" />
</xsl:call-template>
</xsl:for-each>
</xsl:template>
to make sense with the input you have shown (as far as you have shown it, can't judge all those xsl:sort attempts without seeing the data to be sorted).
On the other hand, if you get errors about the stylesheet not being correct XSLT or XML, you would better show us a minimal but complete stylesheet allowing us to reproduce the problem.

Table of Contents XSL-FO XSLT 1.0

XML:
<levelledPara><title>Tools List and Tool Illustrations</title>
<levelledPara><title>General</title>
<levelledPara><para>The special tools, fixtures, and equipment needed.</para></levelledPara></levelledPara>
XSLT:
<xsl:template match="levelledPara" name="levelledPara" mode="tocdm">
<xsl:if test="*[self::title] and not(parent::*[self::levelledPara])">
<xsl:variable name="id">
<xsl:call-template name="para.id"/>
</xsl:variable>
<fo:table-row>
<fo:table-cell xsl:use-attribute-sets="table.cell.padding1" number-columns-spanned="2">
<fo:block text-transform="capitalize" text-align-last="justify" text-indent="21mm">
<xsl:number count="levelledPara" from="content" level="multiple" format="1.1.1.1.1"/>
<xsl:text>   </xsl:text>
<xsl:value-of select="title" /><fo:leader leader-pattern="dots"/><fo:basic-link internal-destination="{$id}"><fo:page-number-citation ref-id="{$id}"/></fo:basic-link>
</fo:block>
</fo:table-cell>
</fo:table-row>
</xsl:if>
</xsl:template>
<xsl:template match="levelledPara">
<fo:list-block
provisional-distance-between-starts="21mm"
provisional-label-separation="4pt">
<fo:list-item space-after="8pt" space-before="13pt" start-indent="0pt">
<xsl:variable name="id">
<xsl:if test="*[self::title] and not(parent::*[self::levelledPara])">
<xsl:call-template name="para.id"/>
</xsl:if>
</xsl:variable>
<fo:list-item-label
end-indent="label-end()"
text-align="start">
<fo:block font-weight="bold" id="{$id}">
<xsl:if test="not(./table)">
<xsl:number count="levelledPara" from="content" level="multiple" format="1.1.1.1.1"/>
</xsl:if>
</fo:block>
</fo:list-item-label>
<fo:list-item-body
start-indent="body-start()">
<xsl:apply-templates/>
</fo:list-item-body>
</fo:list-item>
</fo:list-block>
</xsl:template>
<xsl:template name="para.id">
<xsl:param name="object" select="."/>
<xsl:apply-templates select="ancestor::dmodule/identAndStatusSection/dmAddress/dmIdent/dmCode"/>
<xsl:choose>
<xsl:when test="$object/#id">
<xsl:value-of select="$object/#id"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(count(ancestor::node()),'00000000',count(preceding::node()))"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
The first titled levelledPara should be included in the Table of Contents. In my sample markup none have IDs. The page number wasn't resolving because I forgot to assign an id to the fo:block for levelledPara.
You've shown the XSLT for the table of contents. The ID in the TOC should match an ID in the main text of your document.
So the template match="levelledPara" should contain a block that sets the ID:
<xsl:variable name="lpcode"><xsl:value-of select="$dmcode" /><xsl:value-of select="generate-id(.)" /></xsl:variable>
<fo:block id="{$lpcode}">

Grid-table format in XSLT

I have the following XML:
<Pattern name="Form" Date="12/18/2015 3:25 AM CST">
Swap_Conversion
<CurrentLocale />
<Patterns>
<Pattern name="Section">
Swap_Conversion
<Patterns>
<Pattern name="GroupResult" status="AUTH" inputType="19">
Ultrasound Duration
<Patterns>
<Pattern name="GridDTA">23350691</Pattern>
<Pattern name="GridDTA">56468381</Pattern>
<Pattern name="GridDTA">20218422</Pattern>
<Pattern name="GridDTA">21058661</Pattern>
<Pattern name="GridDTA">4156900</Pattern>
<Pattern name="GridDTA">20008930</Pattern>
<Pattern name="GridDTA">21197198</Pattern>
</Patterns>
<Patterns>
<Pattern name="GroupResult" status="AUTH" inputType="">
Ear Irrigation Solution
<Patterns />
<Patterns>
<Pattern name="CodedResult" status="AUTH" display="Ace Bandage :" taskAssayCode="23350691">2 inch</Pattern>
</Patterns>
</Pattern>
</Patterns>
<Patterns>
<Pattern name="GroupResult" status="AUTH" inputType="">
Frame Order Priority
<Patterns />
<Patterns>
<Pattern name="CodedResult" status="AUTH" display="Ace Bandage :" taskAssayCode="23350691">3 inch</Pattern>
</Patterns>
</Pattern>
</Patterns>
</Pattern>
</Patterns>
</Pattern>
</Patterns>
</Pattern
Currently I have the transpose which look something like:
But I want it to look something like:
Currently I had tried with which worked for transpose:
<xsl:choose>
<xsl:when test="$inputType='19'"
<xsl:variable name="groupNodeSet" select="Patterns/Pattern[#name='GroupResult']"/>
<xsl:for-each select="$groupNodeSet[position() <= ((last() + $tablecolumns - 1) div $tablecolumns)]">
<!-- loopCount indicates which table of the multiple tables that a grid control may be split into that we are currently generating-->
<xsl:variable name="loopCount" select="position()"/>
<fo:table border="1pt solid black">
<fo:table-column/>
<fo:table-column/>
<fo:table-column/>
<fo:table-body>
<fo:table-row>
<fo:table-cell border-width="thin">
<fo:block/>
</fo:table-cell>
<fo:table-cell>
<xsl:if test="$groupNodeSet[position()=((($loopCount - 1) * $tablecolumns) + 1)]">
<xsl:attribute name="border-width">
<xsl:text>thin</xsl:text>
</xsl:attribute>
</xsl:if>
<fo:block font-size="{$regularfontsize}" font-family="sans-serif" text-align="left" font-style="italic">
<xsl:value-of select="$groupNodeSet[position()=((($loopCount - 1) * $tablecolumns) + 1)]/text()"/>
</fo:block>
</fo:table-cell>
<fo:table-cell>
<xsl:if test="$groupNodeSet[position()=((($loopCount - 1) * $tablecolumns) + 2)]">
<xsl:attribute name="border-width">
<xsl:text>thin</xsl:text>
</xsl:attribute>
</xsl:if>
<fo:block font-size="{$regularfontsize}" font-family="sans-serif" text-align="left" font-style="italic">
<xsl:value-of select="$groupNodeSet[position()=((($loopCount - 1) * $tablecolumns) + 2)]/text()"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
<xsl:for-each select="../../Patterns/Pattern[#name='GridDTA' and ../..//#taskAssayCode=text()]">
<xsl:variable name="taskassay">
<xsl:value-of select="node()"/>
</xsl:variable>
<fo:table-row>
<fo:table-cell border-width="thin">
<fo:block>
<xsl:value-of select="../..//Pattern/#display[../..//Pattern/#taskAssayCode=$taskassay]"/>
</fo:block>
</fo:table-cell>
<xsl:call-template name="GenerateGridTableCells">
<xsl:with-param name="count" select="1"/>
<xsl:with-param name="maxcount" select="$tablecolumns"/>
<xsl:with-param name="taskassay" select="$taskassay"/>
<xsl:with-param name="groupNodeSet" select="$groupNodeSet"/>
<xsl:with-param name="rowNumber" select="$loopCount"/>
</xsl:call-template>
</fo:table-row>
</xsl:for-each>
</fo:table-body>
</fo:table>
</xsl:for-each>
</xsl:when>
</xsl:choose>
I have tried multiple approach for normal one (not the transpose) which isn't working for.
Can anyone help me in having the grid matrix without transpose for the above XML?
Since you're using XSLT 1.0, you're stuck with using Meunchian grouping (muenchian grouping, http://www.jenitennison.com/xslt/grouping/muenchian.html). Using XSLT 2.0 would have made it easier.
The version below can cope with a variations in the 'CodedResult' within each 'GroupResult'.
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:variable name="regularfontsize" select="'12pt'"/>
<xsl:output indent="yes" />
<xsl:key name="coded-results"
match="Pattern[#name = 'CodedResult'][#status = 'AUTH']"
use="#display" />
<xsl:template match="/">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:axf="http://www.antennahouse.com/names/XSL/Extensions">
<fo:layout-master-set>
<fo:simple-page-master master-name="a">
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="a">
<fo:flow flow-name="xsl-region-body">
<xsl:apply-templates select="Pattern/Patterns/Pattern[#name = 'Section']/Patterns/Pattern" />
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:variable name="inputType" select="'19'" />
<xsl:template match="Pattern[#inputType = '19']">
<xsl:variable name="all-coded-results"
select="Patterns/Pattern[#inputType = '']/Patterns/Pattern[#name = 'CodedResult']
[count(. | key('coded-results', #display)[1]) = 1]" />
<fo:table border="1pt solid black">
<fo:table-column/>
<xsl:for-each
select="$all-coded-results">
<fo:table-column/>
</xsl:for-each>
<fo:table-body>
<fo:table-row>
<fo:table-cell />
<xsl:for-each
select="$all-coded-results">
<xsl:sort />
<fo:table-cell>
<fo:block>
<xsl:value-of select="#display" />
</fo:block>
</fo:table-cell>
</xsl:for-each>
</fo:table-row>
<xsl:apply-templates select="Patterns/Pattern[#name = 'GroupResult']">
<xsl:with-param name="all-coded-results" select="$all-coded-results" />
</xsl:apply-templates>
</fo:table-body>
</fo:table>
</xsl:template>
<xsl:template match="Pattern[#name = 'GroupResult'][#inputType = '']">
<xsl:param name="all-coded-results" />
<fo:table-row>
<fo:table-cell>
<fo:block>
<xsl:value-of select="normalize-space(text())" />
</fo:block>
</fo:table-cell>
<xsl:variable name="this-pattern" select="." />
<xsl:for-each
select="$all-coded-results">
<xsl:sort />
<xsl:variable name="this-result" select="."/>
<fo:table-cell>
<xsl:if test="$this-pattern/Patterns/Pattern[#display = $this-result/#display]">
<fo:block>
<xsl:value-of select="$this-pattern/Patterns/Pattern[#display = $this-result/#display]" />
</fo:block>
</xsl:if>
</fo:table-cell>
</xsl:for-each>
</fo:table-row>
</xsl:template>
</xsl:stylesheet>

Prevent blank page on last side in xsl fo

i'm using xsl fo and apache fop to generate pdf documents. i have different fo page-sequences (coverpage, toc, imprint and the "main content").
In the main content i handle the datas from the xml file, it's fine.
At the beginning of the main content i started count the pages and show this in the bottom/right. With this i had a problem that it show a blank page before the "main content", i could resolve this issue with adding "force-page-count="no-force" on the page-sequence before.
But i have a blank page after the main-content sequence, any idea how can i solve this?
page-sequence before main-content:
<fo:page-sequence master-reference="imprint" force-page-count="no-force">
...
</fo:page-sequence>
main-content:
<fo:page-sequence master-reference="per-Gruppe" initial-page-number="1">
<fo:static-content flow-name="header">
<xsl:call-template name="doc-header" match=""/>
<fo:block/>
</fo:static-content>
<fo:static-content flow-name="footer">
<xsl:call-template name="doc-footer"/>
<fo:block/>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<xsl:for-each select="//lb">
<xsl:call-template name="Kapitel" select="name"/>
<xsl:for-each select="per-group/pe">
<xsl:call-template name="st.Table" select="."/>
</xsl:for-each>
<xsl:for-each select="cu-group/cu">
<xsl:call-template name="st.Table" select="."/>
</xsl:for-each>
<xsl:if test="position()=last()">
<fo:block id="lastpage"/>
</xsl:if>
</xsl:for-each>
</fo:flow>
</fo:page-sequence>
Any suggestions?
Thanks.
OK, i solve it. i do the following steps.
i put the for each loop outside of the page-sequence.
then i enclose the sequence with an xsl:choose, in the xsl:choose i check the position
with the result i call the template page-sequence and -> "st.table" template
in the template (st.table) i check the result and if it the last position i set the lastpage and i prevent to set the page-break-after property (this was the reason why i get a blank page at the end)
page-sequence:
<xsl:for-each select="//lb">
<xsl:choose>
<xsl:when test="position() = 1">
<fo:page-sequence master-reference="per-Gruppe" initial-page-number="1">
...
</fo:page-sequence>
</xsl:when>
<xsl:otherwise>
<fo:page-sequence master-reference="per-Gruppe">
...
<fo:flow flow-name="xsl-region-body">
...
<xsl:for-each select="cu-group/cu">
<xsl:call-template name="st.Table" select=".">
<xsl:with-param name="last_pos" select="$last_pos" />
</xsl:call-template>
</xsl:for-each>
</fo:flow>
</fo:page-sequence>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
template:
<xsl:template name="st.Table" match=".">
<xsl:param name="last_pos" select="false()" />
...
<xsl:if test="$last_pos">
<fo:block id="lastpage"/>
</xsl:if>
<xsl:if test="$last_pos=false()">
<fo:block page-break-after="always" />
</xsl:if>
</xsl:template>