XSLT: merge glossentries for ditamap in one table

Here should go questions about transforming XML with XSLT and FOP.
pieterjan_vdw
Posts: 41
Joined: Wed Jun 20, 2018 11:30 am

XSLT: merge glossentries for ditamap in one table

Post 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!
Radu
Posts: 9049
Joined: Fri Jul 09, 2004 5:18 pm

Re: XSLT: merge glossentries for ditamap in one table

Post 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
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
pieterjan_vdw
Posts: 41
Joined: Wed Jun 20, 2018 11:30 am

Re: XSLT: merge glossentries for ditamap in one table

Post 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>
pieterjan_vdw
Posts: 41
Joined: Wed Jun 20, 2018 11:30 am

Re: XSLT: merge glossentries for ditamap in one table

Post by pieterjan_vdw »

FYI:
This helped me to achieve what I wanted.
https://stackoverflow.com/questions/554 ... 8#55402728
Post Reply