Question

I need to parse a complex and large (100 MB+) XML file. Fortunately I have XML Schema definitions, but unfortunately I can not use xsd2code to generate an automatic XML deserialization, because there are abstract message types used on the top level of the XML. The structure of the XML file is like this:

<Head>  
    <Batch>   
        <Dog></Dog>   
        <Dog></Dog>  
    </Batch>  
</Head>

The xsd defines batch to contain abstract animals, not dog. Xsd2Code can create the Dog class with the right XML attributes, but the dog class is inside another xsd file. I tried to paste all xsd together, but this did not help to fix this.
Is there a good way like Linq to XML or Xpath to loop over the elements in Batch and create Dog instances without needing to parse Dog manually?

Was it helpful?

Solution

Is there a good way like Linq to XML or Xpath to loop over the elements in Batch and create Dog instances without needing to parse Dog manually?

It depends on what you mean by "manually". I've found it's useful to have a pattern where each relevant class has a static FromXElement factory method (or a constructor taking an XElement) which extracts the relevant details. With LINQ to XML that's pretty straightforward, e.g.

public static Dog FromXElement(XElement element)
{
    // Or whatever...
    return new Dog((string) element.Element("Name"),
                   (double) element.Element("Weight"));
}

Then you can use:

List<Dog> dogs = batch.Elements("Dog")
                      .Select(x => Dog.FromXElement(x))
                      .ToList();

(You may be able to use Select(Dog.FromXElement) instead - it depends on which version of C# you're using.)

To process all the animals in a batch, you'd probably want something like:

private static readonly Dictionary<string, Func<XElement, Animal>> Factories =
    new Dictionary<string, Func<XElement, Animal>>
{
    { "Dog", Dog.FromXElement },
    { "Cat", Cat.FromXElement },
    // etc
}
...
List<Animal> animals = batch.Elements()
                            .Select(x => Factories[x.Name.LocalName](x))
                            .ToList();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top