Page 1 of 1

XSLT: merge glossentries for ditamap in one table

Posted: Wed Mar 27, 2019 1:45 pm
by pieterjan_vdw
Hi,

I would like to merge all the glossterms en glossdef from my ditamap into a CALS table.
When I try to run I get an error message on this line:
<xsl:for-each select="collection(concat($folderURI, '?select=*.dita;recurse=yes'))/glossentry"> with this message:

collection(): failed to parse XML file file:/C:/DITA/XSLT/!glossary/glossary.dita: org.xml.sax.SAXParseException; systemId: file:/C:/DITA/XSLT/!glossary/glossary.dita; lineNumber: 16; columnNumber: 21; XML document structures must start and end within the same entity.

This is the complete code:

Code: Select all

<?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:template name="glossary_table" match="glossentry">
<xsl:result-document href="glossary.dita" doctype-public="-//OASIS//DTD DITA Topic//EN" doctype-system="topic.dtd" indent="yes">
<xsl:element name="topic" xml:lang="en-US" xml:id="glos">
<xsl:attribute name="id">glossary</xsl:attribute>
<xsl:element name="title"/>
<xsl:element name="body">
<xsl:element name="table">
<xsl:element name="tgroup">
<xsl:attribute name="cols">2</xsl:attribute>
<colspec colname="c1" colnum="1" colwidth="1*"/>
<colspec colname="c2" colnum="2" colwidth="1*"/>
<xsl:element name="thead">
<row>
<entry>Term</entry>
<entry>Description</entry>
</row>
</xsl:element>
<xsl:element name="tbody">
<xsl:variable name="folderURI" select="resolve-uri('.',base-uri())"/>
<xsl:for-each select="collection(concat($folderURI, '?select=*.dita;recurse=yes'))/glossentry">
<row>
<entry><xsl:value-of select="glossterm"/></entry>
<entry><xsl:value-of select="glossdef"/></entry>

</row>
</xsl:for-each>
</xsl:element>
</xsl:element>
</xsl:element>
</xsl:element>
</xsl:element>
</xsl:result-document>
</xsl:template>
</xsl:stylesheet>

I created part of the XLST based on this topic of this forum: post50728.html?hilit=XSLT%20multiple%20file#p50728

I am new to XSLT. Anyone who can help me this issue?


Second question.
Currently the XSLT would run on all files in a certain folder. How can I change this to run via a transformation scenario on the selected ditamap.

Thanks a lot!

Re: XSLT: merge glossentries for ditamap in one table

Posted: Wed Mar 27, 2019 4:08 pm
by Radu
Hi,

Just make sure your xsl:result-document saves to a target file which is not included in the same folder where the collection() XSLT function is invoked, otherwise you will end up parsing your own output file.
So do something like this:

Code: Select all

<xsl:result-document href="../glossary.dita" 
if you want to save the result file in the folder which is the parent of the current folder containing the glossentries.

About this question:
Currently the XSLT would run on all files in a certain folder. How can I change this to run via a transformation scenario on the selected ditamap.
There are various ways which could work:

- Your custom XSLT gets applied on the main DITA Map, it matches all topic references, it loads each topicref using the XSLT doc() function. If the loaded topicref is for a glossentry, it processes it. If the topicref is a reference to a DITA Map, the XSLT stylesheet applies recursively the same process.
- There is a DITA OT plugin included also in the DITA OT bundled with Oxygen which produces a single merged XML document from the entire DITA Map, with all topicrefs expanded:

https://github.com/oxygenxml/dita-merged
You would need to apply an XSLT stylesheet on that merged XML output and obtain what you want. So you could take our existing plugin, copy it, make it yours (change plugin ID) and in the plugin after the merged XML is obtained apply an XSLT stylesheet to create that topic.

Regards,
Radu

Re: XSLT: merge glossentries for ditamap in one table

Posted: Thu Mar 28, 2019 12:48 pm
by pieterjan_vdw
Hi Radu,

Thanks for the help. I am already a bit further.

I tried to work with the doc() function, but ran into another problem. Currently I create a separate table per glossentry. I just want them all merged into one table.

Any suggestion to make this work? See code below.

Code: Select all

<?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:template name="test" match="map/topicref">
<xsl:element name="topic" xml:lang="en-US" xml:id="glos">
<xsl:attribute name="id">glossary</xsl:attribute>
<xsl:element name="title"/>
<xsl:element name="body">
<xsl:element name="table">
<xsl:element name="tgroup">
<xsl:attribute name="cols">2</xsl:attribute>
<colspec colname="c1" colnum="1" colwidth="1*"/>
<colspec colname="c2" colnum="2" colwidth="1*"/>
<xsl:element name="thead">
<row>
<entry>Term</entry>
<entry>Description</entry>
</row>
</xsl:element>
<xsl:element name="tbody">
<xsl:variable name="topic" select="document(@href, .)"/>
<xsl:for-each select="$topic//*[contains(@class, ' glossentry/glossentry ')]">
<row>
<entry><xsl:value-of select="glossterm"/></entry>
<entry><xsl:value-of select="glossdef"/></entry>
</row>
</xsl:for-each>
</xsl:element>
</xsl:element>
</xsl:element>
</xsl:element>
</xsl:element>
</xsl:template>
</xsl:stylesheet>

Re: XSLT: merge glossentries for ditamap in one table

Posted: Thu Mar 28, 2019 7:58 pm
by pieterjan_vdw
FYI:
This helped me to achieve what I wanted.
https://stackoverflow.com/questions/554 ... 8#55402728