Reputation: 151
I have xml like this:
<article>
<title> Test title - <literal> Compulsory - </literal> <fn> ABC </fn>
<comments> a comment</comments>
</title>
</article>
I want to get all child node + self text in a variable e.g.
$full_title = "Test title - Compulsory - ABC"
Except comments node text.
Following is my unsuccessful try where i miss title node text.
<xsl:template name="test">
<xsl:variable name="full_title" select="article/title/*[not(self::comments)][1]" />
<xsl:variable name="width" select="45" />
<xsl:choose>
<xsl:when test="string-length($full_title) > $width">
<xsl:value-of select="concat(substring($full_title,1,$width),'..')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$full_title"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Upvotes: 3
Views: 5509
Reputation: 27995
Change *
to node()
. That will select both elements and text nodes that are children of the <title>
element. Then take out the [1]
since you want all children of <title>
:
<xsl:variable name="full_title"
select="string-join(article/title/node()[not(self::comments)], '')" />
A more reliable way to do it, so that you won't get tripped up if you have multiple levels under <title>
and <comments>
elements occur as grandchildren, would be this:
<xsl:variable name="full_title"
select="string-join(article/title//text()[not(ancestor::comments)], '')" />
Since you want the variable to hold a string value, and since you're passing it to functions like concat()
and string-length()
which cannot take a sequence of multiple nodes as a first argument, using string-join(..., '')
around the sequence converts it to a string by concatenating the string values of each node.
Upvotes: 3
Reputation: 23624
Try this:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:variable name="full-text">
<xsl:apply-templates select="//*[not(self::comments)]"
mode="no-comments"/>
</xsl:variable>
<xsl:value-of select="$full-text"/><!-- just for debug-->
</xsl:template >
<xsl:template match="*" mode="no-comments">
<xsl:value-of select="text()"/>
</xsl:template>
</xsl:stylesheet>
attribute mode
used only for clarity
Upvotes: 1