BlackCath
BlackCath

Reputation: 826

C# Linq to XML, get parents when a child satisfy condition

I need some help. I have this xml document:

<?xml version="1.0" encoding="utf-8"?>
<MyItems>
    <Parent upc="A00000000000000000000001" sku="" archivo="pantalon1.jpg">
        <Child upc="101" sku="" archivo="image##.jpg">
            <GrandChild archivo="image##.jpg" />
        </Child>
        <Child upc="102" sku="" archivo="image##.jpg">
            <GrandChild archivo="image##.jpg" />
        </Child>
    </Parent>
    <Parent upc="A00000000000000000000002" sku="" archivo="image##.jpg">
        <Child upc="101" sku="" archivo="image##.jpg">
            <GrandChild archivo="image##.jpg" />
        </Child>
        <Child upc="102" sku="" archivo="image##.jpg">
            <GrandChild archivo="image##.jpg" />
        </Child>
    </Parent>
    <Parent upc="200" sku="" archivo="image##.jpg">
        <Child upc="201" sku="" archivo="image##.jpg">
            <GrandChild archivo="image##.jpg" />
        </Child>
        <Child upc="202" sku="" archivo="image##.jpg">
            <GrandChild archivo="image##.jpg" />
        </Child>
    </Parent>
</MyItems>

Then, I'm trying to select all the 'Parents' where a 'Child' fulfils a condition. Example, all the parents which contains a child where, child attribute upc is equal to 101

I was studying this article: Select nodes based on properties of descendant nodes

But I just can't get what I want.

Upvotes: 8

Views: 6309

Answers (4)

Enigmativity
Enigmativity

Reputation: 117175

This works nicely for me:

var query =
    from p in XDocument.Parse(xml).Root.Elements("Parent")
    where (
            from c in p.Elements("Child")
            where c.Attribute("upc").Value == "101"
            select c
        ).Any()
    select p;

Upvotes: 1

ojlovecd
ojlovecd

Reputation: 4902

try this:

            string xml = @"<?xml version=""1.0"" encoding=""utf-8""?>
<MyItems>
    <Parent upc=""A00000000000000000000001"" sku="""" archivo=""pantalon1.jpg"">
        <Child upc=""101"" sku="""" archivo=""image##.jpg"">
            <GrandChild archivo=""image##.jpg"" />
        </Child>
        <Child upc=""102"" sku="""" archivo=""image##.jpg"">
            <GrandChild archivo=""image##.jpg"" />
        </Child>
    </Parent>
    <Parent upc=""A00000000000000000000002"" sku="""" archivo=""image##.jpg"">
        <Child upc=""101"" sku="""" archivo=""image##.jpg"">
            <GrandChild archivo=""image##.jpg"" />
        </Child>
        <Child upc=""102"" sku="""" archivo=""image##.jpg"">
            <GrandChild archivo=""image##.jpg"" />
        </Child>
    </Parent>
    <Parent upc=""200"" sku="""" archivo=""image##.jpg"">
        <Child upc=""201"" sku="""" archivo=""image##.jpg"">
            <GrandChild archivo=""image##.jpg"" />
        </Child>
        <Child upc=""202"" sku="""" archivo=""image##.jpg"">
            <GrandChild archivo=""image##.jpg"" />
        </Child>
    </Parent>
</MyItems>";

            XElement MyItems = XElement.Parse(xml);
            var parents = MyItems.Elements("Parent").Where(parent => parent.Elements("Child").Any(child => child.Attribute("upc").Value == "101"));
            foreach (var parent in parents)
                Console.WriteLine(parent.Attribute("upc").Value);

Upvotes: 1

Kirk Broadhurst
Kirk Broadhurst

Reputation: 28738

Use a Where with a nested Any.

var xml = XElement.Parse(yourString);
var result = xml.Elements("Parent").Where(parent => 
    parent.Elements("Child").Any(child => child.Attribute("upc").Value == "101"));

Upvotes: 1

Jeff Mercado
Jeff Mercado

Reputation: 134611

XDocument doc = ...;
var targetUpc = 101;
var query = doc.Descendants("Parent")
    .Where(p => p.Elements("Child")
                 .Any(c => (int)c.Attribute("upc") == targetUpc)
    );

So what the query does is select all descendant elements named Parent where any of its child elements named Child have an attribute named upc that is equal to the target upc value, targetUpc. Hopefully you should be able to follow that.

Upvotes: 10

Related Questions