Search code examples
xsltdita

XSLT: create new topic with results of search in table


From a list of referenced glossentry topics I would like to get one table with the following result:

  • column 1: the value of the glossterm element
  • column 2: the value of glossdef element.

I start from one DITAMAP with references to "glossentry" topics. In this glossentry topic I can find the two elements I want to use "glossterm" and "glossdef".

DITAMAP

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE map PUBLIC "-//OASIS//DTD DITA Map//EN" "map.dtd">
<map>
<title>Glossary</title>
<topicref href="gloss_ar3.dita" keys="ar3"/>
<topicref href="gloss_chr.dita" keys="chr"/>
</map>

glossentry 1 (gloss_ar3.dita):

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE glossentry PUBLIC "-//OASIS//DTD DITA Glossary//EN" "glossary.dtd">
<glossentry id="glossentry_vhg_gt4_m2b">
<glossterm><sort-as value="AR3"/>AR3</glossterm>
<glossdef>Amplification Reagent 3</glossdef>
</glossentry>

Glossentry 2 (gloss_chr.dita):

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE glossentry PUBLIC "-//OASIS//DTD DITA Glossary//EN" "glossary.dtd">
<glossentry id="glossentry_v1f_ktv_j2b">
<glossterm><sort-as value="Chr"/>Chr</glossterm>
<glossdef>Chromosome</glossdef>
</glossentry>

What I get with my code is a row per "glossentry" with:

  • glossterm in the first column
  • glossdef in the second column.

Result so far:

<row>
   <entry>AR3</entry>
   <entry>Amplification Reagent 3</entry>
</row>
<row>
   <entry>Chr</entry>
   <entry>Chromosome</entry>
</row>

So far so good.

But I would like to:

  • have the rows in a regular table
  • save it in a new file

This is my XSLT so far:

<?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:output indent="yes" />

<xsl:template match="/map">
<xsl:apply-templates select="topicref"/>
</xsl:template>
<xsl:template name="rows" match="topicref">
   <xsl:for-each select="document(@href)/glossentry">
      <row>     
      <entry><xsl:apply-templates select="glossterm"/></entry>
      <entry><xsl:apply-templates select="glossdef"/></entry>
      </row>
      </xsl:for-each>
</xsl:template>    
</xsl:stylesheet>

The end-result should be:

  • a table with the all terms & definition in a separate rows.
  • saved in a separate file in the same folder as ditamap.

Example of the expected end-result:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE topic PUBLIC "-//OASIS//DTD DITA Topic//EN" "topic.dtd">
<topic id="topic_ph2_kqz_fhb">
    <title>Glossary</title>
    <body>
        <p>
<table id="table_rzs_kqz_fhb">
<title/>
<tgroup cols="2">
<colspec colname="c1" colnum="1"/>
<colspec colname="c2" colnum="2"/>
<thead>
<row>
<entry>Term</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>AR3</entry>
<entry>Amplification Reagent 3</entry>
</row>
<row>
<entry>Chr</entry>
<entry>Chromosome</entry>
</row>
</tbody>
</tgroup>
</table>
</p>
    </body>
</topic>

I am still new to XSLT. Any help would be welcome.


Solution

  • AFAICT, you want to do something like:

    XSLT 1.0

    <xsl:template match="/map">
        <table>
            <xsl:for-each select="topicref">
                <xsl:variable name="gloss" select="document(@href)/glossentry" />
                 <row>     
                    <entry>
                        <xsl:value-of select="$gloss/glossterm"/>
                    </entry>
                    <entry>
                        <xsl:value-of select="$gloss/glossdef"/>
                    </entry>
                </row>
            </xsl:for-each>
        </table>
    </xsl:template>
    
    </xsl:stylesheet>
    

    This is assuming that for every topicref in the map document there is a file in the same directory whose name is equal to the value of the href attribute.