I have the following XSLT variable:
<xsl:variable name="superid" select="/contentdata/id"/>
Furthermore, I have a node with subnodes:
<nodes>
<node name="foo" id="bar" />
<node name="john" id="doe" />
<node name="jane" id="tarzan" />
</nodes>
Now, I'd like to check if a node with an id attribute that equals superid exists.
I've tried the following (which obviously doesn't work):
<xsl:if test="/nodes/node[@id = $superid]">Yes, Sir!</xsl:if>
What you have seems to work for me (xsl 1.0) - as per here.
I've tried to recreate your xslt
:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" indent="yes" />
<xsl:template match="/xml">
<xml>
<xsl:apply-templates select="contentdata/id" />
</xml>
</xsl:template>
<xsl:template match="id">
<Result>
<xsl:variable name="superid" select="."/>
<SearchFor>
<xsl:value-of select="$superid"/>
</SearchFor>
<IsPresent>
<xsl:if test="/xml/nodes/node[@id = $superid]">Node is present</xsl:if>
</IsPresent>
</Result>
</xsl:template>
</xsl:stylesheet>
Given the xml:
<xml>
<contentdata>
<id>doe</id>
<id>unobtanium</id>
</contentdata>
<nodes>
<node name='foo' id='bar' />
<node name='john' id='doe' />
<node name='jane' id='tarzan' />
</nodes>
</xml>
Output:
<xml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Result>
<SearchFor>doe</SearchFor>
<IsPresent>Node is present</IsPresent>
</Result>
<Result>
<SearchFor>unobtanium</SearchFor>
<IsPresent />
</Result>
</xml>
Use:
boolean(/nodes/node/@id = $superid)
Here is a complete transformation, showing this in action:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vDoe" select="'doe'"/>
<xsl:variable name="vXyz" select="'xyz'"/>
<xsl:template match="/">
id attribute with value "doe' exists: <xsl:text/>
<xsl:value-of select="boolean(/nodes/node/@id = $vDoe)"/>
==========
id attribute with value "xyz' exists: <xsl:text/>
<xsl:value-of select="boolean(/nodes/node/@id = $vXyz)"/>
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on the provided XML document:
<nodes>
<node name="foo" id="bar" />
<node name="john" id="doe" />
<node name="jane" id="tarzan" />
</nodes>
the wanted, correct result is produced:
id attribute with value "doe' exists: true
==========
id attribute with value "xyz' exists: false
If you are using the xpath expression /nodes/node[@id = $superid]"> then this would be looking for a root node of nodes in your XML document. However, in your question you seem to imply nodes is just a node within your document, not necessarily the root element. Try this instead
<xsl:if test="//nodes/node[@id = $superid]">Yes, Sir!</xsl:if>
The double-slash selects nodes in the document wherever they are in the hierarchy, not just the top-level node.
This should be working as you expect. One of your expressions (either in the variable's select
or in the test
attribute) must not be selecting what you think it is. (You haven't provided your full input, so it's hard to help there.)
Note a few things about xsl:if
:
First, see this part of the XSLT spec (emphasis my own):
The xsl:if element has a test attribute, which specifies an expression. The content is a template. The expression is evaluated and the resulting object is converted to a boolean as if by a call to the boolean function. If the result is true, then the content template is instantiated; otherwise, nothing is created.
So how would a call to the boolean
function work on your input? See this part of the XPath spec (again, emphasis mine):
The boolean function converts its argument to a boolean as follows :
a number is true if and only if it is neither positive or negative zero nor NaN
a node-set is true if and only if it is non-empty
a string is true if and only if its length is non-zero
an object of a type other than the four basic types is converted to a boolean in a way that is dependent on that type
So, if /contentdata/id
actually selects an id
for which /nodes/node[@id = $superid]
returns a non-empty node-set, then the body of the xsl:if
should execute.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With