Wallstreet Programmer
Wallstreet Programmer

Reputation: 9677

Select elements using attributes with multiple values

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

Answers (1)

Dimitre Novatchev
Dimitre Novatchev

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

Related Questions