raffian
raffian

Reputation: 32086

How to iterate XML data using XSL without hardcoding element names?

We're transforming this xml data into pipe-delimited format using XSL...

<?xml version="1.0" encoding="ISO-8859-1" ?> 
<LIBRARY> 
   <BOOK> 
        <TITLE>Professional JINI</TITLE> 
        <AUTHOR>Sing Li</AUTHOR>
        <PUBLISHER>Wrox Publications</PUBLISHER>
   </BOOK> 
</LIBRARY>

.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="text" indent="no"/>

    <!-- New line character variable -->
    <xsl:variable name="newline">
        <xsl:text>&#10;</xsl:text>
    </xsl:variable>

    <xsl:template match="/">         
        <xsl:for-each select="LIBRARY/BOOK">
            <xsl:value-of select="TITLE"/>|<xsl:value-of select="AUTHOR"/>|<xsl:value-of select="PUBLISHER"/>   
            <xsl:value-of select="$newline"/>       
        </xsl:for-each>

    </xsl:template>
</xsl:stylesheet>

This is the output...

Professional JINI|Sing Li|Wrox Publications

Is there a way to get the values of TITLE, AUTHOR, etc..from without hard coding the element names in xsl:value-of? We want this XSL to be generic so that if we add more book attributes later the style sheet will automatically capture those new fields.

Upvotes: 1

Views: 1851

Answers (2)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243599

Here is an XSLT 1.0 complete solution that is probably among the simplest (no xsl:for-each, push style) shortest possible:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="BOOK">
  <xsl:if test="not(position()=1)">
   <xsl:text>&#xA;</xsl:text>
  </xsl:if>
  <xsl:apply-templates select="*"/>
 </xsl:template>

 <xsl:template match="BOOK/*">
  <xsl:if test="not(position()=1)">|</xsl:if>
  <xsl:value-of select="."/>
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on the following XML document:

<LIBRARY>
   <BOOK>
        <TITLE>Professional JINI</TITLE>
        <AUTHOR>Sing Li</AUTHOR>
        <PUBLISHER>Wrox Publications</PUBLISHER>
   </BOOK>
   <BOOK>
        <TITLE>XSLT 2.0 Programmer's Reference</TITLE>
        <AUTHOR>Michael Kay</AUTHOR>
        <PUBLISHER>Wrox Publications</PUBLISHER>
   </BOOK>
</LIBRARY>

the wanted, correct result is produced:

Professional JINI|Sing Li|Wrox Publications
XSLT 2.0 Programmer's Reference|Michael Kay|Wrox Publications

II. XSLT 2.0 solution:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="BOOK">
  <xsl:if test="not(position()=1)">
   <xsl:text>&#xA;</xsl:text>
  </xsl:if>
  <xsl:value-of select="*" separator="|"/>
 </xsl:template>
</xsl:stylesheet>

Upvotes: 0

thiton
thiton

Reputation: 36059

You mean a concatenation of all subelements with | separating them?

<xsl:for-each select="node()>|<xsl:value-of select="."/></xsl:for-each>

Upvotes: -1

Related Questions