I have an XmlDocument
which I can traverse with XmlNode
or convert it to a XDocument
and traverse it via LINQ.
<Dataset>
<Person>
<PayrollNumber>1234567</PayrollNumber>
<Surname>Smith-Rodrigez</Surname>
<Name>John-Jaime-Winston Junior</Name>
<Skills>
<Skill>ICP</Skill>
<Skill>R</Skill>
</Skills>
<HomePhone>08 8888 8888</HomePhone>
<MobilePhone>041 888 999</MobilePhone>
<Email>curly@stooge.com</Email>
</Person>
<Person>
<PayrollNumber>12342567</PayrollNumber>
<Surname>Smith-Rodrigez</Surname>
<Name>Steve</Name>
<Skills>
<Skill>Resus</Skill>
<Skill>Air</Skill>
</Skills>
<HomePhone>08 8888 8888</HomePhone>
<MobilePhone>041 888 999</MobilePhone>
<Email>curly@stooge.com</Email>
</Person>
</Dataset>
Question 1
I want to convert the Person records/nodes in the XML to a business entity object (POCO).
Therefore I have to iterate through a Person node at a time, and then parse the individual values. This last bit is interesting in itself, but first I have to get the actual Person records. The problem I have is that if I select by individual nodes (using say XmlList
in XmlDocoment
).
I end up aggregating all fields by name. I am concerned to do this in case one of the person nodes is incomplete, or even missing and then I won't know which is missing when I pass through and aggregate the fields in to business objects. I will try and validate - see question 2.
I realize this can be done through reflection but I am interested.
I tried iterating through by Person object:
Option 1:
foreach (XObject o in xDoc.Descendants("Person"))
{
Console.WriteLine("Name" + o);
// [...]
}
This gets me 2 person records (correct) each a stringified complete XML doc - formatted as an XML document. Just a subset of the above XML document.
But how to split up the record now into separate nodes or fields - preferably as painless as possible?
Option 2:
foreach (XElement element in xDoc.Descendants("Person"))
{
// [...]
}
This gets me the XML nodes - values only - for each Person all in one string, e.g.
1234567Smith-RodrigezJohn-Jaime-Winston JuniorLevel 5, City Central Tower 2, 121 King William StNorth Adelaide 5000ICPR08 8888 8888041 888 999111111curly@stooge.comE
Again, not much use.
Question 2
I can validate an XDocument
quite easily, there are some good examples on MSDN, but I'd like to know how can I flag a wrong record. Ideally, I'd like to be able to filter the good records out to a new XDocument
on the fly leaving the old ones behind. Is this possible?
Why not using XML deserialization?
There are two ways to do that.
The first one is to modify the business object
Person
to match the given XML, by adding appropriate attributes to thePerson
class and its properties. The XML is quite simple, so probably you would just have to change the names if there is no 1:1 match between object properties and XML nodes. For example, you have to specify[XmlArray("Skills")]
and[XmlArrayItem("Skill)]
for theSkills
collection.The second one is to transform the given XML to the one which matches the default serialization of your
Person
object, then to deserialize.The second solution will also give you the possibility to filter "bad" records very easily.
The problem is that you're just printing out the elements as strings. You need to write code to convert an
XElement
of<Person>
into your business object. Admittedly I'd expect the full XML to be written out instead - are you sure you're not printing outXElement.Value
(which concatenates all the descendant text nodes)?(I'm not sure of the answer to your second question - I suggest you ask it as a separate question here, so that we don't get a mixture of answers in one page.)