Basic XML/XSLT - value-of when there are multiple elements of the same name

32,911

Solution 1

<xsl:template match="/">
    <xsl:for-each select="catalog">
        <!-- Print Other Stuff, if required -->
        <xsl:for-each select="cd/artist">
            <xsl:value-of select="text()"/><br/>
        </xsl:for-each>
    </xsl:for-each>
</xsl:template>

Output:

Bob Dylan
Bob Dylan2
Bob Dylan3

Solution 2

Now when I for-each through each CD and use value-of to output the artist name, I only get the first element (somewhat understandably). But how do I get ALL elements of the same name within a for-each loop? I tried doing an inner for-each loop but didn't work.

My advice to any XSLT novice is not to use <xsl:for-each> -- as much as possible. I am aware of only one use-case where <xsl:for-each> is necessary, and this is a very rarely encountered case (when it is necessary to explicitly change the current document so that the key() function will use an index built for this specific document).

This is probably one of the simplest possible solutions (no <xsl:for-each> and no nesting):

<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="artist">
  <xsl:value-of select="concat(., '&#xA;')"/>
 </xsl:template>

 <xsl:template match="text()"/>
</xsl:stylesheet>

when this transformation is applied on the provided XML document:

<catalog>
    <cd>
        <title>Empire Burlesque</title>
        <artist>Bob Dylan</artist>
        <artist>Bob Dylan2</artist>
        <artist>Bob Dylan3</artist>
        <country>USA</country>
        <company>Columbia</company>
        <price>10.90</price>
        <year>1985</year>
    </cd>
</catalog>

the wanted, correct result is produced:

Bob Dylan
Bob Dylan2
Bob Dylan3

Solution 3

<xsl:template match="catalog/cd/artist">
    <xsl:value-of select="." />
</xsl:template>

Solution 4

There's no reason an inner loop wouldn't work. What XSLT syntax did you use to do this? It sounds like there's an error in your xpaths or something, because what you've described should work fine.

Share:
32,911
lionysis
Author by

lionysis

PHP, Javascript, jQuery, AJAX, HTML, CSS

Updated on August 30, 2020

Comments

  • lionysis
    lionysis over 3 years

    When I'm getting the value of an element which is used multiple times in the same parent element, I'd like to get each element of the same name and not just the first.

    E.g. -

    <catalog>
    <cd>
        <title>Empire Burlesque</title>
        <artist>Bob Dylan</artist>
                <artist>Bob Dylan2</artist>
                <artist>Bob Dylan3</artist>
        <country>USA</country>
        <company>Columbia</company>
        <price>10.90</price>
        <year>1985</year>
    </cd>
    </catalog>
    

    Now when I for-each through each CD and use value-of to output the artist name, I only get the first element (somewhat understandably). But how do I get ALL elements of the same name within a for-each loop? I tried doing an inner for-each loop but didn't work.

    I'm very new to XML and how it works so please go easy on me...:-(

  • Michael Kay
    Michael Kay over 12 years
    select="." should be used in preference to select="text()". It's more robust if the content contains comments, nested child elements, etc - especially if your'e running against an implementation which doesn't concatenate adjacent text nodes - that's non-conformant, but it happens.
  • lionysis
    lionysis over 12 years
    This seemed to work - I just had to do a inner for-each and text(). Can you tell me what the text() function does?