Reputation: 786
We're using XSLT2. Wondering if this is possible.
We have a tag filter, where a customer can choose to see all the themes which match ALL of their selections.
Here's an idea of the XML structure:
<themes>
<theme>
<name>Apple</name>
<tags>
<tag id="1">
<tag id="2">
</tags>
</theme>
<theme>
<name>Banana</name>
<tags>
<tag id="2">
<tag id="3">
</tags>
</theme>
<theme>
<name>Kiwifruit</name>
<tags>
<tag id="2">
<tag id="3">
</tags>
</theme>
</themes>
The customer chooses tags 2 and 3. The result we want is to only show is Banana and Kiwifruit, as they have all the tags the user selected.
We can't use the AND operator as the list of tags is long and unknown. We currently have this list passed into the XSLT and then tokenised:
<xsl:param name="tag_ids"/>
<xsl:variable name="tag_id_list" select="tokenize($tag_ids,',')"/>
This statement selects any theme that has any of the tag_id_list:
<xsl:for-each select="themes/theme/tags/tag[@id=$tag_id_list]">
But we're trying to find a XPath statement that makes sure the has ALL the s in $tag_id_list
Any ideas?! Thanks in advance.
Upvotes: 3
Views: 52
Reputation: 70628
You could count the number of tags that match, and see if it equals to the number of tags in tag_id_list
. For example
<xsl:variable name="tagcount" select="count($tag_id_list)" />
<xsl:for-each select="themes/theme[count(tags/tag[@id=$tag_id_list]) = $tagcount]">
If the customer could enter duplicate tags (like '2,2,3') then you might have to change tagcount
to this
<xsl:variable name="tagcount" select="count(distinct-values($tag_id_list))" />
Upvotes: 1
Reputation: 163418
You want this if the tags have to be in the right order:
themes/theme/tags[deep-equal($tag_id_list, tag/@id)]
or this if they can be in any order:
themes/theme/tags[
(every $tag in $tag_id_list satisfies $tag = tag/@id)
and
(every $tag in tag/@id satisfies $tag = $tag_id_list)]
Upvotes: 4