Want to do some parsing/modification of the text contents of a node if all that text()
returns is a pure text string. No XML inside.
For example
<test>some <super>1</super> text here</test>
text()
for <test>
returns just "some ". This is a case where I do not want to output the text and instead want to call apply-templates.
Is there anyway to tell or is this situation too ambiguous for XSL to handle?
Edit:
The output I want is exactly this
Reasoning is this: Sometimes there is just text that has a word split by a "/". I want to add spaces before and after so it's " / " instead. But sometimes the same node has xML in it.
some <super>1</super> text here
You can test to see if the current node has children:
<xsl:template match="/test">
<xsl:choose>
<xsl:when test="./*">
<xsl:text>children: </xsl:text>
<xsl:apply-templates />
</xsl:when>
<xsl:otherwise>
<xsl:text>just text: </xsl:text>
<xsl:value-of select="./text()" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Actually in the situation described, text() returns a sequence of two text nodes, "some " and " text here", but in XSLT 1.0, many operations on a sequence (or set) of nodes ignore all nodes except the first.
You haven't said what output you want. But the usual way of processing mixed content is to call apply-templates to process all the children. Explicit use of text() is very rarely the right thing to do.
The test or predicate count(text()) = count(node())
should work to make the distinction.
This stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="vLetters"
>qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM</xsl:variable>
<xsl:variable name="vDots"
>....................................................</xsl:variable>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="test/text()" name="tokenize">
<xsl:param name="pString" select="string()"/>
<xsl:variable name="vString"
select="translate($pString,$vLetters,$vDots)"/>
<xsl:choose>
<xsl:when test="contains($vString,'./.')">
<xsl:variable name="vOffset"
select="string-length(substring-before($vString,'./.'))"/>
<xsl:value-of select="substring($pString,1,$vOffset+1)"/>
<xsl:text> / </xsl:text>
<xsl:call-template name="tokenize">
<xsl:with-param name="pString"
select="substring($pString,$vOffset+3)"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$pString"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
With this input:
<test>This is an answer/solution to <user>OP/bobber205</user>'s question/problem</test>
Output:
<test>This is an answer / solution to <user>OP/bobber205</user>'s question / problem</test>
Note: One way (another would be with modes) for also splitting descendant is to use test//text()
as pattern.