XML reading question (Urgent)

<DataType>
   <PetOwned>
      <PetType value = Dog>
       <Age value = 1>
       <Fleas value = None>
       <Tank Value = none>
       <WaterType value = none>
   </PetOwned>
</DataType>
<DataType>
   <PetOwned>
      <PetType value = Fish>
       <Age value = unknown>
       <Fleas value = None>
      <Tank Value = 10gal>
      <WaterType value = Fresh>
   </PetOwned>
</DataType>

Ok the above XML is an example.

What I am trying to do is loop through the PetTypes (I have this working) and get the type of pet.

Based on the type of pet I am only going to need to pull certain nodes out and place them into a text box. (this I am stuck on)

example for Pet Type Dog.  I only need The age. For fish I only need the 10gal

How do I pull the nodes under that specific PetType node?  Right now I have it pulling the first one in the xml even if the PetType does not match. Does anyone have any code examples.

         // Loop through all messages,saving any messages that are found in an array.
         XmlNodeList nodeListType = xmlDoc.SelectNodes("/DataType/PetOwned/PetType");
         foreach (XmlNode xmlNodeType in nodeListType)
         {
           string sNameType = xmlNodeType.Attributes["value"].InnerText;

            //pull where the typenode is Dog
            if (sNameType =="Dog")
            {
                //only pull the needed nodes for example Age, Fleas
            }
            else if (sNameType == "Fish"
            {
               //only pull the needed nodes for example Tank, Watertype
             }

LVL 2
NewMom2BrandonAsked:
Who is Participating?
 
Bob LearnedCommented:
If you have control over the XML format, I would suggest this format:

<?xml version="1.0"?>
<Data>
     <DataType>
             <PetOwned type="Dog" age="1" fleas="None" tank="none" water="none"/>
     </DataType>
     <DataType>
             <PetOwned type ="Fish" age ="unknown" fleas value="None" tank="10gal" water="Fresh"/>
     </DataType>
</Data>

You could do XPath expressions like this:

  //PetOwned[@type='Dog']

Bob
0
 
Ravi SinghSenior Software EngineerCommented:
Hi, the example XML given wasn't well formed, if you had the corrected version below:

<?xml version="1.0"?>
<root>
      <DataType>
               <PetOwned>
                        <PetType value="Dog">
                               <Age value="1"/>
                               <Fleas value="None"/>
                               <Tank value="none"/>
                               <WaterType value="none"/>
                  </PetType>
               </PetOwned>
      </DataType>
      <DataType>
               <PetOwned>
                        <PetType value="Fish">
                               <Age value="unknown"/>
                               <Fleas value="None"/>
                              <Tank value="10gal"/>
                              <WaterType value="Fresh"/>
                  </PetType>
               </PetOwned>
      </DataType>
</root>


then to access them values you'd have something like:

      // Loop through all messages,saving any messages that are found in an array.
      XmlNodeList nodeListType = xmlDoc.DocumentElement.SelectNodes("DataType/PetOwned/PetType");
                  
      foreach (XmlNode xmlNodeType in nodeListType)
      {
            string sNameType = xmlNodeType.Attributes["value"].InnerText;

            //pull where the typenode is Dog
            if (sNameType == "Dog")
            {
                  //only pull the needed nodes for example Age, Fleas
                  this.textBox1.Text = xmlNodeType.SelectSingleNode("Age").Attributes["value"].InnerText;
            }
            else if (sNameType == "Fish")
            {
                  //only pull the needed nodes for example Tank, Watertype
                  this.textBox2.Text = xmlNodeType.SelectSingleNode("Tank").Attributes["value"].InnerText;
            }
      }

Hope this helps!
0
 
Ravi SinghSenior Software EngineerCommented:
Notice that to select the PetType nodes I used an xpath relative to the root element (DocumentElement):

XmlNodeList nodeListType = xmlDoc.DocumentElement.SelectNodes("DataType/PetOwned/PetType");

Your original way would have been:

XmlNodeList nodeListType = xmlDoc.SelectNodes("root/DataType/PetOwned/PetType");

0
Cloud Class® Course: CompTIA Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

 
NewMom2BrandonAuthor Commented:
I am still getting the first PetType value instead of what I really want.

here is my actual code for what I am working on

      private void LoadTCPXML()
      {
         // Load XML document
         XmlDocument xmlDoc = new XmlDocument();
         xmlDoc.Load(sConfigFile);

         // Loop through all errorlog messages,saving any messages that are found in an array.
         XmlNodeList nodeListType = xmlDoc.DocumentElement.SelectNodes("/Config/PI/Connection/Type");
         foreach (XmlNode xmlNodeType in nodeListType)
         {
           string sNameType = xmlNodeType.Attributes["value"].InnerText;

            //pull where the typenode is TCP/IP
            if (sNameType =="TCP/IP")
            {
               string sType = xmlNodeType.SelectSingleNode("/Config/PI/Connection/Type").Attributes["value"].InnerText;
               string sConnect = xmlNodeType.SelectSingleNode("/Config/PI/Connection/To").Attributes["value"].InnerText;
               string sIPAddress = xmlNodeType.SelectSingleNode("/Config/PI/Connection/IPAddress").Attributes["value"].InnerText;
               string sIPPort = xmlNodeType.SelectSingleNode("/Config/PI/Connection/IPPort").Attributes["value"].InnerText;

               listviewConfiguration.Items.Add(sType);
               listviewConfiguration.Items[0].SubItems.Add(sConnect);
               listviewConfiguration.Items[0].SubItems.Add(sIPAddress + ", " + sIPPort);
            }
         }
      }

So the code is looping through and finding the correct Type value "TCP/IP" however when I try to have it placed into the listview. It populates it with the first set only "Serial"

My actual XML File is like this

<PI>
   <Connection>
      <Type value="Serial" />
      <To value="Computer1" />
      <IPAddress value="10.10.10.11" />
      <IPPort value="9999" />
   </Connection>
 </PressInterface>
<PressInterface>
   <Connection>
      <Type value="TCP/IP" />
      <To value="Computer2" />
      <IPAddress value="10.10.10.10" />
      <IPPort value="9998" />
   </Connection>
 </PI>
0
 
Bob LearnedCommented:
Use this expression, and see if it helps:

XmlNodeList nodeListType = xmlDoc.DocumentElement.SelectNodes("//Type");

Bob
0
 
NewMom2BrandonAuthor Commented:
Nope still get the first one. "Serial"
0
 
Bob LearnedCommented:
I used this XML file:

<?xml version="1.0" ?>
<Data>
<DataType>
   <PetOwned>
      <PetType value = "Dog"/>
       <Age value = "1"/>
       <Fleas value = "None"/>
       <Tank Value = "none"/>
       <WaterType value = "none"/>
   </PetOwned>
</DataType>
<DataType>
   <PetOwned>
      <PetType value = "Fish" />
       <Age value = "unknown" />
       <Fleas value = "None" />
      <Tank Value = "10gal" />
      <WaterType value = "Fresh" />
   </PetOwned>
</DataType>
</Data>

And, this test code:

    XmlDocument doc = new XmlDocument();
    doc.Load(@"c:\temp\test.xml");

    foreach (XmlNode node in doc.SelectNodes("//PetType"))
    {
      Debug.WriteLine(node.Name );
    }

It wrote two entries in the Output window.

Bob
0
 
Bob LearnedCommented:
Do you have control over the format of that XML file?

Bob
0
 
NewMom2BrandonAuthor Commented:
I do but there are so many nodes that if I place them all in one line it would be really long.
0
 
Bob LearnedCommented:
Are you saying that you have more than 1 set of entries under the <Connection> node.  It looks like you only have 1 per connection.  Have you over simplified the XML file that you are showing us?

It would like this this to me:

<PI>
 <PressInterface>
   <Connection type="Serial" to="Computer1" ip="10.10.10.11" port="9999" />
 </PressInterface>
<PressInterface>
   <Connection type="TCP/IP" to="Computer2" ip="10.10.10.10" port="9998" />
 </PressInterface>
</PI>

That seems like significantly less text then having a node + attribute for each value.

Bob
0
 
NewMom2BrandonAuthor Commented:
here is the complete XML file (no modifications from me minus small value detail)

<?xml version="1.0"?>
<Config>
<PI>
   <Identifier value="1" />
   <DllName value="XXXX.dll" />
   <Interface value="T2" />
   <Connection>
      <Identifier value="1" />
      <Type value="Serial" />
      <To value="computer1" />
      <IPAddress value="localhost" />
      <IPPort value="6980" />
      <Parameters>
             <SerialPort value="XXXX1" />
       <BaudRate value="19200" />
       <Databits value="8" />
       <Parity value="None" />
       <Stopbits value="1" />
       <Timeout value="0" />
       <CTS value="0" />
       <DTR value="0" />
       <Device value="1" />
       <Node value="255" />
       <BusType value="PCI" />
      </Parameters>
   </Connection>
 </PI>
 <PI>
   <Identifier value="1" />
   <DllName value="XXXX.dll" />
   <Interface value="T1" />
   <Connection>
      <Identifier value="1" />
      <Type value="TCP/IP" />
      <To value="computer2" />
      <IPAddress value="10.10.10.10" />
      <IPPort value="6999" />
      <Parameters>
             <SerialPort value="XXXX1" />
       <BaudRate value="19200" />
       <Databits value="8" />
       <Parity value="None" />
       <Stopbits value="1" />
       <Timeout value="0" />
       <CTS value="0" />
       <DTR value="0" />
       <Device value="1" />
       <Node value="255" />
       <BusType value="PCI" />
      </Parameters>
    </Connection>
 </PI>
</Config>

So for a "Serial" I need everything under the parameters plus the Identifier, Type  and To under the connection
For "TCP/IP" I need the Identifier, Type  and To, IPAddress and IPPort under the connection
0
 
NewMom2BrandonAuthor Commented:
The SerialPort Value block is actually over. Sorry didn't line up right

<?xml version="1.0"?>
<Config>
<PI>
   <Identifier value="1" />
   <DllName value="XXXX.dll" />
   <Interface value="T2" />
   <Connection>
      <Identifier value="1" />
      <Type value="Serial" />
      <To value="computer1" />
      <IPAddress value="localhost" />
      <IPPort value="6980" />
      <Parameters>
          <SerialPort value="XXXX1" />
          <BaudRate value="19200" />
          <Databits value="8" />
          <Parity value="None" />
          <Stopbits value="1" />
          <Timeout value="0" />
          <CTS value="0" />
          <DTR value="0" />
          <Device value="1" />
          <Node value="255" />
          <BusType value="PCI" />
      </Parameters>
   </Connection>
 </PI>
 <PI>
   <Identifier value="1" />
   <DllName value="XXXX.dll" />
   <Interface value="T1" />
   <Connection>
      <Identifier value="1" />
      <Type value="TCP/IP" />
      <To value="computer2" />
      <IPAddress value="10.10.10.10" />
      <IPPort value="6999" />
      <Parameters>
          <SerialPort value="XXXX1" />
          <BaudRate value="19200" />
          <Databits value="8" />
          <Parity value="None" />
          <Stopbits value="1" />
          <Timeout value="0" />
          <CTS value="0" />
          <DTR value="0" />
          <Device value="1" />
          <Node value="255" />
          <BusType value="PCI" />
      </Parameters>
    </Connection>
 </PI>
</Config>
0
 
NewMom2BrandonAuthor Commented:
The to value can actually be to computer1 again
0
 
Bob LearnedCommented:
The inherent problem with XML files are they are significantly over-bloated with information.  There is an optimization step to include only as much information as necessary to get the job done.  It shouldn't matter how each entry is, but the amount of characters that need to be stored.  It comes in handy to think about things like this when you have to send XML over the wire, such as with a web service.

<?xml version="1.0"?>
<Config>
<PI id="1" dll="XXXX.dll" interface="T2">
   <Connection id="1" type="Serial" to="computer1" ip="localhost" port="6980">
      <Parameters>
            <SerialPort name="XXXX1" baud="19200" data="8" parity="None" stop="1" timeout="0" cts="0" dtr="0" device="1" node="255" bus="PCI" />
      </Parameters>
   </Connection>
 </PI>
</Config>

In my opinion, this XML structure is easier to read (since it is more compact), and you can still do XPath expressions using the attribute syntax that I showed you above.

Bob
0
 
NewMom2BrandonAuthor Commented:
OK so I switched the XML to look like this
<Config>
<PI Identifier ="1" DllName =" xxxx.dll" Interface=" T2">
   <Connection Identifier ="1" Type="Serial" To="computer1" IPAddress ="localhost" IPPort ="6980">
      <Parameters>
            < SerialPort ="COM1" BaudRate ="19200" Databits ="8" Parity ="None" Stopbits ="1" Timeout ="0" CTS ="0" DTR ="0" Device ="1" Node ="255" BusType ="PCI" />
      </Parameters>
   </Connection>
 </PI >
<PI Identifier ="1" DllName =" xxxx.dll" Interface=" T2">
   <Connection Identifier ="1" Type="TCP/IP" To="computer1" IPAddress ="10.10.10.10" IPPort ="6989">
      <Parameters>
            <SerialPort ="COM1" BaudRate ="19200" Databits ="8" Parity ="None" Stopbits ="1" Timeout ="0" CTS ="0" DTR ="0" Device ="1" Node ="255" BusType ="PCI" />
      </Parameters>
   </Connection>
 </PI >
<Config>

and I get this error (listed below) on this line
         foreach (XmlNode xmlNodeType in xmlDoc.SelectNodes("//Connection[@Type='TCP/IP']"))

An unhandled exception of type 'System.Xml.XmlException' occurred in system.xml.dll
Additional information: System error.
0
 
Bob LearnedCommented:
1) It is important that whenever you change XML text, that you test it with something like Internet Explorer.  

2) Here is the XML file that I came up with:

<?xml version="1.0" ?>
<Config>
<PI Identifier="1" DllName="xxxx.dll" Interface="T2">
   <Connection Identifier="1" Type="Serial" To="computer1" IPAddress="localhost" IPPort="6980">
      <Parameters>
            <Serial port="COM1" baud="19200" data="8" parity="None" stop="1" timeout="0" cts="0" dtr="0" device="1" node="255" bus="PCI" />
      </Parameters>
   </Connection>
 </PI>
<PI Identifier="1" DllName="xxxx.dll" Interface="T2">
   <Connection identifier="1" type="TCP/IP" to="computer1" ip="10.10.10.10" port="6989">
      <Parameters>
            <Serial port="COM1" baud="19200" data="8" parity="None" stop="1" timeout="0" cts="0" dtr="0" device="1" node="255" bus="PCI" />
      </Parameters>
   </Connection>
 </PI>
</Config>

3) You will notice some things:  
   a) No spaces in elements names
   b) Serial port=, and not SerialPort=
 
4) Keep the white space to a minimum.

5) Use short, lowercase names for attributes.

6) Use try...catch blocks to get real exceptions.

7) foreach (XmlNode xmlNodeType in xmlDoc.SelectNodes("//Connection[@type='TCP/IP']")) will now select one node.

Bob
0
 
NewMom2BrandonAuthor Commented:
I am sorry to ask one more quick question.

How do I change this line then                
string sType = xmlNodeType.SelectSingleNode("//Connection[@Type]").Attributes["value"].InnerText;

      foreach (XmlNode xmlNodeType in xmlDoc.SelectNodes("//Connection[@Type='TCP/IP']"))
         {
            string sType = xmlNodeType.SelectSingleNode("//Connection[@Type]").Attributes["value"].InnerText;
            string sConnect = xmlNodeType.SelectSingleNode("//Connection[@To]").Attributes["value"].InnerText;
            string sIPAddress = xmlNodeType.SelectSingleNode("//Connection[@IPAddress]").Attributes["value"].InnerText;
            string sIPPort = xmlNodeType.SelectSingleNode("//Connection[@IPPort]").Attributes["value"].InnerText;

               listviewConfiguration.Items.Add(sType);
               listviewConfiguration.Items[0].SubItems.Add(sConnect);
               listviewConfiguration.Items[0].SubItems.Add(sIPAddress + ", " + sIPPort);
          }
               

0
 
NewMom2BrandonAuthor Commented:
Got it thank you Bob!!
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.