user2304996
user2304996

Reputation: 244

How to return text of node without child nodes text

I have xml like:

<item id="1">
        <items>
            <item id="2">Text2</item>
            <item id="3">Text3</item>
        </items>Text1
</item>

How to return text of <item id="1">('Text1')? <xsl:value-of select="item/text()"/> returns nothing.

My XSLT is:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="w3.org/1999/XSL/Transform">

  <xsl:template match="/">
    <html>
      <body>
         <xsl:apply-templates select="item"/>
     </body>
    </html>
  </xsl:template>

  <xsl:template match="item">
     <xsl:value-of select="text()"/>
  </xsl:template>
</xsl:stylesheet>

I dont know what else to type to commit my edits

Upvotes: 5

Views: 4266

Answers (2)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243579

How to return text of <item id="1">('Text1')? <xsl:value-of select="item/text()"/> returns nothing.

The item element has more than one text-node children and the first of them happens to be a all-whitespace one -- this is why you get "nothing".

One way to test if the string value of a node isn't all-whitespace is by using the normalize-space() function.

In a single Xpath expression, you want this:

/*/text()[normalize-space()][1]

Here is a complete transformation the result of which is the desired text node:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/*">
  <xsl:copy-of select="text()[normalize-space()][1]"/>
 </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the provided XML document:

<item id="1">
        <items>
            <item id="2">Text2</item>
            <item id="3">Text3</item>
        </items>Text1
</item>

the wanted, correct result is produced:

Text1

Upvotes: 5

JLRishe
JLRishe

Reputation: 101748

This should generally work:

<xsl:apply-templates select="item/text()" />

Incorporated into your XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:key name="item_key" match="item" use="."/>
  <xsl:strip-space elements="*" />

  <xsl:template match="/">
    <html>
      <body>
        <ul>
          <xsl:apply-templates select="item"/>
        </ul>
      </body>
    </html>
  </xsl:template>
  <xsl:template match="item">
    <li>
      <xsl:apply-templates select="text()"/>
    </li>
  </xsl:template>
</xsl:stylesheet>

When run on your sample input, the result is:

<html>
  <body>
    <ul>
      <li>Text1
</li>
    </ul>
  </body>
</html>

Alternatively, this should work as well:

<xsl:copy-of select="item/text()" />

Upvotes: 2

Related Questions