tags:

views:

51

answers:

2

Let's say I have an XML document that has this:

<keywords>
<keyword>test</keyword>
<keyword>test2</keyword>
<keyword>test3</keyword>
<keyword>test4</keyword>
</keywords>

And i want to use XSLT to print it out in HTML like this:

<ul>
<li>test</li>
<li>test2</li>
<li>test3</li>
<li>test4</li>
</ul>

What would my XSLT look like? I tried this:

<ul>
<xsl:for-each select="keywords/keyword">
    <li><xsl:value-of select="keyword"/></li>
</xsl:for-each>
</ul>

but that doesn't print out the keyword value, just a blank item.

<ul>
<xsl:for-each select="keywords">
    <li><xsl:value-of select="keyword"/></li>
</xsl:for-each>
</ul>

doesn't work (for obvious reasons), but at least it prints the first keyword!

suggestions? thanks!

+3  A: 
<ul>
<xsl:for-each select="keywords/keyword">    
  <li><xsl:value-of select="text()"/></li>
</xsl:for-each>
</ul>

using text() should get you the text inside the keyword node

dnagirl
thanks for the help!
lawdawg
Actually, in this case, using `select="."` will work too (the node will be atomized, which effectively means a concatenation of values of all nested text nodes on all levels).
Pavel Minaev
Good to know. Thank!
dnagirl
+8  A: 

I would suggest avoiding for-each here, and doing it using a template - it's more idiomatic in XSLT, especially when you have a clear one-to-one mapping:

<xsl:template match="keyword">
    <li><xsl:value-of select="."/></li>
</xsl:template>

<xsl:template match="keywords">
    <ul><xsl:apply-templates/></ul>
</xsl:template>
Pavel Minaev
Agreed - major programmer issue in adapting to XSLT is to think in terms of for-each (and call-template) instead of using apply-tempaltes and match=
Murph
agreed. Avoid `for-each` where you can.
Jweede
Agreed, but use xsl:apply-templates without its select attribute only when the XML schema is well known and stable; otherwise, if there's any tag whose the template is missing, it will be processed by default templates and its text content will be put on the output.
Erlock
@Erlock: I usually start with a default rule for all nodes that simply calls `<xsl:apply-template/>`. That way you get tree propagation for all nodes, but no output, by default.
Pavel Minaev
I wholeheartedly agree to the `apply-templates` vs `for-each` argument. +1
Tomalak