Разбор файла XML -опции? - PullRequest
       12

Разбор файла XML -опции?

1 голос
/ 27 июля 2010

Я занимаюсь разработкой системы для получения вложений XML из электронных писем через веб-службы Exchange и ввода их в базу данных с помощью созданного мной пользовательского объекта DAL.

Мне удалось извлечь XML-вложение и подготовить его в виде потока ... они задаются вопросом, как проанализировать этот поток и заполнить объект DAL.

Я могу создать XMLTextReader и перебирать каждый элемент. Я не вижу никаких проблем с этим, кроме того, что я подозреваю, что есть намного более гладкий путь. Читатель, похоже, рассматривает открывающий тег, содержимое тега и закрывающий тег как разные элементы (используя reader.NodeType). Я ожидал, что myValue будет считаться одним элементом, а не тремя. Как я уже сказал, я могу обойти эту проблему, но я уверен, что должен быть лучший способ.

Мне пришла в голову идея использовать XML Serializer (совершенно новый для меня), но быстрый взгляд показал, что они не могут обрабатывать ArrayLists и List (я использую List).

Опять же, я новичок в LINQ, но LINQ-to-XML также упоминался, но примеры, которые я видел, кажутся довольно сложными, хотя это просто мое отсутствие знакомства.

По сути, я не хочу использовать систему с кластерами, но я не хочу использовать какую-либо сложную технику с кривой обучения, просто потому, что она «крутая».

Какой самый простой и эффективный способ преобразования этого XML / Stream в мои объекты DAL?

Пример XML:

<?xml version="1.0" encoding="UTF-8"?>
<enquiry>
    <enquiryno>100001</enquiryno>
    <companyname>myco</companyname>
    <typeofbusiness>dunno</typeofbusiness>
    <companyregno>ABC123</companyregno>
    <postcode>12345</postcode>
    <contactemail>me@example.com</contactemail>
    <firstname>My</firstname>
    <lastname>Name</lastname>
    <vehicles>
        <vehicle>
            <vehiclereg>54321</vehiclereg>
            <vehicletype>Car</vehicletype>
            <vehiclemake>Ford</vehiclemake>
            <cabtype>n/a</cabtype>
            <powerbhp>130</powerbhp>
            <registrationdate>01/01/2003</registrationdate>
        </vehicle>
    </vehicles>
</enquiry>

Обновление 1 : Я пытаюсь десериализовать, основываясь на примере Грэма. Я думаю Я настроил DAL для сериализации, включая указание [XmlElement("whatever")] для каждого свойства. И я попытался десериализовать, используя следующее:

SalesEnquiry enquiry = null;
XmlSerializer serializer = new XmlSerializer(typeof(SalesEnquiry));
enquiry = (SalesEnquiry)serializer.Deserialize(stream);

Однако я получаю исключение: 'There is an error in XML document (2, 2)'. Состояния невосприятия {"<enquiry xmlns=''> was not expected."}

Вывод (обновлено):

Моя предыдущая проблема заключалась в том, что элемент в XML-файле (Inquiry)! = Имя класса (SalesEnquiry). Вместо атрибута [XmlElement] для класса нам нужен атрибут [XmlRoot]. Для полноты, если вы хотите, чтобы свойство в вашем классе игнорировалось во время сериализации, используйте атрибут [XmlIgnore].

Я успешно сериализовал свой объект, и теперь успешно принял входящий XML и десериализовал его в объект SalesEnquiry.

Этот подход намного проще, чем ручной анализ XML. Хорошо, крутой курс обучения был, но оно того стоило.

Спасибо!

Ответы [ 3 ]

6 голосов
/ 27 июля 2010

Если в вашем XML используется схема (т.е. вы всегда будете знать, какие элементы появляются и где они появляются в дереве), вы можете использовать XmlSerializer для создания ваших объектов.Вам просто потребуются некоторые атрибуты в ваших классах, чтобы сообщить сериализатору, каким элементам или атрибутам XML они соответствуют.Затем вы просто загружаете свой XML, создаете новый XmlSerializer с типом объекта .NET, который хотите создать, и вызываете метод Deserialize.

Например, у вас есть такой класс, как этот:

[Serializable]
public class Person
{
    [XmlElement("PersonName")]
    public string Name { get; set; }

    [XmlElement("PersonAge")]
    public int Age { get; set; }

    [XmlArrayItem("Child")]
    public List<string> Children { get; set; }
}

И введите XML-код следующим образом (сохраненный в файле для этого примера):

<?xml version="1.0"?>
<Person>
  <PersonName>Bob</PersonName>
  <PersonAge>35</PersonAge>
  <Children>
    <Child>Chris</Child>
    <Child>Alice</Child>
  </Children>
</Person>

Затем создайте Person экземпляр, подобный этому:

Person person = null;
XmlSerializer serializer = new XmlSerializer(typeof(Person));
using (FileStream fs = new FileStream(GetFileName(), FileMode.Open))
{
    person = (Person)serializer.Deserialize(fs);
}

Обновление: Исходя из вашего последнего обновления, я бы предположил, что либо вам нужно указать атрибут XmlRoot для класса, который действует как ваш корневой элемент (то есть SalesEnquiry), либоXmlSerializer может быть немного озадачен тем, что вы ссылаетесь на пустое пространство имен в своем XML (xmlns='' кажется неправильным).

2 голосов
/ 27 июля 2010

XmlSerializer поддерживает массивы и списки ... при условии, что содержащийся тип является сериализуемым.

1 голос
/ 28 июля 2010

Я нашел Xsd2Code очень полезным для такого рода вещей: http://xsd2code.codeplex.com/

По сути, все, что вам нужно сделать, это написать файл xsd (файл схемы XML) и указать несколько параметров командной строки.Xsd2Code автоматически сгенерирует файл класса C #, который содержит все классы и свойства, а также все необходимое для обработки сериализации.Это не идеальное решение, поскольку оно не поддерживает все аспекты XSD, но если ваши XML-файлы представляют собой относительно простые наборы элементов и атрибутов, это должно быть хорошим сокращением для вас.

Есть еще один аналогпроект на Codeplex под названием Linq to XSD (http://linqtoxsd.codeplex.com/),), который был разработан для обеспечения выполнения всей спецификации XSD, но в прошлый раз, когда я проверял, его больше не поддерживали и он не был готов к прайм-тайм. Думаю, стоит упомянутьВпрочем.

...