So I am reading a xml file with unknown length and reading each element into a list structure. Right now once I get to the end of the file I continue reading, this causes an exception. Right now I just catch this exception and continue with my life but is there a cleaner way to do this?
try
{
while(!textReader.EOF)
{
// Used to store info from each command as they are read from the xml file
ATAPassThroughCommands command = new ATAPassThroughCommands ();
// the following is just commands being read and their contents being saved
XmlNodeType node = textReader.NodeType;
textReader.ReadStartElement( "Command" );
node = textReader.NodeType;
name = textReader.ReadElementString( "Name" );
node = textReader.NodeType;
CommandListContext.Add(name);
command.m_Name = name;
command.m_CMD = Convert .ToByte(textReader.ReadElementString("CMD" ),16);
command.m_Feature = Convert .ToByte(textReader.ReadElementString("Feature" ),16);
textReader.ReadEndElement(); //</command>
m_ATACommands.Add(command);
}
}
catch ( Exception ex)
{
//</ATAPassThrough> TODO: this is an ugly fix come up with something better later
textReader.ReadEndElement();
//cUtils.DisplayError(ex.Message);
}
xml file:
<ATAPassThrough>
<Command>
<Name>Smart</Name>
<CMD>B0</CMD>
<Feature>D0</Feature>
</Command>
<Command>
<Name>Identify</Name>
<CMD>B1</CMD>
<Feature>D0</Feature>
</Command>
.
.
.
.
</ATAPassThrough>
Reading XML Files To read an XML file using ElementTree, firstly, we import the ElementTree class found inside xml library, under the name ET (common convension). Then passed the filename of the xml file to the ElementTree.parse () method, to enable parsing of our xml file. Then got the root (parent tag) of our xml file using getroot ().
Therefore, when you read the file and encounter that special end-of-file mark, the system would know there is no input data after this mark. If you try to read passing this mark, it is considered as an error. If you prepare the input using keyboard, hiting the Ctrl-D key would generate the end-of-mark under UNIX.
So while Notepad might be useful for quickly checking out an XML file, you’re much better off with a more advanced tool like Notepad++, which highlights syntax and formats the file the way it’s intended. Here is the same XML file opened in Notepad++: RELATED: How To Replace Notepad with Another Text Editor in Windows.
You can open and edit them with any text editor, view them with any web browser, or use a website that lets you view, edit, and even convert them to other formats. Since XML files are really just text files, you can open them in any text editor.
I would recomend using XDocument for reading XML data... for instance in your case since you already have a TextReader for your XML you can just pass that into the XDocument.Load method... your entire function above looks like this..
var doc = XDocument.Load(textReader);
foreach (var commandXml in doc.Descendants("Command"))
{
var command = new ATAPassThroughCommands();
var name = commandXml.Descendants("Name").Single().Value;
// I'm not sure what this does but it looks important...
CommandListContext.Add(name);
command.m_Name = name;
command.m_CMD =
Convert.ToByte(commandXml.Descendants("CMD").Single().Value, 16);
command.m_Feature =
Convert.ToByte(commandXml.Descendants("Feature").Single().Value, 16);
m_ATACommands.Add(command);
}
Significantly easier. Let the framework do the heavy lifting for you.
Probably the easiest way if you have normal and consistant XML is to use the XML Serializer.
First Create Objects that match your XML
[Serializable()]
public class Command
{
[System.Xml.Serialization.XmlElement("Name")]
public string Name { get; set; }
[System.Xml.Serialization.XmlElement("CMD")]
public string Cmd { get; set; }
[System.Xml.Serialization.XmlElement("Feature")]
public string Feature { get; set; }
}
[Serializable()]
[System.Xml.Serialization.XmlRoot("ATAPassthrough")]
public class CommandCollection
{
[XmlArrayItem("Command", typeof(Command))]
public Command[] Command { get; set; }
}
The a method to return the CommandCollection
public class CommandSerializer
{
public commands Deserialize(string path)
{
CommandCollection commands = null;
XmlSerializer serializer = new XmlSerializer(typeof(CommandCollection ));
StreamReader reader = new StreamReader(path);
reader.ReadToEnd();
commands = (CommandCollection)serializer.Deserialize(reader);
reader.Close();
return commands ;
}
}
Not sure if this is exactly correct, I don't have the means to test it, but is should be really close.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With