0

I'm stucked with a xslt for-each-loop.

The xml source file is:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="party.xsl"?>
<party date="31.12.01">
<guest name="Albert">
    <drink>wine</drink>
    <drink>beer</drink>
    <status single="true" sober="false" />
</guest>
<guest name="Martina">
    <drink>apple juice</drink>
    <status single="true" sober="true" />
</guest>
<guest name="Zacharias">
    <drink>wine</drink>
    <status single="false" sober="false" />
</guest>
</party>

I'd like to get the following output:

  • Albert drinks: wine , beer ,
  • Martina drinks: apple juice
  • Zacharias drinks: wine ,

Therefore i wrote following XSLT file:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
    <html>
    <head></head>
    <body bgcolor="white">
        <xsl:for-each select="party/guest">
        <ul><li><b><xsl:value-of select="@name"/></b>
            <xsl:text> drinks: </xsl:text>
            <xsl:value-of select="drink"/>
            <xsl:text>, </xsl:text>
        </li></ul>
        </xsl:for-each>
    </body>
    </html>
</xsl:template>
</xsl:stylesheet>

Using the XSLT file above i get following output:

  • Albert drinks: wine,
  • Martina drinks: apple juice,
  • Zacharias drinks: wine,

How do i have to change my XSLT file, that i get all drinks form the guests displayed? Thanks a lot for your support!

1 Answer 1

1

You could just nest another level of <xsl:for-each select="drink">.

I recommend to avoid <xsl:for-each>, though. Also, don't cram everything into a single do-it-all template.

<xsl:template match="/">
  <html>
    <head></head>
    <body bgcolor="white">
      <xsl:apply-templates select="party" />
    </body>
  </html>
</xsl:template>

<xsl:template match="party">
  <ul>
    <xsl:apply-templates select="guest" />
  </ul>
</xsl:template>

<xsl:template match="guest">
  <li>
    <xsl:value-of select="concat(@name, ' drinks: ')" />
    <xsl:apply-templates select="drink" />
  </li>
</xsl:template>

<xsl:template match="drink">
  <xsl:value-of select="." />
  <xsl:if test="position() &lt; last()">, </xsl:if>
</xsl:template>
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks a lot! Why do you recommend to avoid <xsl:for.each>?
Because XSLT is not an imperative language and "for each" is an imperative paradigm. Using it tends to produce monolithic, deeply nested code that's impossible to re-use (and therefore often contains a lot of copy/paste duplication). It's not that there is no use at all for it, but in 95% of all cases I've seen it is used inappropriately. Resist the impulse to write an <xsl:for-each> and concentrate on writing <xsl:template> and using <xsl:apply-templates>, like shown above. The result will almost always be better code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.