2010-02-13 4 views
1

J'essaye d'interroger ce document XML très compliqué en utilisant xDocument et LINQ to XML. Je souhaite effectuer l'action suivante:C# extension où méthode - gérer un cas lorsque l'élément n'est pas trouvé

Obtient tous les éléments répondant à un certain critère et, dans le cas contraire, renvoie un autre attribut du xDocument.

Exemple:

<cars> 
    <car> 
     <patrol type="oil"> 
      <url> http://Toyotaoil.com </url> 
     </patrol> 
    </car> 
    <car> 
     <patrol type="oil"> 
      <url> http://BMWoil.com </url> 
     </patrol> 
     <patrol type="gas"> 
      <url> http://BMWgas.com </url> 
     </patrol> 
    </car> 
    <car> 
     <patrol type="gas"> 
      <url> http://Hondagas.com </url> 
     </patrol> 
    </car> 

Maintenant, ce que je voudrais obtenir de cette requête est une liste de patrouilles d'huile de type, à moins que la voiture ne pas utiliser l'essence, et je serais satisfait gaz.

Si j'utilise la clause where, je manque juste les cas où la voiture utilise du gaz. Y at-il une telle chose comme une clause where, où je peux spécifier ce qu'il faut faire si la condition n'a pas été remplie?

+0

La partie de l'aperçu sur la page est là pour une raison, vous devez vous assurer de formater le contenu correctement avant de poster. –

Répondre

2

La solution ci-dessous devrait vous donner la possibilité d'interroger tout ce que vous voulez:

var result = from car in xdoc.Element("cars").Elements("car") 
      let patrols = car.Elements("patrol") 
      let oils = patrols.Where(patrol => patrol.Attribute("type") == "oil") 
      select new { 
        Car = car, 
        Patrols = (oils.Any() ? oils : patrols) 
      } 

Je n'ai pas Visual Studio ici, donc J'espère qu'il compile :)
Donnez un peu plus d'informations sur ce que vous aimez sélectionner, et je vais vous donner une déclaration LINQ plus spécifique.

+0

cela n'a pas fonctionné complètement, mais j'ai appris une approche totalement nouvelle (en utilisant le mot-clé let) qui m'a indiqué la bonne direction ... alors, merci! – vondip

-1

Order par type selon vos spécifications, prendre FirstOrDefault().


Edit: Ce que je voulais dire quelque chose comme ceci:

var patrols = from car in doc.Root.Elements() 
       let p = car.Elements().OrderBy(patrol=>patrol.Attribute("type").Value).First() 
       select p; 

Ce retourne un résultat par voiture. Vérifiez la clause OrderBy et ajustez-la en conséquence. Cela se traduirait par:

<patrol type="oil"> 
    <url> http://Toyotaoil.com </url> 
</patrol> 

<patrol type="gas"> 
    <url> http://BMWgas.com </url> 
</patrol> 

<patrol type="gas"> 
    <url> http://Hondagas.com </url> 
</patrol> 

Modifier à nouveau: Ah, maintenant il a cliqué. Oui, cela ne rapporte qu'un seul article par voiture - Zyphrax a donné une bonne solution.

+0

Il essaie de sélectionner plusieurs éléments, pas un seul. –

+0

@Jon: Je ne reçois pas votre réponse, ni la downvote. S'il vous plaît vérifier le poste à nouveau. –

0

Il semble que vous ne souhaitiez pas du tout une clause where - vous voulez juste une clause select qui choisit une valeur ou une autre.

Cependant, votre exemple ne décrit pas vraiment comment sélectionner un élément différent en fonction des valeurs - quel "autre attribut" choisiriez-vous? Que voulez-vous dire par "où la voiture utilise du gaz"? Si vous pouvez donner plus de détails sur l'exemple, il ne devrait pas être trop difficile de vous donner le code correspondant.

2
xdoc.Element("cars") 
    .Elements("car") 
    .Select(car => car.Elements("patrol") 
         .SingleOrDefault(p => (string)p.Attribute("type") == "oil") 
        ?? 
        car.Elements("patrol") 
         .Single(p => (string)p.Attribute("type") == "gas")); 
+0

Cela se traduira par un seul élément d'huile. Si je comprends bien, il faut retourner tous les éléments de patrouille pétrolière (le cas échéant) sinon renvoyer tout élément de patrouille. – Zyphrax

1

Vous pouvez juste faire quelque chose comme ceci:

var query = from element in someElements 
      select element.Attribute("type").Value == "oil" 
       ? returnSomethingWhenItIsOil 
       : returnSomethingWhenItIsSomethingElse; 

ou

var query = from element in someElements 
      where element.Attribute("type") == "oil" 
       || element.Attribute("type") == "gas" 
      select element; 

Mais expliquer mieux le problème, merci :)

+0

Pas tout à fait correct, cela retournera le pétrole ou le gaz. Pas seulement du pétrole ou s'il n'y a pas de pétrole, puis du gaz. – Zyphrax

+0

Ahh maintenant je l'ai eu;) merci pour le nettoyage. Alors je suppose que la solution de dtb fera l'affaire. –

0
     var cars = from c in xdoc.Descendants("car") 
         where 
         (c.Element("patrol").Attribute("type").Value == "oil" || 
         c.Element("patrol").Attribute("type").Value == "gas") 
         select new Car 
         { 
          FuelType = c.Element("patrol").Attribute("type").Value.ToString() 
         }; 

    foreach (Car c in cars) 
     { 
      Console.WriteLine(c.ToString()); 
     } 

    class Car 
    { 
     public string FuelType { get; set; } 
     public override string ToString() 
     { 
      return "Car FeulType = " + this.FuelType.ToString(); 
     } 
    } 

Ce sont les résultats, je reçois

alt text http://img694.imageshack.us/img694/5016/carse.jpg