• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 453
  • Last Modified:

Read XML with Linq (the second)

I try to read the following XML Structure with Linq (yes, newbie here :) )

  <registry>
    <exclude_pcs>
      <pc></pc>
    </exclude_pcs>
    <detail></detail>
    <keys>
      <key>HKLM\Software\Microsoft\Windows\CurrentVersion\Run</key>
      <key>HKLM\Software</key>
    </keys>
  </registry>

My Code returns both values, but in one single string (HKLM\Software\Microsoft\Windows\CurrentVersion\Run\HKLM\Software)

What am I doing wrong?
This is what I am doing at the moment:
 
List<Object> keysSet = new List<Object>;
 
XElement configXML = XElement.Load(xmlFileName);
 
           var reg = configXML.Elements("registry");
 
            // Go through nodes
            foreach (XElement regNodes in reg)
            {
 
                // Keys
                var q = from c in regNodes.Descendants("keys")
                        select c;
 
                if (q.Count() > 0)
                {
                    foreach (String key in q)
                    {
                        if (! string.IsNullOrEmpty(key))
                        {
                            keysSet.Add(key);
                        }
                    }
                }
}

Open in new window

0
schubduese
Asked:
schubduese
  • 6
  • 2
  • 2
  • +1
1 Solution
 
abelCommented:
You are looping through the keys, not through the keys/key collection. Try:

var q = from c in regNodes.Descendants("key")                        select c;
instead.

0
 
abelCommented:
btw, your code does not compile, the first line misses parentheses ()
0
 
DhaestCommented:
You just need to change your linq-query

                // Keys
                var q = from c in regNodes.Descendants("key")
                        select c;
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
schubdueseAuthor Commented:
I know the code is not compiling, it's just an extract of the code... :)

thanks again abel
0
 
abelCommented:
Btw, since you placed this question on the LINQ Zone, what about making your code a bit easier by using LINQ? See snippet (tested and works with your source XML):

var reg = configXML.Elements("registry");
 
// Go through nodes
foreach (string keyValues in 
    from key in configXML.DescendantsAndSelf() 
    where key.Name == "key" 
    select key.Value)
{
 
    keysSet.Add(keyValues);
}

Open in new window

0
 
abelCommented:
And, now that we're on it, we can even make that a bit slimmer:

keysSet.AddRange(from key in configXML.DescendantsAndSelf()
                 where key.Name == "key"
                 select (object) key.Value);

Open in new window

0
 
Fernando SotoCommented:
Hi schubduese;

This code will get all the key values from the key node and place them into the List.

Fernando
// The list returned from query is of type string
List<String> keysSet = new List<String>();
// Load the XML document into a XElement structure
XElement configXML = XElement.Load(xmlFileName);
 
// Query the XML document for all the key nodes within the parent node keys
// and do not select those nodes with a inner text value of empty string and
// place the selected values into the List<String> keySet
keysSet = (from k in configXML.Descendants("keys").Descendants("key")
           where k.Value != String.Empty
           select k.Value).ToList();
 
// Display the values in the keySet
foreach (string key in keysSet)
{
    Console.WriteLine("Key = " + key);
}

Open in new window

0
 
schubdueseAuthor Commented:
great! thanks abel, that's fantastic!
0
 
abelCommented:
As fernando has showed, if you have <key></key> in your data that you do not want to include, you can add the "where key.Value != String.Empty" to the command:

keysSet.AddRange(from key in configXML.DescendantsAndSelf()
                 where key.Name == "key" and key.Value != String.Empty
                 select (object) key.Value);

Open in new window

0
 
Fernando SotoCommented:
Hi schubduese;

Please note that the solution by abel will select all nodes that have the name key no matter where it is in the document even if it is a child of a different node and not a child of the node keys.

Fernando
0
 
abelCommented:
That is entirely correct. But I took the liberty to take the input XML. Using the Descendants("keys").Descendants("key") you will make sure that they are a descendant to keys. Still, that doesn't help if you XML looks like this:

<keys>
     <specialkeys>
          <key>....</key>
     </specialkeys>
     <key>.....</key>
</keys>
because then both the special keys and the normal keys will get selected. If you need a better selection from your XML if the <key> can also appear on different levels and you do not want to include those, show a bit of the XML and we will help you further with it.
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

  • 6
  • 2
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now