Reputation: 9677
I have xml containing attributes with comma seperated values. I am aware this is not a good idea, but stuck with it for now.
I like to select elements with matching attribute values using XPath. I want the match to only consider full values, not partial matches. Is it possible to do this with XPath?
See C# code below for example. I use .NET 4.0.
string xml = @"<Foos>
<Foo Tag=""AA, BB"" />
<Foo Tag=""BB"" />
<Foo Tag=""AAA, BBB"" />
</Foos>";
using (StringReader reader = new StringReader(xml))
{
XElement doc = XElement.Load(reader);
// I like to select elements with tag BB:
// <Foo Tag=""AA, BB"" />
// <Foo Tag=""BB"" />
var fooElementsWithTagBB = doc.XPathSelectElements("//Foo[@Tag = 'BB']"); // Selects only <Foo Tag=""BB"" />
fooElementsWithTagBB = doc.XPathSelectElements("//Foo[contains(@Tag, 'BB')]"); // Selects all elements
}
I would like a general query, I know
Foo[@Tag = 'AA, BB' or @Tag = 'BB']
would work in this example.
Upvotes: 2
Views: 125
Reputation: 243459
Use:
//Foo[contains(concat(',',@Tag, ','), ',BB,')]
If trere are spaces between a comma and the next value, you can eliminate them as in the following XPath expression:
//Foo[contains(concat(',',translate(@Tag, ' ', ''), ','), ',BB,')]
XSLT - based verification:
<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="*"/>
<xsl:template match="/">
<xsl:copy-of select=
"//Foo[contains(concat(',',translate(@Tag, ' ', ''), ','), ',BB,')]"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the provided XML document:
<Foos>
<Foo Tag="AA, BB"/>
<Foo Tag="BB" />
<Foo Tag="AAA, BBB" />
</Foos>
the XPath expression is evaluated and the result of this evaluation (the selected nodes) is copied to the output:
<Foo Tag="AA, BB"/>
<Foo Tag="BB"/>
Explanation:
This is an illustration of sentinel programming.
Upvotes: 1