Confused on reading attributes of an XML element.

  • Thread starter Thread starter sherifffruitfly
  • Start date Start date
S

sherifffruitfly

Hi,

I have an xml file with structured like this:

<?xml version="1.0" encoding="UTF-8"?>
<Soldiers>
<Soldier name="Billy Smith" rank="Private" serial="34" />

(a bunch more soldiers)

</Soldiers>

In my program, I have a struct:

public struct soldierStruct
{
public string name;
public string rank;
public string serial;
}

I would like to make a loop that reads however many XML-soldiers there
are into an ArrayList of struct-soldiers. I can come up with the
framework for it, it's just the reading attributes part that I don't
understand how to do. Can anyone help?

Thanks for any suggestions,

cdj

===============
Framework:

public ArrayList GetSoldiers()
{
ArrayList soldiers= new ArrayList();
soldiers.clear();

XmlTextReader reader = new XmlTextReader(path + filename);
reader.Read();
while (reader.Read())
{
soldierStruct sol;

//Stuff here to make sure the reader is
where
//it's supposed to be?????

sol.name = ????? //Need attribute help
somewhere around here
sol.rank = ??????
sol.serial = ??????

soldiers.add(sol)
}

return soldiers;
}
 
sherifffruitfly said:
Hi,

I have an xml file with structured like this:

<?xml version="1.0" encoding="UTF-8"?>
<Soldiers>
<Soldier name="Billy Smith" rank="Private" serial="34" />

(a bunch more soldiers)

</Soldiers>

In my program, I have a struct:

public struct soldierStruct
{
public string name;
public string rank;
public string serial;
}

I would like to make a loop that reads however many XML-soldiers there
are into an ArrayList of struct-soldiers. I can come up with the
framework for it, it's just the reading attributes part that I don't
understand how to do. Can anyone help?

Thanks for any suggestions,

cdj

===============
Framework:

public ArrayList GetSoldiers()
{
ArrayList soldiers= new ArrayList();
soldiers.clear();

XmlTextReader reader = new XmlTextReader(path + filename);
reader.Read();
while (reader.Read())
{
soldierStruct sol;

//Stuff here to make sure the reader is
where
//it's supposed to be?????

sol.name = ????? //Need attribute help
somewhere around here
sol.rank = ??????
sol.serial = ??????

soldiers.add(sol)
}

return soldiers;
}

I know this may not help you, but hey, it just might be of some use to you.
You can try creating a typed dataset and using it's methods to save to an
xml string/file or load from an xml string/file. All the reading/parsing of
the xml file is internal to the dataset and you get your "name", "rank",
"serial", etc properties because it is a typed dataset.

Just thought you may like to try a slightly alternate but easier approach :)

HTH,
Mythran
 
XmlReader can be hard. Once you know your node is a Soldier (possibly using
ReadToFollowing) you
should be able to use e.g. sol.rank = reader.GetAttribute("rank");

I don't know if you are coming from a C++ background, but "class" may be
more appropriate than "struct" here, else you could end up with a lot of
problems; I recommend refreshing "value type" versus "reference type".

Additionally, note that this may fit the XmlSerializer very nicely - making
a few changes to fit standard C# naming (although I haven't switched to
properties), you may be able to just use:

[Serializable]
public class Soldier
{
[XmlAttribute("name")]
public string Name; // better as a property
[XmlAttribute("rank")]
public string Rank;
[XmlAttribute("serial")]
public string Serial;
}

And then deserialize the xml as an array of soldiers. Might need a little
tweaking, and I'm not going to bother tilling in blanks unless you are
genuinely interested in this option - but would also save you having to do
much to write them back as xml.

Marc
 
Each call to Read() will advance the reader to the next node. So you
wan to call Read and then test if the node you found is a soldier node
and if so then you call MoveToFirstAttribute to get the first
attribute, and then MoveToNextAttribute for the following attributes.

Here's a working example. HOWEVER, I would strongly suggest using
XmlSerializer instead of custom XML code. XmlSerializer is easier to
use and writes more efficient code than what I'm showing here.

HTH,

Sam


------------------------------------------------------------
We're hiring! B-Line Medical is seeking Mid/Sr. .NET
Developers for exciting positions in medical product
development in MD/DC. Work with a variety of technologies
in a relaxed team environment. See ads on Dice.com.



using System;
using System.Collections;
using System.IO;
using System.Xml;

namespace CommandTest
{
public class XmlTextReaderAttributes
{
public static void Test()
{
ArrayList soldiers = GetSoldiers();
foreach(soldierStruct sol in soldiers)
{
Console.WriteLine(sol);
}
}

public static ArrayList GetSoldiers()
{
ArrayList soldiers = new ArrayList();
soldiers.Clear();

StringReader text = new StringReader(
@"<?xml version='1.0' encoding='UTF-8'?>
<Soldiers>
<Soldier name='Billy Smith' rank='Private' serial='34' />
<Soldier name='John Jones' rank='General' serial='25' />
</Soldiers>");

XmlTextReader reader = new XmlTextReader(text);
reader.Read();
while (reader.Read())
{
if (reader.Name == "Soldier" &&
reader.MoveToFirstAttribute())
{
soldierStruct sol = new soldierStruct();

do
{
switch (reader.Name)
{
case "name":
sol.name = reader.Value;
break;

case "rank":
sol.rank = reader.Value;
break;

case "serial":
sol.serial = reader.Value;
break;
}
} while (reader.MoveToNextAttribute());

soldiers.Add(sol);
}
}

return soldiers;
}

public struct soldierStruct
{
public string name;
public string rank;
public string serial;

public override string ToString()
{
return rank + " " + name + ", " + serial;
}

}
}
}
 
sherifffruitfly said:
Hi,

I have an xml file with structured like this:

<?xml version="1.0" encoding="UTF-8"?>
<Soldiers>
<Soldier name="Billy Smith" rank="Private" serial="34" />

(a bunch more soldiers)

</Soldiers>

In my program, I have a struct:

public struct soldierStruct
{
public string name;
public string rank;
public string serial;
}

I would like to make a loop that reads however many XML-soldiers there
are into an ArrayList of struct-soldiers. I can come up with the
framework for it, it's just the reading attributes part that I don't
understand how to do. Can anyone help?

Thanks for any suggestions,

cdj

===============
Framework:

public ArrayList GetSoldiers()
{
ArrayList soldiers= new ArrayList();
soldiers.clear();

XmlTextReader reader = new XmlTextReader(path + filename);
reader.Read();
while (reader.Read())
{
soldierStruct sol;

//Stuff here to make sure the reader is
where
//it's supposed to be?????

sol.name = ????? //Need attribute help
somewhere around here
sol.rank = ??????
sol.serial = ??????

soldiers.add(sol)
}

return soldiers;
}

XmlDocument xDoc = new XmlDocument();
xDoc.Load(reader);
XmlNodeList nodes = xDoc.SelectNodes("Soldiers/Soldier");
foreach (XmlNode node in nodes)
{
sol.name = node.Attributes["name"].InnerText;
sol.rank = node.Attributes["rank"].InnerText;
sol.serial = node.Attributes["serial"].InnerText;
}
 
Back
Top