Jump to content


Check out our Community Blogs

Register and join over 40,000 other developers!


Recent Status Updates

View All Updates

Photo
- - - - -

[SOLVED} C# and XML

c# xml

  • Please log in to reply
7 replies to this topic

#1 crokett

crokett

    CC Addict

  • Advanced Member
  • PipPipPipPipPip
  • 109 posts
  • Programming Language:C#, Perl
  • Learning:C#, Perl, Transact-SQL

Posted 17 October 2012 - 05:41 PM

I was asked today to look at a new project - parsing some XML with C#. I have gotten this far with this code that so far works. I get the 4 node lists successfully. I have a couple problems. First I am not sure how to access what is in the <property> tag on any of the nodes in any of the lists. Second, I'd prefer to be able to use LINQ queries but XmlNodeList doesn't seem to support that syntax. In the sample XML below, I'd like to be able to get all the vdisks that belong to a particular IO Group or mdisk as determined by io_group_name or mdisk_grp_name property.

What I tried is also below, it gave a null value exception. The Attributes list only has one attribute. I can't find any examples to do what I want and it isn't clear from inspecting the node in the debugger what I need to access to do what I want.


//this works

XmlTextReader reader = new XmlTextReader(_InputFile);
XmlDocument doc = new XmlDocument();
doc.Load(reader);

XmlNodeList clusterlist = doc.SelectNodes("//object[@type='cluster']");
XmlNodeList controllerlist = doc.SelectNodes("//object[@type='controller']");
XmlNodeList mdisklist = doc.SelectNodes("//object[@type='mdisk']");
XmlNodeList vdisklist = doc.SelectNodes("//object[@type='vdisk']");


/// this did not work - got null value exception
foreach (XmlNode vdisknode in vdisklist)
{
string str = vdisknode.Attributes["mdisk_grp_name"].Value;
}


A sample of the XML:



<object type="vdisk" >
<property name="id" value="0" />
<property name="name" value="nim01_vd06_gmt" />
<property name="IO_group_id" value="0" />
<property name="IO_group_name" value="ossvc06_iogrp0" />
<property name="status" value="online" />
<property name="mdisk_grp_id" value="0" />
<property name="mdisk_grp_name" value="T1_OSIBM06_MDG1" />
<property name="capacity" value="644245094400" />
<property name="type" value="striped" />
<property name="formatted" value="no" />
<property name="mdisk_id" value="" />
<property name="mdisk_name" value="" />
<property name="FC_id" value="0" />
<property name="FC_name" value="nim01_fc1rel06" />
<property name="RC_id" value="0" />
<property name="RC_name" value="nim01_gmrel06" />
<property name="vdisk_UID" value="60050768018D83156000000000000000" />
<property name="throttling" value="0" />
<property name="preferred_node_id" value="3" />
<property name="fast_write_state" value="not_empty" />
<property name="cache" value="readwrite" />
</object.

  • 0

#2 lespauled

lespauled

    CC Leader

  • Expert Member
  • PipPipPipPipPipPipPip
  • 1360 posts
  • Programming Language:C, C++, C#, JavaScript, PL/SQL, Delphi/Object Pascal, Visual Basic .NET, Pascal, Transact-SQL, Bash

Posted 18 October 2012 - 05:12 AM

That's because each node doesn't have an mdisk_grp_name attribute. You can look through to find that node, then get the value.
  • 0
My Blog: http://forum.codecal...699-blog-77241/
"Women and Music: I'm always amazed by other people's choices." - David Lee Roth

#3 crokett

crokett

    CC Addict

  • Advanced Member
  • PipPipPipPipPip
  • 109 posts
  • Programming Language:C#, Perl
  • Learning:C#, Perl, Transact-SQL

Posted 18 October 2012 - 06:43 AM

well after some fumbling around, this works. However I am wondering in each Xelement is there XName syntax to access the property/attribute directly?


  XDocument xdoc = Xdocument.Load(_InputFile);

            var clusters = from cluster in xdoc.Descendants("object")
                       where cluster.Attribute("type").Value == "cluster"
                       select cluster;

            var mdisks = from mdisk in xdoc.Descendants("object")
                         where mdisk.Attribute("type").Value == "mdisk"
                         select mdisk;

            var mdiskgroups = from mdiskgroup in xdoc.Descendants("object")
                              where mdiskgroup.Attribute("type").Value == "mdisk_grp"
                              select mdiskgroup;

            var controllers = from controller in xdoc.Descendants("object")
                              where controller.Attribute("type").Value == "controller"
                              select controller;

            var vdisks = from vdisk in xdoc.Descendants("object")
                         where vdisk.Attribute("type").Value == "vdisk"
                         select vdisk;


            foreach (XElement mdisk in mdiskgroups)
            {
                var name = from prop in mdisk.Elements("property")
                           where (string)prop.Attribute("name") == "name"
                           select prop;

                string  namestring = name.FirstOrDefault().Attribute("value").Value;


                var status = from prop in mdisk.Elements("property")
                             where (string)prop.Attribute("name") == "status"
                             select prop;
                string statusstring = status.FirstOrDefault().Attribute("value").Value;

            }

  • 1

#4 VNFox

VNFox

    CC Devotee

  • Senior Member
  • PipPipPipPipPipPip
  • 648 posts
  • Programming Language:C#, PHP
  • Learning:Assembly

Posted 19 October 2012 - 02:22 PM

Aight..... looks complicated ... usually I just do it data readXML .. then parse them through row and columns. It looks like you have query inside your loop.
  • 0

www.pickmike.com
I don't just develop software. I find solutions to your business needs.


#5 crokett

crokett

    CC Addict

  • Advanced Member
  • PipPipPipPipPip
  • 109 posts
  • Programming Language:C#, Perl
  • Learning:C#, Perl, Transact-SQL

Posted 19 October 2012 - 06:59 PM

I had those queries inside the loop. I figured out the XPath with more fumbling. The problem is the schema in the XML I am working with is poorly designed, at least according to the folks who know more than me that I also consulted. All those <property> tags should really be set up as attributes, since that is what they are. Most of the XML parsing examples I looked at expect attributes and not the property tags. As such those tags create child nodes on each node when I do the initial read. I didn't design the schema and have no control over it so....
  • 0

#6 BlackRabbit

BlackRabbit

    CodeCall Legend

  • Expert Member
  • PipPipPipPipPipPipPipPip
  • 3871 posts
  • Location:Argentina
  • Programming Language:C, C++, C#, PHP, JavaScript, Transact-SQL, Bash, Others
  • Learning:Java, Others

Posted 19 October 2012 - 08:17 PM

Uff, poorly designed schemas are headaches, a word of advice, in shortening the code's sake, is to write some methods, which given a node and a attribute "name", searches for it in the whole node. Taking care of the null or no path situations, converting the data, etc. you can iterate that function with the list of required attribute names.
  • 0

#7 crokett

crokett

    CC Addict

  • Advanced Member
  • PipPipPipPipPip
  • 109 posts
  • Programming Language:C#, Perl
  • Learning:C#, Perl, Transact-SQL

Posted 21 October 2012 - 01:13 PM

I have attached a zip file containing the project and the incoming XML file. I ran into a bug when I am parsing the object type of Node - NOT an XmlNode, there is a line in the file that reads <object type="node" >

A Node has 4 ports on it. Each of those ports has these properties:


  <property name="port_id" value="50050768014062AC" />
    <property name="port_status" value="active" />
    <property name="port_speed" value="4Gb" />
    <property name="port_id" value="50050768013062AC" />
    <property name="port_status" value="active" />
    <property name="port_speed" value="4Gb" />
    <property name="port_id" value="50050768011062AC" />
    <property name="port_status" value="active" />
    <property name="port_speed" value="4Gb" />
    <property name="port_id" value="50050768012062AC" />
    <property name="port_status" value="active" />
    <property name="port_speed" value="4Gb" />

this code is supposed to build 3 lists and walk the lists extracting the properties. However, I get an index out of bounds exception. I expect 4 entries in each list. The problem is there are 2 objects of type node in this XML file. When I examine the XElement lists in the debugger, I am seeing the properties from each node in both XElements. I end up with 12 entries in the wwpns list, and 8 in the other two. I am not sure why.


 //these lists all have duplicate entries.  there should be 4 entries in each list since there are 4 ports.
            List<XElement> wwpns = element.XPathSelectElements("//property[@name='port_id']").ToList();
            List<XElement> states = element.XPathSelectElements("//property[@name='port_status']").ToList();
            List<XElement> speeds = element.XPathSelectElements("//property[@name='port_speed']").ToList();

            //this shows properties from other nodes 
            // just added this line to examine the elements in the debugger
            List<XElement> nodeles = element.Elements().ToList();

            var wwpnvar = element.XPathSelectElements("//property[@name='port_id']");

            for (int i = 0; i < wwpns.Count(); i++)
            {
                FCPort port = new FCPort();

                port.WWPN = wwpns[i].Attribute("value").Value;
                port.Status = states[i].Attribute("value").Value;
                port.Speed = speeds[i].Attribute("value").Value;
                node.PortList.Add(port);
            }

Attached Files


  • 0

#8 crokett

crokett

    CC Addict

  • Advanced Member
  • PipPipPipPipPip
  • 109 posts
  • Programming Language:C#, Perl
  • Learning:C#, Perl, Transact-SQL

Posted 23 October 2012 - 04:49 AM

Solved!!! I figured out after doing more inspection in the debugger that this statement:


XElemen wwpns = element.XPathSelectElement("//property[@name='port_id']")ToList();

says to get all the matching elements and start at document Root. I removed the // in front of property and the code now works the way I expected. :)

This would all be a lot easier if the XML file had a properly designed schema....
  • 0





Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download