Сложный синтаксический анализ XML в C#

Мне нужно проанализировать сложный и большой (более 100 МБ) XML-файл. К счастью, у меня есть определения схемы XML, но, к сожалению, я не могу использовать xsd2code для генерации автоматической десериализации XML, поскольку на верхнем уровне XML используются абстрактные типы сообщений. Структура файла XML выглядит следующим образом:

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

XSD определяет партию для содержания абстрактных животных, а не собак. Xsd2Code может создавать класс Dog с правильными атрибутами XML, но класс dog находится внутри другого файла xsd. Я пытался вставить все xsd вместе, но это не помогло исправить это.
Есть ли хороший способ, как Linq to XML или Xpath, перебирать элементы в Batch и создавать экземпляры Dog без необходимости синтаксического анализа Dog вручную?

1 ответ

Решение

Есть ли хороший способ, как Linq to XML или Xpath, перебирать элементы в Batch и создавать экземпляры Dog без необходимости синтаксического анализа Dog вручную?

Это зависит от того, что вы подразумеваете под "вручную". Я обнаружил, что полезно иметь шаблон, в котором каждый соответствующий класс имеет статический FromXElement фабричный метод (или конструктор, принимающий XElement) который извлекает соответствующие детали. С LINQ to XML это довольно просто, например,

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

Тогда вы можете использовать:

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

(Вы можете использовать Select(Dog.FromXElement) вместо этого - это зависит от того, какую версию C# вы используете.)

Для обработки всех животных в партии, вы, вероятно, захотите что-то вроде:

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();
Другие вопросы по тегам