How to keep my topics printing consecutively, without an empty page after each topic - page-break

DITA 3.6
Oxygen XML Editor 23.1
The "DITA for Print" book nor any other source, so far, has helped me produce a pdf where the topics are consecutive rather than having a blank page after them. To each topicref in the ditamap, I added outputclass="page-break-avoid". To each topic element in each file, I added outputclass="page-break-avoid".
Should I add something in an xsl file? Can you point me to the answer?

The blank page is generated from the definition fo:page-sequence/#force-page-number property.
To change not to generate blank-page, you can override org.dita.pdf2/cfg/fo/attrs/commons-attr.xsl.
<xsl:attribute-set name="__force__page__count">
<xsl:attribute name="force-page-count">
<xsl:choose>
<xsl:when test="/*[contains(#class, ' bookmap/bookmap ')]">
<xsl:value-of select="'even'"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'auto'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:attribute-set>
Change the value even to auto will satisfy your needs.
Steps to customize
I'm not familiar with PDF2 plug-in. So this may not the standard way. But I could customize it by following steps.
Make customization XSL file
[DITA-OT]/plugins/org.dita.pdf2/Customization/fo/attrs/commons-attr.xsl
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:rx="http://www.renderx.com/XSL/Extensions"
version="2.0">
<xsl:attribute-set name="__force__page__count">
<xsl:attribute name="force-page-count">
<xsl:choose>
<xsl:when test="/*[contains(#class, ' bookmap/bookmap ')]">
<xsl:value-of select="'auto'"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'auto'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:attribute-set>
</xsl:stylesheet>
Include it into [DITA-OT]/plugins/org.dita.pdf2/Customization/fo/attrs/custom.xsl
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
version="2.0">
<xsl:include href="commons-attr.xsl"/>
</xsl:stylesheet>
Customize [DITA-OT]/plugins/org.dita.pdf2/Customization/catalog.xml
<?xml version="1.0" encoding="utf-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="system">
<!-- Custom attributes entry -->
<uri name="cfg:fo/attrs/custom.xsl" uri="fo/attrs/custom.xsl"/>
</catalog>
Specify customization.dir property with [DITA-OT]\plugins\org.dita.pdf2\Customization in Oxygen transformation scenario.
Apply transformation scenario from Oxygen.
I've got the following temp/topic.fo. The fo:page-sequence/#force-page-count became auto and in the result PDF, the redundant blank pages are removed.

Related

How to map value of one xml to another one in Python

I need to make XML out of response in XML format.
For some fields, I need to be able to change the value. I also need to remove all fields that are not mapped.
I get responses that look like this
<response>
<DOCUMENTS>
<DOCUMENT>
<KODA>AA</KODA>
<ITEMS>
<ITEM>B</ITEM>
<ITEM>C</ITEM>
</ITEMS>
</DOCUMENT>
</DOCUMENTS>
</response>
and want to make of it something that looks like below
<EXPORT>
<DOCUMENTS>
<DOCUMENT>
<KODDZ>SS</KODDZ>
<VALUES>
<VALUE>B</VALUE>
<VALUE>C</VALUE>
</VALUES>
</DOCUMENT>
</DOCUMENTS>
</EXPORT>
I have been trying using the XSLT example from this question but without success.
Basically what would be best for me would be a solution that takes some kind of map of fields for example:
map_of_values = {"response/DOCUMENTS/DOCUMENT/KODA":"EXPORT/DOCUMENTS/DOCUMENT/KODZA",
"response/DOCUMENTS/DOCUMENT/ITEMS/ITEM":EXPORT/DOCUMENTS/DOCUMENT/VALUES/VALUE}
What would be the best way to achieve a static map kind of solution?
In terms of XSLT you seem to want something along the lines of
<xsl:template match="response">
<EXPORT>
<xsl:apply-templates/>
</EXPORT>
</xsl:template>
<xsl:template match="KODA">
<KODDZ>
<xsl:apply-templates/>
</KODDZ>
</xsl:template>
<xsl:template match="KODA/text()[. = 'AA']">
<xsl:text>SS</xsl:text>
</xsl:template>
<xsl:template match="ITEMS">
<VALUES>
<xsl:apply-templates/>
</VALUES>
</xsl:template>
<xsl:template match="ITEM">
<VALUE>
<xsl:apply-templates/>
</VALUE>
</xsl:template>
plus the identity transformation template, of course.

"Reserved namespace" error occurs when chaining named templates with "xsl:original" in XSLT-3.0

I'm trying to chain named templates in XSLT 3.0 using the "xsl:original" feature, but I get a reserved-name namespace error.
As an example, I use a named template add-atts that is defined in two included stylesheets:
<?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="3.0">
<xsl:template match="/">
<root>
<xsl:apply-templates select="root/line"/>
</root>
</xsl:template>
<xsl:template match="line">
<xsl:copy>
<xsl:call-template name="add-atts"/> <!-- USED HERE -->
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
<xsl:import href="add-foo.xsl"/> <!-- DEFINED HERE -->
<xsl:import href="add-bar.xsl"/> <!-- DEFINED HERE -->
</xsl:stylesheet>
The first included stylesheet has a named template that adds a #foo attribute:
<?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="3.0">
<xsl:template name="add-atts">
<xsl:attribute name="att1">foo</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
The second included stylesheet has a named template of the same name (which takes precedence due to ordering) that adds a #bar attribute, then attempts to call the overridden template from the previous file:
<?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="3.0">
<xsl:template name="add-atts">
<xsl:attribute name="att2">bar</xsl:attribute>
<xsl:call-template name="xsl:original"/> <!-- HERE -->
</xsl:template>
</xsl:stylesheet>
When I run this on the following input file
<root>
<line>1</line>
<line>2</line>
<line>3</line>
</root>
I get the following error:
$ java -jar .../Saxon-HE-9.9.1-4.jar in.xml trans.xsl
Static error in xsl:call-template/#name on line 8 column 46 of add-bar.xsl:
XTSE0080: Namespace prefix xsl refers to a reserved namespace
Errors were reported during stylesheet compilation
The xsl: namespace is declared, the XSLT version is set to 3.0, and the usage is the same as what's shown in this example from the deprecated XSL-LIST mailing list. What am I missing?
(The actual intent is to chain named templates when creating plugins for the DITA Open Toolkit.)
Thanks in advance!
The functionality exists in the context of the new XSLT 3 feature of packages, see https://www.w3.org/TR/xslt-30/#refer-to-overridden. Neither the spec nor that thread you have linked to seem to introduce this functionality in the context of simply xsl:imports.
To give you an example on how this can be used in XSLT 3 with packages, suppose you have a first package
<?xml version="1.0" encoding="UTF-8"?>
<xsl:package
name="http://example.com/packages/ex1"
package-version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:template name="add-atts" visibility="public">
<xsl:attribute name="att1">foo</xsl:attribute>
</xsl:template>
</xsl:package>
then you can write a second package overriding that named template and making use of <xsl:call-template name="xsl:original"/>:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:package
name="http://example.com/packages/ex2"
package-version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:use-package name="http://example.com/packages/ex1">
<xsl:override>
<xsl:template name="add-atts" visibility="public">
<xsl:attribute name="att2">bar</xsl:attribute>
<xsl:call-template name="xsl:original"/>
</xsl:template>
</xsl:override>
</xsl:use-package>
</xsl:package>
Finally you can use the second package:
<?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="3.0">
<xsl:use-package name="http://example.com/packages/ex2"></xsl:use-package>
<xsl:output indent="yes"/>
<xsl:template match="/">
<root>
<xsl:apply-templates select="root/line"/>
</root>
</xsl:template>
<xsl:template match="line">
<xsl:copy>
<xsl:call-template name="add-atts"/> <!-- USED HERE -->
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
With Saxon from the command line, you would need to make sure you give the list of file names of the two packages with the -lib option e.g. -lib:package1.xsl;package2.xsl on Windows and -lib:package1.xsl:package2.xsl on Linux, when you run the main stylesheet.

XSL if test string comparison not working

I have some XML this looks like this:
<region class="TableInfo">
text
</region>
<region>
text
</region>
I want to write XSL that only preserves that part without the class="TableInfo".
I've tried a number of different ways, including:
<xsl:for-each select="region[class!='TableInfo']">
</xsl:for-each>
and
<xsl:for-each select="region">
<xsl:if test="not(class=&apos;TableInfo&apos;)">
</xsl:if>
</xsl:for-each>
and several variations thereof. it seems like it's somehow evaluating as a value rather than a string, because when I set it up as an != test, all the content gets deleted, and when I set it up as a not(), nothing gets deleted. any help?
thanks!
<xsl:for-each select="region[not(#class='TableInfo')]">
</xsl:for-each>
You forgot the # on class, so you were trying to check for class elements instead of the attributes. And apparently the != is not working as well, so I swapped in the not() function instead.
From a stylistic point, I would also suggest looking into using templates that match the region elements so you can use apply-templates instead of a for-each.
The identity rule is your friend (and of course, you need to specify the attribute class, not a "class" element):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*"><xsl:apply-templates/></xsl:template>
<xsl:template match="region[#class='TableInfo']"/>
</xsl:stylesheet>
When this transformation is applied on the provided XML (fragment wrapped into a single top element to make it a well-formed XML document):
<region>
text
</region>

How to replace text defined in a given tag or element using xslt, xslt string replace

Please help me with this xslt transformation.
Source Xml
<xml>
<test>This is a <bold>sample</bold> description. Please help me with a sample</text>
</xml>
Expected Output: This is a sample description. Please help me with a sample
I just need to make bold only the specified text by the xml markup.
Thank you
This transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="text">
<p>
<xsl:apply-templates/>
</p>
</xsl:template>
<xsl:template match="bold">
<b><xsl:apply-templates/></b>
</xsl:template>
</xsl:stylesheet>
when applied against the provided XML document:
<xml>
<text>This is a <bold>sample</bold> description. Please help me with a sample</text>
</xml>
produces the desired result in HTML:
<p>This is a <b>sample</b> description. Please help me with a sample</p>

xslt hyperlink, separate the url and descption

I have a list in sharepoint with a hyperlink column.
I'm putting this list into xml and applying xslt to it.
the xml is producing output in the form of:
<link>http://www.foo.com, http://www.foo.com</link>
how can i display this link using xslt?
thanks
How about:
<xsl:template match="link">
<a href="{substring-before(.,',')}">
<xsl:value-of select="substring-after(.,',')"/>
</a>
</xsl:template>
For XSLT 2.0
<xsl:template match="link">
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="substring-before(.,',')"/>
</xsl:attribute>
<xsl:value-of select="substring-after(.,',')"/>
</xsl:element>
</xsl:template>
Although it makes it slightly less readable, the extended syntax is considered good practice when stylesheets become large. Literal Result Elements are not as easy to manipulate via XPath as xsl:element/xsl:attribute

Resources