Premlal Premkumar
Premlal Premkumar

Reputation: 63

XSL Transform for Multiple Child Elements

Team

I am an absolute newbie to XSLT. I am trying my hand at some automation. I want to be able to create the following output using the below XML code of text:

My XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0">
<xsl:output method="html" version="5.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
    <html>
        <head>
            <title>KT/Definitions List</title>
        </head>
        <body>
            <h2>KT/Definitions List</h2>
            <table border="1">
                <thead>
                    <tr>
                        <th>KT</th>
                        <th>Definition</th>
                    </tr>
                </thead>
                <tbody>
                        <xsl:apply-templates select="cl:doc//cl:key-term-entry"/>
                </tbody>
            </table>
        </body>
    </html>
</xsl:template>
<xsl:template match="cl:key-term-entry">
    <tr>
        <td><xsl:value-of select="cl:key-term"/></td>
        <td><xsl:value-of select="cl:key-term-def"/></td>
    </tr>
</xsl:template>
</xsl:stylesheet>

My Part XML Input

<cl:key-term-entry identifier="JMTMRA930472614">
<cl:key-term identifier="DXYKHJ261631149">availability sampling</cl:key-term>
<cl:key-term-def identifier="BKPHVJ904214958">A sampling method that selects elements simply because of their ready availability and convenience. Frequently used in social work because it is usually less expensive than other methods and because other methods may not be feasible for a particular type of study or population. See also
<cl:style styles="italic">accidental sampling</cl:style>,
<cl:style styles="italic">convenience sampling</cl:style>, and
<cl:xref link-target="KRJPJV275444397" ordinal="11" pre-text="Chapter "/>.
</cl:key-term-def>
</cl:key-term-entry>

MY XSLT Output

<tr>
<td>availability sampling</td>
<td>A sampling method that selects elements simply because of their ready availability and convenience. Frequently used in social work because it is usually less expensive than other methods and because other methods may not be feasible for a particular type of study or population. See also accidental sampling, convenience sampling, and .</td>
</tr>

MY Desired XSLT Output

<tr>
<td>availability sampling</td>
<td>A sampling method that selects elements simply because of their ready availability and convenience. Frequently used in social work because it is usually less expensive than other methods and because other methods may not be feasible for a particular type of study or population. See also <i>accidental sampling</i>, <i>convenience sampling</i>, and <a href="chapter11.html">Chapter 11</a>.</td>
</tr>

As you can see from my output (not my desired output), I am unable to understand how to add the <i> tags and <a> tag here. In fact, the self-closing <cl:xef> tag (whose attribute values have to be transformed as <a> tag) is empty in my output. Any help here will advance my knowledge of XSLT.

Thanks.

Update

Your answers provided me an insight into the workings of the XSLT. Thank you! However, I forgot to include another question here. I want to capture information from a different element as well in my output.

My Updated Input XML

<cl:chapter identifier="GIZWOL818406804">
<cl:complex-meta>
    <cl:title identifier="FBXQBD997244986">Why Study Research?</cl:title>
    <cl:label>Chapter <cl:ordinal>1</cl:ordinal></cl:label>
</cl:complex-meta>
<cl:key-term-entry identifier="JMTMRA930472614">
    <cl:key-term identifier="DXYKHJ261631149">availability sampling</cl:key-term>
    <cl:key-term-def identifier="BKPHVJ904214958">A sampling method that selects elements simply because of their ready availability and convenience. Frequently used in social work because it is usually less expensive than other methods and because other methods may not be feasible for a particular type of study or population. See also
        <cl:style styles="italic">accidental sampling</cl:style>,
        <cl:style styles="italic">convenience sampling</cl:style>, and
    <cl:xref link-target="KRJPJV275444397" ordinal="11" pre-text="Chapter "/>.
    </cl:key-term-def>
</cl:key-term-entry>
</cl:chapter>

My Updated Part XSLT

<xsl:template match="cl:key-term-entry">
    <tr>
        <td><xsl:apply-templates select="cl:key-term"/></td>
        <td><xsl:apply-templates select="cl:key-term-def"/></td>
    </tr>
</xsl:template>
<xsl:template match="//cl:chapter/cl:complex-meta/cl:label">
    <td><xsl:value-of select="."/></td>
</xsl:template>

I am not sure where I should include <xsl:apply-templates select="cl:label"/> to get the below desired output.

My New Desired Output

<tr>
                <td>scientific method</td>
                <td>An approach to inquiry that attempts to safeguard against errors commonly made in casual human inquiry. Chief features include viewing all knowledge as provisional and subject to refutation, searching for evidence based on systematic and comprehensive observation, pursuing objectivity in observation, and replication. See Chapter 1.</td>
                <td>Chapter 1</td>

</tr>
<tr>...</tr>

Upvotes: 1

Views: 444

Answers (4)

Premlal Premkumar
Premlal Premkumar

Reputation: 63

Finally, I got the answer I was looking for. Thanks to @Rudramuni and @Martin:

My XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:cl="http://www.test.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output method="html" version="5.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
    <html>
        <head>
            <title>KT List</title>
        </head>
        <body>
            <table border="1">
                <thead>
                    <tr>
                        <th>KT</th>
                        <th>Definition</th>
                        <th>Chapter Number</th>
                    </tr>
                </thead>
                <tbody>
                    <xsl:for-each select="//cl:key-term-entry">
                        <tr>
                            <td><xsl:apply-templates select="cl:key-term"/></td>
                            <td><xsl:apply-templates select="cl:key-term-def"/></td>
                            <td><xsl:apply-templates select="ancestor::cl:chapter/cl:complex-meta/cl:label"/></td>
                        </tr>
                    </xsl:for-each>
                </tbody>
            </table>            
        </body>
    </html>
</xsl:template>
<xsl:template match="cl:style">
    <xsl:choose>
        <xsl:when test="@styles='italic'">
            <i><xsl:apply-templates/></i>
        </xsl:when>
        <xsl:when test="@styles='bold'">
            <b><xsl:apply-templates/></b>
        </xsl:when>
        <xsl:otherwise><xsl:apply-templates/></xsl:otherwise>
    </xsl:choose>
</xsl:template>
<xsl:template match="cl:xref"><xsl:value-of select="concat(@pre-text,@ordinal)"/></xsl:template>

Upvotes: 0

Rudramuni TP
Rudramuni TP

Reputation: 1278

For another requirement, update as given below.

change following

    <tr>
        <td><xsl:apply-templates select="cl:key-term"/></td>
        <td><xsl:apply-templates select="cl:key-term-def"/></td>
    </tr>

to

    <tr>
        <td><xsl:apply-templates select="cl:key-term"/></td>
        <td><xsl:apply-templates select="cl:key-term-def"/></td>
        <td><xsl:value-of select="concat(cl:key-term-def/cl:xref/@pre-text, cl:key-term-def/cl:xref/@ordinal)"/></td>
    </tr>

Upvotes: 0

Rudramuni TP
Rudramuni TP

Reputation: 1278

Try this:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:cl="http://www.examples">
<xsl:output method="xml" version="5.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
    <html>
        <head>
            <title>KT/Definitions List</title>
        </head>
        <body>
            <h2>KT/Definitions List</h2>
            <table border="1">
                <thead>
                    <tr>
                        <th>KT</th>
                        <th>Definition</th>
                    </tr>
                </thead>
                <tbody>
                        <xsl:apply-templates select="//cl:key-term-entry"/>
                </tbody>
            </table>
        </body>
    </html>
</xsl:template>
<xsl:template match="cl:key-term-entry">
    <tr>
        <td><xsl:apply-templates select="cl:key-term"/></td>
        <td><xsl:apply-templates select="cl:key-term-def"/></td>
    </tr>
</xsl:template>

<xsl:template match="cl:style">
    <xsl:choose>
        <xsl:when test="@styles='italic'">
            <i><xsl:apply-templates/></i>
        </xsl:when>
        <xsl:when test="@styles='bold'">
            <b><xsl:apply-templates/></b>
        </xsl:when>
        <xsl:otherwise><xsl:apply-templates/></xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template match="cl:xref">
    <a>
        <xsl:attribute name="href">
            <xsl:value-of select="concat(normalize-space(@pre-text), @ordinal, '.html')"/>
        </xsl:attribute>
        <xsl:value-of select="concat(@pre-text, @ordinal)"/>
    </a>
</xsl:template>


</xsl:stylesheet>

Upvotes: 0

Martin Honnen
Martin Honnen

Reputation: 167401

Instead of simply using value-of use apply-templates:

<xsl:template match="cl:key-term-entry">
    <tr>
        <td><xsl:apply-templates select="cl:key-term"/></td>
        <td><xsl:apply-templates select="cl:key-term-def"/></td>
    </tr>
</xsl:template>

Then of course you need to add templates for the other elements you want to transform e.g.

<xsl:template match="cl:style[styles = 'italic']">
  <i>
   <xsl:apply-templates/>
  </i>
</xsl:template>

and

<xsl:template match="cl:xref">
  <a href="{@pre-text}{@ordinal}.html"><xsl:value-of select="concat(@pre-text, ' ', @ordinal)"/></a>
</xsl:template>

Upvotes: 1

Related Questions