Say I have this data:
<recipe name="Fruit Salad">
<ingredient name="banana"/>
<ingredient name="oRange"/>
<ingredient name="APPLE"/>
</recipes>
and I have this other data:
<refrigerator>
<item name="appLe"/>
<item name="Grape"/>
</refrigerator>
and I want to find all the things needed for my recipes that are not already in my frig, to make a shopping list. The right answer is the set {banana, orange}
This doesn't work because lower-case() only takes a string. So does translate():
<xsl:variable name="missing-ingredients" select="recipe/ingredient/@name[not(lower-case(.)=lower-case(refrigerator/item/@name))]"/>
Without resorting to cheating (going outside xslt and xpath), how can I do this? I find it hard to imagine they didn't make a provision for this inside xpath, since node lookups are the bread and butter of xslt and xpath, and weren't not on the first versions anymore.
If I could just convert a list of nodes (a node-set, I suppose) to lowercase, I would be home free.
There's a problem with this XPath expression:
The expresson
refrigerator/item/@nameyields a sequence of attributes, rather than a single string, as thelower-case()function expects. You need to lower-case each one of the items in that sequence, by passing them to thelower-case()function individually. e.g.In XPath 3 there's a more concise alternative, the "simple map" operator
!, which would look like this: