Compare node set against a string

S

ShaggyMoose

I have a delimited string (value1, value2, value3 etc) and a node set
(single value text nodes). I want to compare each node in the set
against the string and return true when a match is found. If no match
is found, return false. However, I can't work out a way to do this
without the ability to re-assign variables or exit a loop early. This
isn't something I have had to attempt using XSL before. Can anyone
suggest a way to complete the template function below, or a better
method? Thanks.

<xsl:template name="has-value">

<xsl:param name="strVals"/> <!-- Comma delimited string of user
roles. -->
<xsl:param name="setVals"/> <!-- Node set of roles to match. -->

<xsl:for-each select="etVals">
<xsl:if test="contains($strVals, .)">
-- RETURN TRUE HERE --
</xsl:if>
</xsl:for-each>

-- RETURN FALSE HERE --

</xsl:template>
 
M

Martin Honnen

ShaggyMoose said:
I have a delimited string (value1, value2, value3 etc) and a node set
(single value text nodes). I want to compare each node in the set
against the string and return true when a match is found. If no match
is found, return false. However, I can't work out a way to do this
without the ability to re-assign variables or exit a loop early. This
isn't something I have had to attempt using XSL before. Can anyone
suggest a way to complete the template function below, or a better
method? Thanks.

<xsl:template name="has-value">

<xsl:param name="strVals"/> <!-- Comma delimited string of user
roles. -->
<xsl:param name="setVals"/> <!-- Node set of roles to match. -->

<xsl:for-each select="etVals">
<xsl:if test="contains($strVals, .)">
-- RETURN TRUE HERE --
</xsl:if>
</xsl:for-each>

Well with XSLT 2.0 you can easily do e.g.
<xsl:value-of
select="if ($setVals = tokenize($strVals, ',\s*')) then 'TRUE' else
'FALSE'"/>

For XSLT 1.0 check whether an EXSLT extension function can do the same:
http://www.exslt.org/str/functions/tokenize/index.html
 
S

ShaggyMoose

Well with XSLT 2.0 you can easily do e.g.
   <xsl:value-of
     select="if ($setVals = tokenize($strVals, ',\s*')) then 'TRUE' else
'FALSE'"/>

Thanks for the reply Martin. However, the test you described will
check that each node of the set matches each token from the string,
correct? I only need to match one node from the set.
 
J

Joseph Kesselman

In 1.0, I'd recursively parse my way through the string, extracting the
values in order to do the appropriate comparisons.

In general, if loops don't seem to do it for you in XSLT, consider
recursion.
 
P

Pavel Lepin

ShaggyMoose said:
Thanks for the reply Martin. However, the test you
described will check that each node of the set matches
each token from the string, correct? I only need to match
one node from the set.

XSLT1 should suffice:

<xsl:template name="check-roles">
<xsl:param name="string"/>
<xsl:param name="nodeset"/>
<xsl:choose>
<xsl:when
test=
"
$nodeset
[
contains(concat(', ',$string,', '),
concat(', ',.,', '))
]
">
<true/>
</xsl:when>
<xsl:eek:therwise>
<false/>
</xsl:eek:therwise>
</xsl:choose>
</xsl:template>

Note that you made a standard beginner mistake: for-each is
not a loop, it's an application of an inline template to a
nodeset or a sequence. There's no order-of-execution
guarantee.

There aren't any loops in XSLT. If you need to iterate over
some sort of collection, be it a nodeset, a tokenized
string or anything else, you should use recursion. If it
gets too deep, use divide-and-conquer or tail recursion
(assuming your processor can optimise it away - some
can't).
 
M

Martin Honnen

ShaggyMoose said:
Thanks for the reply Martin. However, the test you described will
check that each node of the set matches each token from the string,
correct? I only need to match one node from the set.

No, the comparison
$setVals = tokenize($strVals, ',\s*')
compares two sequences and the general comparison is true if there is
(at least) one value in the first that is equal to (at least) one value
in the second sequence.
 
S

ShaggyMoose

Thank you Martin and Pavel for your responses. I have managed to
cobble together something that works.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top