Reputation: 5866
For the sake of simplicity, I will drastically reduce the complexity of my project and give a simple yet equally accurate example of what I'm struggling with. I have two XML files, we'll call them Read.xml
and Write.xml
. The goal is to have my project read the contents of Read.xml, parse the XML into a class, then rebuild it into Write.xml.
The way the XML gets generated into Read.xml is such that when an element has no value it uses the shorthand closing tag (<ElementName />
), and when it does have a value it uses the longhand closing tag (<ElementName>Element Value</ElementName>
). I have no control over the generation of the XML in Read.xml.
The below code works perfect for parsing the XML so long as it uses the longhand closing tag. However, if say ReportId
below was to have the shorthand closing tag, the code as it stands now would then read the next line (which for long hand closing tags would be the value of the XML element), but the next line is a white space element with the value "\n". This then adds a new line to the XML in Write.xml which makes the XML format oddly. Here's the code I use to read and parse the XML from Read.xml:
while(xmlReader.Read())
{
switch(xmlReader.NodeType)
{
case XmlNodeType.Element:
if(xmlReader.Name.Equals("ReportSummary") && xmlReader.IsStartElement())
{
currentReport = new Entities.Report();
}
else if(xmlReader.Name.Equals("ReportName"))
{
xmlReader.Read();
currentReport.ReportName = xmlReader.Value;
}
else if(xmlReader.Name.Equals("ReportId"))
{
xmlReader.Read();
currentReport.ReportId = xmlReader.Value;
}
break;
case XmlNodeType.EndElement: //Reached the end of the element.
if(xmlReader.Name.Equals("ReportSummary"))
{
if(currentReport!= null)
{
reportList.Add(currentReport);
currentReport = null;
}
}
break;
default:
break;
}
}
My question is, is there a proper way to handle shorthand closing tags versus long hand closing tags. Or, is there a better way to parse an XML file all together?
Thanks all in advance for any provided.
Upvotes: 2
Views: 2953
Reputation: 1985
I would use the SelectSingleNode function of the XmlDocument, it will be more efficient in parsing files.
http://msdn.microsoft.com/en-us/library/system.xml.xmlnode.selectsinglenode.aspx
If there's multiple nodes you can use the SelectNodes function.
http://msdn.microsoft.com/en-us/library/4bektfx9.aspx
As spender points out, you cal also parse it using XDocument/XElement also. This approach may be preferable if you're using at least framework 3.5
Upvotes: 0
Reputation: 3416
If you are inclined to go for a way which would be a bit less performant but much more managable,
I would suggest a solution that resembles the following:
XmlDocument xmlDoc = new XmlDocument();
List<Entities.Report> reports = new List<Entities.Report>();
xmlDoc.Load("Read.xml");
foreach (XmlNode reportNode in xmlDoc.SelectNodes("//ReportSummary"))
{
Entities.Report report = new Entities.Report();
report.ReportName = reportNode["ReportName"].InnerText;
report.ReportId = reportNode["ReportId"].InnerText;
reports.Add(report);
}
Much more readable, maintainable and a bit less performant.
Good luck!
Upvotes: 0
Reputation: 891
You could use LINQ to XML if possible...
Think it will make everything simpler for you.
http://msdn.microsoft.com/en-us/library/bb387098.aspx
Hope it helps...
Upvotes: 2
Reputation: 6361
You can use XmlReader.IsEmptyElement
to determine if the reader is at an empty element: http://msdn.microsoft.com/en-us/library/system.xml.xmlreader.isemptyelement.aspx
Upvotes: 4