2010-04-14 6 views
2

Je suis en train d'apprendre des requêtes XDocument et LINQ. Voici quelques XML simple (qui ne semble pas formaté exactement droit dans ce forum dans mon navigateur, mais vous voyez l'idée...)Noob LINQ - lecture, filtrage XML avec XDocument

<?xml version="1.0" encoding="utf-8"?> 
<quiz 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.example.com/name XMLFile2.xsd" 
    title="MyQuiz1"> 
    <q_a> 
    <q_a_num>1</q_a_num> 
    <q_>Here is question 1</q_> 
    <_a>Here is the answer to 1</_a> 
    </q_a> 

    <q_a> 
    <q_a_num>2</q_a_num> 
    <q_>Here is question 2</q_> 
    <_a>Here is the answer to 2</_a> 
    </q_a> 
</quiz> 

J'itérer sur tous les éléments dans mon fichier XML et afficher leur nom , la valeur et NodeType dans un ListBox comme celui-ci, pas de problème:

 XDocument doc = XDocument.Load(sPath); 
     IEnumerable<XElement> elems = doc.Descendants(); 

     IEnumerable<XElement> elem_list = from elem in elems 
              select elem; 

     foreach (XElement element in elem_list) 
     { 
      String str0 = "Name = " + element.Name.ToString() + 
          ", Value = " + element.Value.ToString() + 
          ", Nodetype = " + element.NodeType.ToString(); 
      System.Windows.Controls.Label strLabel = new System.Windows.Controls.Label(); 
      strLabel.Content = str0; 
      listBox1.Items.Add(strLabel); 
     } 

... mais maintenant je veux ajouter un « where » à ma requête pour que je sélectionne uniquement des éléments avec un certain nom (par exemple , "qa") mais ma liste d'éléments apparaît vide. J'ai essayé . . .

  IEnumerable<XElement> elem_list = from elem in elems 
             where elem.Name.ToString() == "qa" 
             select elem; 

Quelqu'un pourrait-il expliquer ce que je fais mal? (et en général y a-t-il de bons conseils pour déboguer des requêtes?) Merci d'avance!

Répondre

1

Le problème est que la propriété Name est pas une chaîne, il est un XName. Quand vous le ToString, vous obtenez beaucoup plus que vous ne le pensez.

Bien qu'il soit possible d'écrire la requête de la manière que vous essayez de, également ces possibilités:

//from nodes immediately below this one 
IEnumerable<XElement> elem_list = doc.Elements("qa"); 

//from nodes of all levels below this node. 
IEnumerable<XElement> elem_list = doc.Descendants("qa"); 
+1

Cependant, pour obtenir le nom non qualifié comme une chaîne, il peut utiliser 'elem.Name. LocalName.' –

0

je serais peut-être changer votre requête à quelque chose qui ressemble plus à ce

var query = from q_a in document.Descendants("q_a") 
      select new 
      { 
       Number = (int)q_a.Element("q_a_num"), 
       Question = (string)q_a.Element("q_"), 
       Answer = (string)q_a.Element("_a") 
      }; 

Avec cela, vous tirez de chacun de vos q_a descendants les éléments intérieurs dans un IEnumerable<[Anonymous Type]>, chaque objet contenant le nombre, question et réponse. Toutefois, si vous souhaitez simplement extraire les XElements dont le nom est q_a, vous pouvez le faire en utilisant une clause where. Bien sûr, comme l'a montré David B, la clause where n'est pas nécessaire ici.

IEnumerable<XElement> elem_list = elems.Elements("q_a");