Solved

Link query

Posted on 2008-10-08
9
272 Views
Last Modified: 2013-12-17
Is there an easy way to get to the individual elements in the XML?

  XDocument books = new XDocument(
                                    new XElement("Books",
                                new XElement("book",
                                    new XElement("name", "Book 1"),
                                    new XElement("author", "John Doe")),
                                new XElement("book",
                                    new XElement("name", "Book 2"),
                                    new XElement("author", "Jane Doe"))));


 IEnumerable<XElement> elements;
            elements = books.Element("Books").Elements("book");


 foreach (XElement element in elements.Elements())
{
// Something like
element["name"].value;
element["author"].value;

// instead of looping - returns Book 1john Doe
element.value;

}

thanks


0
Comment
Question by:sansoftura
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 4
9 Comments
 
LVL 21

Expert Comment

by:naspinski
ID: 22670135
you could simply do something like this:
foreach (XElement x in (from p in books.Descendants("book"))
  //loop here
 
//or if you just want the first one
XElement xe = (from p in books.Descendants("book").First();
//then just use it like this:
string value = xe.Value;
 
//Does that answer your question?

Open in new window

0
 
LVL 6

Author Comment

by:sansoftura
ID: 22670457
Thanks. I just added 'select p' to your first for each
foreach (XElement x in (from p in books.Descendants("book") select p))

but still how do i get to each item in the element
x("name")
x("author")

?
0
 
LVL 63

Expert Comment

by:Fernando Soto
ID: 22670701
Hi sansoftura;

This code snippet will do what you want.

Fernando

            XDocument books = new XDocument(
                                    new XElement("Books",
                                        new XElement("book",
                                            new XElement("name", "Book 1"),
                                            new XElement("author", "John Doe")),
                                        new XElement("book",
                                            new XElement("name", "Book 2"),
                                            new XElement("author", "Jane Doe"))));
 
            var elements = from book in books.Document.Root.Elements("book")
                           select new
                           {
                               Name = book.Element("name").Value,
                               Author = book.Element("author").Value
                           };
 
            foreach (var element in elements)
                Console.WriteLine("Book Name = {0}\nBook Author = {1}",
                        element.Name, element.Author);

Open in new window

0
Salesforce Made Easy to Use

On-screen guidance at the moment of need enables you & your employees to focus on the core, you can now boost your adoption rates swiftly and simply with one easy tool.

 
LVL 6

Author Comment

by:sansoftura
ID: 22671779
Thanks that helped . But if i want to get the elements from the node books how do i get it?

say
<Books>
<book>
...
</book>
<book>
...
</book>
<ImportDate>1/1/1980</ImportDate>
<ImportUser>Fernando</ImportUser>
</Books>

How do i get to the other elements?

0
 
LVL 63

Expert Comment

by:Fernando Soto
ID: 22672300
Hi sansoftura;


There are a couple of approaches to this question:
1. you can do the query like the following:
 
   IEnumerable<XElement> elements = from book in books.Document.Root.Elements("book")
                                    select book;
 
then in the foreach loop you can get each node of type "book". Then for each element you can get it Descendants and print out its values. But this causes you to use XML to navigate the child nodes and pull out the values you need.
 
2. Another approache is to get the information you want in the select clause and return that as an Anonymous type as in the following.
 
   var elements = from book in books.Document.Root.Elements("book")
                  select new
                  {
                     Name = book.Element("name").Value,
                     Author = book.Element("author").Value,
                     ImportDate = book.Element("ImportDate").Value,
                     ImportUser = book.Element("ImportDate").Value
                  };
 
then in the foreach loop get the needed values as in the following code.
 
foreach (var element in elements)
   Console.WriteLine("Book Name = {0}\nBook Author = {1}\nImport Date = {2}\tImport User = {3}",
      element.Name, element.Author, element.ImportDate, element.ImportUser );
 
Note that in the select clause above, variable = node value, the variable name used here can be anything you want just like any other C# variable name and that is the name you use to access that value in the foreach loop.
 
Fernando

Open in new window

0
 
LVL 6

Author Comment

by:sansoftura
ID: 22672865
Thanks Fernando. I tried the above method but i am not getting the value for the elements in book  (ImportDate, ImportUser)
            XElement books = new XElement(
                                    new XElement("Books",
                                       new XElement("ImportDate", "1/1/80"),
                                       new XElement("ImportUser", "Fernando"),
                                       new XElement("book",
                                    new XElement("name", "Book 1"),
                                    new XElement("author", "John Doe")),
                                new XElement("book",
                                    new XElement("name", "Book 2"),
                                    new XElement("author", "Jane Doe"))));
 
// Code works
          var elements = from book in books.Elements("book")
                           select new
                           {
                               name = book.Element("name").Value,
                               author = book.Element("author").Value
                           };
            foreach (var element in elements)
                MessageBox.Show("Book Name = " + element.name + "\nBook Author = " + element.author);
 
// End code works
 
// New Code that doesn't work
          
            var newElements = from book in books.Descendants()
                           select new
                           {
                               ImportDate = book.Element("ImportDate").Value,
                               ImportUser = book.Element("ImportUser").Value
                           };
 
            foreach (var importElement in newElements)
                MessageBox.Show("ImportDate = " + importElement.ImportDate + "\nImportUser = " + importElement.ImportUser);

Open in new window

0
 
LVL 63

Accepted Solution

by:
Fernando Soto earned 500 total points
ID: 22673657
Because the new document now looks like this:

<Books>
  <ImportDate>1/1/80</ImportDate>
  <ImportUser>Fernando</ImportUser>
  <book>
    <name>Book 1</name>
    <author>John Doe</author>
  </book>
  <book>
    <name>Book 2</name>
    <author>Jane Doe</author>
  </book>
</Books>

ImportDate and ImportUser are at the same level as book. Then you would need to change the query in such a way to catch the needed nodes and if you had multiple nodes of ImportDate and ImportUser and wanted book as well it would become difficult to do. One way to get thoes two fields if they were to be the only nodes of there type would be as follows:

String importDate = books.Element("ImportDate").Value;
String importUser = books.Element("ImportUser").Value;

To query an XML document you need to know before hand the schema of the document and create the query from that.
0
 
LVL 6

Author Closing Comment

by:sansoftura
ID: 31504285
Thanks! that worked.

Just curious when we use  IEnumerable elements  to query the XML?

0
 
LVL 63

Expert Comment

by:Fernando Soto
ID: 22678814
Hi sansoftura;

To your question, "when we use  IEnumerable<XElement> elements  to query the XML?", The   elements variable is typed with IEnumerable<XElement> when the query parses the XML document and does not create an anonymous type like was done in one of the sample code. For example  in the following snippet oc code the return type is a collection of XElement and therefore you can use IEnumerable<XElement>:

IEnumerable<XElement> elements =
    from book in books.Document.Root.Elements("book")
    select book;

In the above the books document is queryed and each element that is parsed is placed into book variable and in the select statement a collection of book is created and returned which are still XElement. While in the following code this is not true:

var elements = from book in books.Document.Root.Elements("book")
               select new
               {
                   Name = book.Element("name").Value,
                   Author = book.Element("author").Value,
               };

The reason this is not true is that in the select clause we create a collection of an anonymous type by using the new keyword with the structure of that anonymous type,

      select new
               {
                   Name = book.Element("name").Value,
                   Author = book.Element("author").Value,
               };

Fernando

0

Featured Post

Get free NFR key for Veeam Availability Suite 9.5

Veeam is happy to provide a free NFR license (1 year, 2 sockets) to all certified IT Pros. The license allows for the non-production use of Veeam Availability Suite v9.5 in your home lab, without any feature limitations. It works for both VMware and Hyper-V environments

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In my previous two articles we discussed Binary Serialization (http://www.experts-exchange.com/A_4362.html) and XML Serialization (http://www.experts-exchange.com/A_4425.html). In this article we will try to know more about SOAP (Simple Object Acces…
For those of you who don't follow the news, or just happen to live under rocks, Microsoft Research released a beta SDK (http://www.microsoft.com/en-us/download/details.aspx?id=27876) for the Xbox 360 Kinect. If you don't know what a Kinect is (http:…
Michael from AdRem Software outlines event notifications and Automatic Corrective Actions in network monitoring. Automatic Corrective Actions are scripts, which can automatically run upon discovery of a certain undesirable condition in your network.…
Monitoring a network: why having a policy is the best policy? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the enormous benefits of having a policy-based approach when monitoring medium and large networks. Software utilized in this v…

615 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question