How to iterate through an XDocument, getting compl

2019-06-24 19:11发布

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?

2条回答
该账号已被封号
2楼-- · 2019-06-24 19:17

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 the Person 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 the Skills 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.

查看更多
混吃等死
3楼-- · 2019-06-24 19:31

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 out XElement.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.)

查看更多
登录 后发表回答