2009-04-24 4 views
3

Ich habe die folgende XML-Dokument:Beste LINQ-zu-XML-Abfrage zum Auswählen von Knoten basierend auf Eigenschaften von Nachkommenknoten?

<?xml version="1.0" encoding="UTF-8"?> 
<FamilyTree> 
    <Parent name="Ken"> 
    <Child name="Lorna"> 
     <Grandchild name="Andrew"/> 
     <Grandchild name="Brian"/> 
    </Child> 
    <Child name="Mike"> 
     <Grandchild name="Ann"/> 
     <Grandchild name="Beth"/> 
    </Child> 
    </Parent> 
    <Parent name="Norma"> 
    <Child name="Owen"> 
     <Grandchild name="Charles"/> 
    </Child> 
    <Child name="Peter"> 
     <Grandchild name="Charlotte"/> 
    </Child> 
    </Parent> 
    <Parent name="Quinn"> 
    <Child name="Robert"> 
     <Grandchild name="Debbie"/> 
     <Grandchild name="Eric"/> 
    </Child> 
    <Child name="Susan"> 
     <Grandchild name="Frank"/> 
    </Child> 
    </Parent> 
    <Parent name="Tom"> 
    <Child name="Ursula"> 
     <Grandchild name="George"/> 
     <Grandchild name="Harriet"/> 
    </Child> 
    <Child name="Victor"> 
     <Grandchild name="Ian"/> 
     <Grandchild name="Juliet"/> 
    </Child> 
    </Parent> 
</FamilyTree> 

Ich versuche, alles wählen Sie die „Eltern“ mit einem Kind, das mindestens zwei Kinder („Enkel“) seiner/ihrer eigenen hat. Beachten Sie, dass ich bin nicht auf der Suche nach "Eltern" mit mindestens zwei "Enkelkind [ren]".

Die folgende LINQ-Abfrage funktioniert, aber ich habe das Gefühl, dass es nicht die eleganteste ist.

IEnumerable<XElement> parents = (from c in familyTreeElement.Descendants("Child") 
           where c.Elements().Count() > 1 
           select c.Parent).Distinct(); 

Gibt es eine bessere Möglichkeit, dies zu spezifizieren?

+0

Erster Kommentar - das ist für mindestens * zwei * Kinder ... –

+1

Vielen Dank. Ich habe den Tippfehler behoben. Ich möchte in der Tat nach mindestens zwei Kindern suchen. – Gayle

Antwort

2

Ahh Bearbeitungs (2 Enkelkinder) hilft ;-p

Während XDocument nützlich, manchmal vermisse ich XPath/XQuery. Mit XmlDocument können Sie einfach doc.DocumentElement.SelectNodes("Parent[Child/Grandchild[2]]") verwenden.

+0

Gibt es einen Grund, XPathExtensions nicht zu benutzen? –

+0

Ja, tut mir leid. Tippfehler Ich habe zu viel nachgedacht, als ich alles erklären wollte. – Gayle

+0

@Jon - wahr, wahr - ich habe Blindheit für sie ... –

0

Ich weiß nicht, „SQL-like“ Syntax genug, um zu garantieren, dass ich die Syntax bekommen richtig, wenn ich es so schreiben, aber Sie wollen .Any() verwenden, anstatt .Count(), und wenn Sie wählen in einem andere Weise, Sie brauchen nicht die Distinct() am Ende. Versuchen Sie folgendes:

IEnumerable<XElement> parents = 
    familyTreeElement.Elements("Parent").Where(
     parent => parent.Elements("Child").Any(
      child => child.Elements().Count() >= 2)); 

EDIT: Wenn Sie sicherstellen wollen, dass es mindestens zwei, tun Sie haben ziemlich viel .Count() zu verwenden.

+0

Count() ist für Wimps - Sie können ohne es wegkommen;) –

5

Hmmm ... Ich finde es schwer, meinen Kopf um es genau zu bekommen :)

Normalerweise, wenn es um herauszufinden, sind alle Elemente, würde ich verwenden Any - aber Sie wollen sehen, wenn es mindestens zwei Elemente gibt. Wir müssen aber immer noch nicht Count verwenden - weil es mindestens zwei Elemente gibt, die dasselbe sind wie ein Element zu überspringen und zu sehen, ob es noch welche gibt. So ...

var parents = familyTreeElement.Elements("Parent") 
    .Where(parent => parent.Elements("Child").Any(
        child => child.Elements("Grandchild").Skip(1).Any())); 

Ich denke, das funktioniert - und eigentlich ist es nicht auch liest schlecht:

Für jeden Elternteil sehen, ob jeden von dort Kindern hat jeden (grand) Kinder nach dem Ignorieren des ersten (Groß-) Kindes.

Ich vermute, dass die Verwendung von XPath (laut Marc's Antwort) die am besten lesbare Option wäre.

+0

Das ist eine clevere Möglichkeit zu finden, ob es zwei ohne zu zählen gibt. +1. – mquander

+2

Ich hatte vorher nicht daran gedacht, aber genau so würden wir es als Menschen machen. Wenn wir gefragt würden, ob es mindestens zehn Kekse in der Dose gäbe, würden wir nur so weit schauen wie die ersten zehn, die wir sahen :) –