Reputation: 33
I want to check if node value contains a string that occurs in an attribute of a node with-in variable made as a node-set.
<xsl:variable name="Var">
<root>
<tag atr="x3"> some string <tag>
<tag atr="x4"> some string <tag>
<root>
<xsl:variable>
xml contains:
<name>one x3 two<name>
i've tried something like :
<xsl:value-of select="contains(name,msxsl:node-set($Var)/root/tag/@atr)"/>
but it just output's nothing and move on.
Upvotes: 3
Views: 6768
Reputation: 243459
In XPath 1.0 if a function or operator expects a string and is passed a node-set, only the string value of the first (in document order) node of the node-set is produced and used by this function or operator.
Therefore, an expression such as:
contains(name, msxsl:node-set($Var)/root/tag/@atr)
tests only whether the string value of the first of the msxsl:node-set($Var)/root/tag/@atr
nodes is contained in the string value of the first name
node.
You actually want to see if the string value of any of the nodes in msxsl:node-set($Var)/root/tag/@atr
is contained in a the string value of a given element, named name
.
One correct XPath expression evaluating this condition:
boolean(msxsl:node-set($Var)/root/tag/@atr[contains($name, .)])
where $name
is defined to contain exactly the element name
.
A complete code example:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="name" select="'x42'"/>
<xsl:variable name="Var">
<root>
<tag atr="x3"> some string </tag>
<tag atr="x4"> some string </tag>
</root>
</xsl:variable>
<xsl:template match="/">
<xsl:value-of select=
"boolean(msxsl:node-set($Var)
/root/tag/@atr[contains($name, .)])"/>
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on any XML document (not used), the wanted, correct result is produced:
true
However, if we substitute in the above transformation the XPath expression offered in the another answer (by Siva Charan) :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="name" select="'x42'"/>
<xsl:variable name="Var">
<root>
<tag atr="x3"> some string </tag>
<tag atr="x4"> some string </tag>
</root>
</xsl:variable>
<xsl:template match="/">
<xsl:value-of select=
"contains(name, msxsl:node-set($Var)/root/tag/@atr)"/>
</xsl:template>
</xsl:stylesheet>
this transformation produces the wrong answer:
false
because it only tests for containment the first of all attr
attributes.
Upvotes: 3