tags:

views:

90

answers:

4

I have an XML file looks like this:

<?xml version="1.0" encoding="utf-8" ?> 
 <PathMasks>
 <Mask desc="Masks_X1">
  <config id="01" mask="88" /> 
  <config id="03" mask="80" /> 
  <config id="51" mask="85" /> 
  </Mask>

 <Mask desc="Masks_X2">
  <config id="70" mask="1" /> 
  <config id="73" mask="6" /> 
  </Mask>

 <Types>
  <path id="01" desc="TC->PP1" /> 
  <path id="02" desc="TC->PP2" /> 
  <path id="03" desc="TC->PPn" /> 
  </Types>
  </PathMasks>

How to parse the file and get all the data of Mask_X1 as following:

id  value
=====
01, 88
03, 80
51, 85

The .NET framework I am using is 2.0

A: 

Use XDocument and query into it with Linq to XML

XDocument doc = XDocument.Load("file.xml");
var linqtoxml = from node in document.Descendants("Mask")
    where (string)node.Attribute("desc").Value == "Masks_X1"
    select node;
foreach (var mask in linqtoxml)
{
    // pull data out of here into a structure of your choosing
}
ZombieSheep
I am using .NET 2.0, it seems that there is not linq in System.Xml namespace
Carlos_Liu
In that case, you are pretty much stuck with XmlDocument and XPath queries.
ZombieSheep
A: 

Using Linq to XML :

XDocument doc = XDocument.Load(filename);
var query = from mask in doc.Root.Elements("Mask")
            where mask.Attribute("desc").Value == "Masks_X1"
            from config in mask.Elements("config")
            select new
            {
                id = config.Attribute("id").Value,
                value = config.Attribute("mask").Value
            };

foreach(var mask in query)
{
    Console.WriteLine("{0}\t{1}", mask.id, mask.value);
}
Thomas Levesque
+2  A: 

Hi,

As you're working with .Net 2.0 you won't have Linq and will therefore need to use XPath, this sample should help you out.

        XmlDocument doc = new XmlDocument();

        doc.Load(pathToXmlDoc);


        XmlNode node = doc.SelectSingleNode("/PathMasks/Mask[@desc='Masks_X1']");

        foreach (XmlNode config in node)
        {
            Console.WriteLine("{0}\t{1}", 
                            config.Attributes["id"].Value,
                            config.Attributes["mask"].Value);
        }
Alan
`SelectSingleNode` returns a single node or null. You can't iterate over the result.
John Saunders
Using the SelectSingleNode does indeed return a single XmlNode. However each XmlNode contains a collection of child nodes, the foreach in this example iterates over each of the child nodes under the single Mask node that was selected. So in this example SelectSingleNode will select the Mask node with a desc attribute that holds the value Mask_X1. The returned XmlNode's ChildNodes property will hold three entries one for each of the config nodes under the Mask node. We can the iterate over the child nodes and produce the required output.
Alan
+1  A: 

Using XmlDocument (slower, larger memory footprint, read/write, works the same way XML DOMs everywhere work):

XmlDocument d = new XmlDocument();
d.Load(filename);
string xpath = "/PathMasks/Mask[@desc='Mask_X1']/config"
foreach (XmlElement elm in d.SelectNodes(xpath))
{
   Console.WriteLine(elm.GetAttribute("id"), elm.GetAttribute("desc"));
}

Using XPathDocument (faster, smaller memory footprint, read-only, weird API):

XPathDocument d = new XPathDocument(filename);
string xpath = "/PathMasks/Mask[@desc='Mask_X1']/config"
XPathNodeIterator iter = d.CreateNavigator().Select(xpath);
while (iter.MoveNext())
{
   Console.WriteLine(iter.Current.GetAttribute("id"), iter.Current.GetAttribute("desc'));
}

I'm sure there's a perfectly good reason why there isn't a method of XPathNavigator that returns an IEnumerable<XPathNavigator> so that you can iterate over the results of an XPath query like a normal person, but I haven't been able to work it out.

Robert Rossney
`XPathDocument` predates `IEnumerable<XPathNavigator>`. Feel free to write your own extension method to do this, then publish it here.
John Saunders
One of these days I'll remember the technologies are introduced in the order they're introduced, not in the order I learned about their existence.
Robert Rossney