Using XmlReader how do I read past an empty element? - c#

I have written an Xml file using XmlWriter.
Here is the code:
public void WriteXml(XmlWriter writer)
{
writer.WriteStartElement("element1");
writer.WriteAttributeString("attrs1", Attrs1);
writer.WriteAttributeString("attrs2", Attrs2);
if (!string.IsNullOrWhiteSpace("element2"))
{
writer.WriteStartElement("element2");
writer.WriteCData(Element2);
writer.WriteEndElement();
}
if (!string.IsNullOrWhiteSpace("element3"))
{
writer.WriteStartElement("element3");
writer.WriteCData(Element3);
writer.WriteEndElement();
}
Element4.WriteXml(writer);
Element5.WriteXml(writer);
writer.WriteEndElement();
}
As you can see, element4 calls a method named "WriteXml()". Here is that method:
public void WriteXml(XmlWriter writer)
{
if (m_PropertyValueList.Count > 0)
{
writer.WriteStartElement("element4");
foreach (var p in m_PropertyValueList)
{
if (p.CurrentValue != null)
{
writer.WriteStartElement("property");
writer.WriteAttributeString("name", p.PropertyName);
writer.WriteAttributeString("value", p.CurrentValue.ToString());
writer.WriteEndElement();
}
}
writer.WriteEndElement();
}
}
Notice that it checks for p.CurrentValue != null. If it is null then this element should be written as an empty element. In this case, p.CurrentValue is null so I do want an empty element. You will see in the Xml output below that is writing this element as . To me it looks like it is properly writing an empty element, PLEASE CORRECT ME IF I'M WRONG HERE.
The Xml file output looks like this:
<?xml version="1.0" encoding="UTF-8"?>
-<element>
-<element 1 attrs1="Some Info" attrs2="More Info">
-<element2>
+<![CDATA[]]>
</element2>
-<element3>
-<![CDATA[ ]]>
</element3>
<element4/>
</element1>
</element>
Then I create a method for reading the Xml file back in. This is where it breaks. It does just fine reading element, element1, element2 and element3. However, when it gets to element4, I start having issues. I will explain below.
Here is the XmlReader method:
public void ReadXml(XmlReader reader)
{
if (reader.IsStartElement("element1"))
{
//
// Get the values of all the <element1> attributes
//
Attrs1= reader.GetAttribute("attrs1");
Attrs2 = reader.GetAttribute("attrs2");
//
// Read past <element1>
//
reader.Read();
while (true)
{
if (reader.IsStartElement("element2"))
{
Description = reader.ReadElementContentAsString();
}
else if (reader.IsStartElement("element3"))
{
Source = reader.ReadElementContentAsString();
}
else if (reader.IsStartElement("element4")) && (!reader.IsEmptyElement))
{
Element4.ReadXml(reader);
}
else if ((reader.IsStartElement("element5")) && (!reader.IsEmptyElement))
{
Element5.ReadXml(reader);
}
else
{
reader.MoveToContent();
reader.ReadEndElement();
break;
}
}
}
else
{
throw new XmlException("Expected <element1> element was not present");
}
}
Notice that if element4 IsStartElement and if it's not an empty element it will call Element4.ReadXml(). Here is that method:
public void ReadXml(XmlReader reader)
{
if ((reader.IsStartElement("element4")) && (!reader.IsEmptyElement))
{
reader.Read();
while (reader.IsStartElement("property"))
{
string propertyName = reader.GetAttribute("name");
string propertyValue = reader.GetAttribute("value");
SetValue(propertyName, propertyValue);
reader.Read();
}
//
// Read </element4>
//
reader.MoveToContent();
reader.ReadEndElement();
}
}
But since element4 IS empty this method never gets called. So it will continue to the else{} statement and break when it gets to reader.ReadEndElement(); There error message I get is:
"Message: TestMethod myTestMethodName threw exception: System.Xml.XmlException 'Element' is an invalid XmlNodeType. Line 8, position 6."
So my questions are:
Is this because the element is empty? If so, how do I close or read past an empty element?
Where I am reading element4 if it's start element and if it's not empty....If I remove (!reader.IsEmptyElement) I get an infinite loop. It continues to call Element4.ReadXml(reader). Why is this?
How to I fix and continue past this so that I can read the rest of the elements.

Where I read my elements from my xml file I needed to add another else if condition to handle if the element is start element and if the element IS empty. I was only checking if it wasn't empty. So it didn't know how to handle it being empty. Then when those conditions were met I simply had to do reader.Read() to tell the app to read the element as is <element4/>.
Here is what it looks like:
else if (reader.IsStartElement("element4")) && (reader.IsEmptyElement))
{
reader.Read();
}

Related

Read an existing xml file and apply changes

I'm trying to learn how to read a XML file and do changes using C#.
Problem:
The XMLfile already exists. I would like to read the file and search for a specific element which has another element with an attribute:
<ELement>
<Element2 Attribute = "Value" />
</Element>
The problem is if this element "Element2" does not exist in the xml file I would like to create it under the same path.
Here is my actual code.
private void UpdateConfig(string configPath, string serverName)
{
string oldServername = null;
XElement config = XElement.Load(configPath);
CreateConfigBackup(configPath);
try
{
//which could be Null if the element does not exist in xml file.
oldServername = config.Element("WebGUI").Element("ServerIP").Attribute("Value").Value.ToString();
oldServername = oldServername.Split(':').FirstOrDefault();
// Config updaten
config.Element("WebGUI").Element("ServerIP").Attribute("Value").SetValue(serverName);
}
else
{
XElement ELM = new XElement("ServerIP");
ELM.SetAttributeValue("Value",serverName);
config.Element("WebGUI").Add(ELM);
}
}
catch (Exception ex)
{
if (oldServername == null)
{
MessageBox.Show(configPath+ "enthält nicht das Element Server in der Web-Konfigurationsdatei.");
}
}
SaveConfig(config, configPath);
}

Delete an element with specific node name from XML file using XDocument and XmlDocument class

I am trying to delete an element with specific node name. Using the following code but receive an error like "Name cannot begin with the '2' character, hexadecimal value 0x32." As I understand this method is not correct for the relevant xml format.
How can I delete Table with specific User_Name info. should delete specific table When I try to delete Administrator User
RemoveElement("Accounts.xml", "User", "Test1");
private static void RemoveElement(string xmlFile, string elementName, string elementAttribute)
{
XDocument xDocument = XDocument.Load(xmlFile);
foreach (var profileElement in xDocument.Descendants("Table").ToList())
{
if (profileElement.Attribute(elementAttribute).Value == elementName)
{
profileElement.Remove();
}
}
xDocument.Save(xmlFile);
}
Here is the Xml file;
`<?xml version="1.0" encoding="utf-8"?>
<Accounts>
<Table>
<User>Administrator</User>
<Domain>Localhost</Domain>
<Password>Test</Password>
<Account_Type>Windows</Account_Type>
</Table>
<Table>
<User>Test1</User>
<Domain>demo</Domain>
<Password>empty</Password>
<Account_Type>Domain</Account_Type>
</Table>
</Accounts>`
Original code snippet doesn't work because name of user is not an attribute of user but a value. Also, you can replace .Descendants("Table") with .Descendants(elementName) to avoid unnecessary if statement.
I think, the most elegant way to achieve needed functionality is to use Linq to Xml:
XDocument xDocument = XDocument.Load(xmlFile);
xDocument.Descendants(elementName)
.Where(e => e.Value == elementAttribute)
.ToList()
.ForEach(e => e.Remove());
xDocument.Save(xmlFile);
As for your second question: I believe that you remove first element in this line
listViewMevcutKullaniciListesi.Items.RemoveAt(listViewMevcutKullaniciListesi.SelectedIndices[0]);
When you call listViewMevcutKullaniciListesi.SelectedIndices[0] for the second time you obviously get an Exception.
Also, listViewMevcutKullaniciListesi.SelectedIndices[0].ToString() don't give you selected item but just it's number.
Yeah Found it how you can delete when you get info from texBox
xDoc.Load("Accounts.xml");
foreach (XmlNode node in xDoc.SelectNodes("Accounts/Table"))
{
if (node.SelectSingleNode("User").InnerText == textBox1.Text)
{
node.ParentNode.RemoveChild(node);
}
}
xDoc.Save("Accounts.xml");
But I Want to get info from listview. I receive an error When I try to use following code.
Error : InvalidArgument=Value of '0' is not valid for 'index'.\r\nParameter name: index
listViewMevcutKullaniciListesi.Items.RemoveAt(listViewMevcutKullaniciListesi.SelectedIndices[0]);
xDoc.Load("Accounts.xml");
foreach (XmlNode node in xDoc.SelectNodes("Accounts/Table"))
{
if (node.SelectSingleNode("User").InnerText == listViewMevcutKullaniciListesi.SelectedIndices[0].ToString())
{
node.ParentNode.RemoveChild(node);
}
}
xDoc.Save("Accounts.xml");
Here is the answer with XmlDocument class;
You are calling the method like
`RemoveElementWithXmlDocument("Accounts.xml", "Accounts/Table", "User", listViewMevcutKullaniciListesi.SelectedItems[0].Text);`
method;
private static void RemoveElementWithXmlDocument(string xmlFile, string nodeName, string elementName, string elementAttribute)
{
xDoc.Load(xmlFile);
try
{
foreach (XmlNode node in xDoc.SelectNodes(nodeName))
{
if (node.SelectSingleNode(elementName).InnerText == elementAttribute)
{
node.ParentNode.RemoveChild(node);
}
}
xDoc.Save(xmlFile);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
And also I wanna use XDocument class for same structure But I receive an exception like "Object reference not set to an instance of an object" in foreach loop when the ran profileElement.Remove(); line. If I comment out to this line never get the exception but I need this line for removing relevant node from xml. So, As I understand I missing something in XDocument. need your help
RemoveElementWithXDocument("Accounts.xml", "Table", "User", listViewMevcutKullaniciListesi.SelectedItems[0].Text);
method for XDocument
private static void RemoveElementWithXDocument(string xmlFile, string nodeName, string elementName, string elementAttribute)
{
XDocument xDocument = XDocument.Load(xmlFile);
try
{
foreach (XElement profileElement in xDocument.Descendants(nodeName))
{
if (profileElement.Element(elementName).Value == elementAttribute)
{
profileElement.Remove();
}
}
xDocument.Save(xmlFile);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

removing "#text" while parsing xml and displaying node value

I have a program to display the node name and value like this
public void findAllNodes(XmlNode node)
{
Console.Write("{0}:", node.Name);
Console.WriteLine(node.Value);
Console.WriteLine("{0}"," ");
foreach (XmlNode n in node.ChildNodes)
findAllNodes(n);
}
using this xml:
<application_data>
<applicant_data type="primary">
<first_name>VINNY</first_name>
<mi></mi>
<last_name>SSILVERLACE</last_name>
<ssn>666279999</ssn>
<dob>1973-06-27</dob>
<address type="current">
<po_box_no></po_box_no>
<roural_route></roural_route>
<street_no>7690</street_no>
<street_name>KETTLEDRUMS</street_name>
<apt_no></apt_no>
<city>MILILANI TOWN</city>
<state>HI</state>
<zip_code>96789</zip_code>
</address>
</applicant_data>
</application_data>
But for this code, while displaying the node values, it diplays like this
#text:("node value").
Can you suggest some way to delete "#text" from the node value?
It has nothing to do with your xml, but with your node.Name statement.
If you look here you will see that, node.Name will print #text for text nodes every time. I'm not familiar enough with XmlNode to tell you how to get the tag name as you appear to be wanting. You could try Linq-To-Xml as someone commented.
Example:
public void findAllNodes(XElement node)
{
Console.Write("{0}:", node.Name.ToString());
Console.WriteLine(node.Value);
Console.WriteLine("{0}"," ");
foreach (XElement n in node.Elements())
findAllNodes(n);
}
findAllNodes(XElement.Load(file));
private static void RecurseXmlDocument(XmlNode root)
{
if (root is XmlElement)
{
Console.Write("\n" + root.Name + ": ");
if (root.HasChildNodes) RecurseXmlDocument(root.FirstChild);
if (root.NextSibling != null) RecurseXmlDocument(root.NextSibling);
}
else if (root is XmlText)
{
Console.Write(((XmlText)root).Value);
}
else if (root is XmlComment)
{
Console.Write(root.Value);
if (root.HasChildNodes) RecurseXmlDocument(root.FirstChild);
if (root.NextSibling != null) RecurseXmlDocument(root.NextSibling);
}
}
I modified this according to your needs and it works just fine now. You're going to have to call it like this:
public static void Main()
{
XmlDocument document = new XmlDocument();
document.Load("File.xml");
RecurseXmlDocument((XmlNode)document.DocumentElement);
Console.ReadKey();
}

how to read & write xml file in C# not rely on the tag name?

Thank you very much for reading my question.
the bottom is the sample of my xml file.please refer that.
i did some xml files before, but by "CMarkXml". "IntoElement, OutofElement", is very clear.
but when C#...i was lost..
1: how to read & write my xml file without using the tag name. i see some articles about operation on xml file by c#, but all assumed that known the tag name.
2: if without tag name, it is very difficult or not recommend. then how to read & write my xml file by XmlDocument? (sorry, but no Ling please, i am very faint with that...).
3: my idear is, for the xml file, get out some section, we still could parse the section by xmldocument.
4: for the write/modify the xml file, of course, should contain delete some section, delete some "leaf", change the attributes...
Thank you very much for reading the long question, and any help i will very appreciate. If you have a good sample code but not continent paste them here, could you send it to "erlvde#gmail.com"?
<root>
<a>i belong to a</a>
<b>
<bb>
<bb>1</bb>
<bb>2</bb>
<bb>3</bb>
<bb>4</bb>
<bb>5</bb>
</bb>
<bb>
<bb>1</bb>
<bb>2</bb>
<bb>3</bb>
<bb>4</bb>
<bb>5</bb>
<bb>
....(other <bb>)
</b>
</root>
Read your xml into XmlDocument:
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml("XML HERE");
Access child nodes:
xmlDocument.ChildNodes[1]
But it's also true that it's very error prone
You can also check if you have child nodes at all:
xmlDocument.HasChildNodes
And get number of child nodes:
xmlDocument.ChildNodes.Count
It looks to me like your elements names contain identifiers. If that is the case, and you have control over the XML schema, I would highly recommend changing your XML to contain elements and/or attributes indicating your identifiers and then use the built in XmlSerializer class for serializing to and from XML. It has many modifiers available, such as XmlElement and XmlAttribute among many others, for formatting the output.
Here is a tutorial to get you started.
If possible, change your XML to something like following which would make it far simpler to manipulate...again if changing the schema is a possibility.
<root>
<a>i belong to a</a>
<b>
<bb id="1">
<bb>1</bb>
<bb>2</bb>
<bb>3</bb>
<bb>4</bb>
<bb>5</bb>
</bb>
<bb id="2">
<bb>1</bb>
<bb>2</bb>
<bb>3</bb>
<bb>4</bb>
<bb>5</bb>
<bb>
</b>
</root>
Edit this edit reflects the changes you made to your XML
Here is a simple console application which will serialize an object to an XML file and then rehydrate it.
Expected XML
<?xml version="1.0" encoding="utf-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<a>i belong to a</a>
<b>
<bb>
<bb>1</bb>
<bb>2</bb>
<bb>3</bb>
<bb>4</bb>
<bb>5</bb>
</bb>
<bb>
<bb>1</bb>
<bb>2</bb>
<bb>3</bb>
<bb>4</bb>
<bb>5</bb>
</bb>
</b>
</root>
Simple Console Application Demonstration
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var items = new root
{
a = "i belong to a",
b = new List<bb>
{
new bb
{
bbClassProperty = new List<int>
{
1,
2,
3,
4,
5
}
},
new bb
{
bbClassProperty= new List<int>
{
1,
2,
3,
4,
5
}
}
}
};
XmlSerializer serializer = new XmlSerializer(typeof(root));
using (var textWriter = new StreamWriter(#"C:\root.xml"))
{
serializer.Serialize(textWriter, items);
textWriter.Close();
}
using (var stream = new StreamReader(#"C:\root.xml"))
{
var yourObject = serializer.Deserialize(stream);
}
Console.Read();
}
}
#region [Classes]
public class root
{
public string a { get; set; }
public List<bb> b { get; set; }
}
public class bb
{
[XmlElement("bb")]
public List<int> bbClassProperty { get; set; }
}
#endregion
}
Look into the ChildNodes (and similar) properties and methods on your XmlElement object. These will let you iterate over the children of a node and you can then ask that node for its name.
If you have a XmlNode object, you can use XMLNode.FirstChild to get the child, if it has any. You can also use XMLNode.NextSibling to get the next Node of the same parent node.
Why can't you use the names of the nodes? It's the easiest and most common way. Especially if you use XPath or similar.
XPath is also the answer to your second question.
U can use the class XML reader, a simple example is given here.
using System;
using System.Xml;
class Program
{
static void Main()
{
// Create an XML reader for this file.
using (XmlReader reader = XmlReader.Create("perls.xml"))
{
while (reader.Read())
{
// Only detect start elements.
if (reader.IsStartElement())
{
// Get element name and switch on it.
switch (reader.Name)
{
case "perls":
// Detect this element.
Console.WriteLine("Start <perls> element.");
break;
case "article":
// Detect this article element.
Console.WriteLine("Start <article> element.");
// Search for the attribute name on this current node.
string attribute = reader["name"];
if (attribute != null)
{
Console.WriteLine(" Has attribute name: " + attribute);
}
// Next read will contain text.
if (reader.Read())
{
Console.WriteLine(" Text node: " + reader.Value.Trim());
}
break;
}
}
}
}
}
}
The input file text is:
<?xml version="1.0" encoding="utf-8" ?>
<perls>
<article name="backgroundworker">
Example text.
</article>
<article name="threadpool">
More text.
</article>
<article></article>
<article>Final text.</article>
</perls>
Output
Start element.
Start element.
Has attribute name: backgroundworker
Text node: Example text.
Start element.
Has attribute name: threadpool
Text node: More text.
Start element.
Text node:
Start element.
Text node: Final text.enter code here
You can use the following code to if the file does not contain the headers, in the example above.
XmlReaderSettings settings = new XmlReaderSettings();
settings.ConformanceLevel = ConformanceLevel.Fragment;
reader = XmlReader.Create(filePath, settings)
Would something like this help?
void Iterate(XmlNode parent) {
//do something with
//parent.Name
//parent.Value
//parent.Attributes
foreach(XmlNode child in parent.ChildNodes) {
Iterate(child);
}
}
XmlDocument document = new XmlDocument();
document.Load(filename);
XmlNode parent = document.DocumentElement;
Iterate(parent);
You could also store it like that (sorry for any syntactical error, didn't run it)
public class Document {
public Element DocumentElement { set; get; }
private void Load(string fileName) {
XmlDocument document = new XmlDocument();
document.Load(fileName);
DocumentElement = new Element(this, null);
DocumentElement.Load(document.DocumentElement);
}
}
public class Element {
public string Name { set; get; }
public string Value { set; get; }
//other attributes
private Document document = null;
private Element parent = null;
public Element Parent { get { return parent; } }
public List<Element> Children { set; get; }
private int order = 0;
public Element(Document document, Element parent) {
Name = "";
Value = "";
Children = new List<LayoutElement>();
this.document = document;
this.parent = parent;
order = parent != null ? parent.Children.Count + 1 : 1;
}
private Element GetSibling(bool left) {
if(parent == null) return null;
int add = left ? -1 : +1;
Element sibling = parent.Children.Find(child => child.order == order + add);
return sibling;
}
public Element GetLeftSibling() {
return GetSibling(true);
}
public Element GetRightSibling() {
return GetSibling(false);
}
public void Load(XmlNode node) {
Name = node.Name;
Value = node.Value;
//other attributes
foreach(XmlNode nodeChild in node.Children) {
Element child = new Element(document, this);
child.Load(nodeChild);
Children.Add(child);
}
}
}
Document document = new Document();
document.Load(fileName);
For changing/deleting right now you could iterate the tree and find elements by name, but since name is not unique, you would affect many elements at once. You could add an unique id in every tag like
<bb id="bb1"/>
Then read it in Load function like
id = ((XmlElement)node).GetAttribute("id");
and use this id to iterate through the tree. Sorry I don't have time right now to provide something more detailed.

XmlReader ReadStartElement causes XmlException

I'm writing a file reader using the XmlReader in a Silverlight project. However, I'm getting some errors (specifically around the XmlReader.ReadStartElement method) and it's causing me to believe that I've misunderstood how to use it somewhere along the way.
Basically, here is a sample of the format of the Xml I am using:
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<root>
<EmptyElement />
<NonEmptyElement Name="NonEmptyElement">
<SubElement Name="SubElement" />
</NonEmptyElement>
</root>
And here is a sample of some code used in the same way as how I am using it:
public void ReadData(XmlReader reader)
{
// Move to root element
reader.ReadStartElement("root");
// Move to the empty element
reader.ReadStartElement("EmptyElement");
// Read any children
while(reader.ReadToNextSibling("SubEmptyElement"))
{
// ...
}
// Read the end of the empty element
reader.ReadEndElement();
// Move to the non empty element
reader.ReadStartElement("NonEmptyElement"); // NOTE: This is where I get the error.
// ...
}
So, essentially, I am simply trying to read each element and any contained children. The error I get at the highlighted point is as follows:
Error Description
[Xml_InvalidNodeType]
Arguments: None,10,8
Debugging resource strings are unavailable. Often the key and arguments provide sufficient information to diagnose the problem. See http://go.microsoft.com/fwlink/?linkid=106663&Version=4.0.51204.0&File=System.Xml.dll&Key=Xml_InvalidNodeType
Error Stack Trace
at System.Xml.XmlReader.ReadStartElement(String name)
at ----------------
Any advice or direction on this would be greatly appreciated.
EDIT
Since this reader needs to be fairly generic, it can be assumed that the Xml may contain elements that are children of the EmptyElement. As such, the attempt at reading any SubEmptyElements should be valid.
<SubElement/> is not a sibling of <EmptyElement>, so <NonEmptyElement> is going to get skipped entirely, and your call to ReadEndElement() will read the end element </root>. When you try to subsequently read "NonEmptyElement", there are no elements left, and you'll get an XmlException: {"'None' is an invalid XmlNodeType. Line 8, position 1."}
Note also that since <EmptyElement/> is empty, when you ReadStartElement("EmptyElement"), you'll read the whole element, and you won't need to use ReadEndElement().
I'd also recommend that you configure your reader settings to IgnoreWhitespace (if you're not already doing so), to avoid any complications introduced by reading (insignificant) whitespace text nodes when you aren't expecting them.
Try moving the Read of NonEmptyElement up:
public static void ReadData(XmlReader reader)
{
reader.ReadStartElement("root");
reader.ReadStartElement("EmptyElement");
reader.ReadStartElement("NonEmptyElement");
while (reader.ReadToNextSibling("SubEmptyElement"))
{
// ...
}
reader.ReadEndElement(/* NonEmptyElement */);
reader.ReadEndElement(/* root */);
// ...
}
If you just want to skip anything in <EmptyElement>, regardless of whether or not its actually empty, use ReadToFollowing:
public static void ReadData(XmlReader reader)
{
reader.ReadStartElement("root");
reader.ReadToFollowing("NonEmptyElement");
Console.WriteLine(reader.GetAttribute("Name"));
reader.ReadStartElement("NonEmptyElement");
Console.WriteLine(reader.GetAttribute("Name"));
while (reader.ReadToNextSibling("SubEmptyElement"))
{
// ...
}
reader.ReadEndElement(/* NonEmptyElement */);
reader.ReadEndElement(/* root */);
// ...
}
Update: Here's a fuller example with a clearer data model. Maybe this is closer to what you're asking for.
XMLFile1.xml:
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<root>
<Person Type="Homeless"/>
<Person Type="Developer">
<Home Type="Apartment" />
</Person>
<Person Type="Banker">
<Home Type="Apartment"/>
<Home Type="Detached"/>
<Home Type="Mansion">
<PoolHouse/>
</Home>
</Person>
</root>
Program.cs:
using System;
using System.Xml;
namespace ConsoleApplication6
{
internal class Program
{
public static void ReadData(XmlReader reader)
{
reader.ReadStartElement("root");
while (reader.IsStartElement("Person"))
{
ReadPerson(reader);
}
reader.ReadEndElement( /* root */);
}
public static void ReadPerson(XmlReader reader)
{
Console.WriteLine(reader.GetAttribute("Type"));
bool isEmpty = reader.IsEmptyElement;
reader.ReadStartElement("Person");
while (reader.IsStartElement("Home"))
{
ReadHome(reader);
}
if (!isEmpty)
{
reader.ReadEndElement( /* Person */);
}
}
public static void ReadHome(XmlReader reader)
{
Console.WriteLine("\t" + reader.GetAttribute("Type"));
bool isEmpty = reader.IsEmptyElement;
reader.ReadStartElement("Home");
if (!isEmpty)
{
reader.Skip();
reader.ReadEndElement( /* Home */);
}
}
private static void Main(string[] args)
{
var settings = new XmlReaderSettings { IgnoreWhitespace = true };
using (var xr = XmlReader.Create("XMLFile1.xml", settings))
{
ReadData(xr);
}
Console.ReadKey();
}
}
}

Categories