For comparing an xml string value against multiple strings, I am doing the following.
<xsl:if test="/Lines/@name = 'John' or /Lines/@name = 'Steve' or /Lines/@name = 'Marc' " >
Can any one tell me, instead of using 'or' in the above case, how can I check whether a string is existing in an set of strings using xslt.
Thanks.
Three ways of doing this:
- Use a pipe (or other appropriate character) delimited string
...
<xsl:template match=
"Lines[contains('|John|Steve|Mark|',
concat('|', @name, '|')
)
]
">
<!-- Appropriate processing here -->
</xsl:template>
.2. Test against an externally passed parameter. If the parameter is not externally set, and we are using XSLT 1.0, the xxx:node-set()
extension function needs to be used to convert it to normal node-set, before accessing its children
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- externally-specified parameter -->
<xsl:param name="pNames">
<n>John</n>
<n>Steve</n>
<n>Mark</n>
</xsl:param>
<xsl:template match="Lines">
<xsl:if test="@name = $pNames/*">
<!-- Appropriate processing here -->
</xsl:if>
</xsl:template>
</xsl:stylesheet>
.3. In XSLT 2.0 compare against a sequence of strings
<xsl:template match="Lines[@name=('John','Steve','Mark')]">
<!-- Appropriate processing here -->
</xsl:template>
XSLT 2.0 only: <xsl:if test="/Lines/@name = ('John', 'Steve', 'Marc')">
With XSLT 1.0 you can't write a literal expression representing a sequence of strings or a set of strings but if you know the literal values then you can construct a set of nodes e.g.
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
xmlns:data="http://example.com/data"
exclude-result-prefixes="data">
<data:data xmlns="">
<value>John</value>
<value>Steve</value>
<value>Marc</value>
</data:data>
<xsl:variable name="values" select="document('')/xsl:stylesheet/data:data/value"/>
<xsl:template match="...">
<xsl:if test="/Lines/@name = $values">..</xsl:if>
</xsl:template>
</xsl:stylesheet>
Yep - I use substring - put all your name in a string - xsl:variable - then if contains true, the name is there
e.g.
<xsl:variable name="months">**janfebmaraprmajjunjulaugsepoktnovdec</xsl:variable>
<xsl:if test="contains($months,'feb')"> do stuff ...
XPath has a some $x in (1,2,..) satisfies $x>10
expression that could be useful for this. See: http://www.java2s.com/Code/XML/XSLT-stylesheet/everyandsomeoperator.htm
For space-separated words you can use index-of(tokenize("list of allowed", "\s+"), "needle"))
or match
to go with regular expressions, although I am pretty sure there is something smarter than this.
Other possiblity:
XPath 2.0 (XSLT 2.0)
matches(/Lines/@name, 'John|Steve|Marc')
In XSLT 1.0 you have the similar function matches
provided by EXSLT.
Notice
This is not exact match against the string, but a regex match, which in your case seems appropriate anyway.