简体   繁体   中英

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

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.

Eg -

<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...:-(

<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

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
<xsl:template match="catalog/cd/artist">
    <xsl:value-of select="." />
</xsl:template>

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.

Your XPATH is proably wrong:

While in the CD element using a foreach:

  <xsl:template match="/">
    <xsl:for-each select="//cd">
      <xsl:for-each select="artist">
        <xsl:message terminate="no">
          <xsl:value-of select="."/>
        </xsl:message>
      </xsl:for-each>
    </xsl:for-each>
  </xsl:template>

That prints all the artists..

the text() xpath syntax selects any text child nodes of the current specified node.

some don't particularly like this website, but for starting off, its not bad to point you in the right direction - click here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM