Noob LINQ - Reading, Filtering XML with XDocument

I am just learning XDocument and LINQ queries. Here's a simple XML (which doesn't look formatted exactly in this forum in my browser, but you get the idea ...)

<?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>

      

I can loop through all the elements in my XML file and display their name, value and NodeType in the ListBox like this, no problem:

        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);
        }

      

... but now I want to add a "where" clause to my query so that I only select items with a specific name (eg "qa"), but my list of items is empty. I've tried.,

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

      

Can someone please explain what I am doing wrong? (and in general, are there any good tips for debugging queries?) Thanks in advance!

+2


a source to share


2 answers


The problem is that the Name property is not a string, it is XName . When you use ToString, you get a lot more than you think.

While it is possible to write the query the way you are trying, consider these possibilities as well:



//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


a source


I would change your request to something more like this

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")
            };

      

In doing so, you will pull q_a

internal elements from each of your descendants into IEnumerable<[Anonymous Type]>

, each object containing a number, a question and an answer.

However, if you just want to extract the XElements where the name is q_a, you can do so using the where clause.



IEnumerable<XElement> elem_list = elems.Where(elem => elem.Name.LocalName == "q_a");

      

Of course, as David B has shown, the sentence is not necessary here.

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

      

0


a source







All Articles