Попытка десериализации XML в объект C # - PullRequest
2 голосов
/ 26 марта 2011

У меня есть XML-файл, который представляет собой сериализованный экземпляр того, что в пользовательском интерфейсе является формой. Эта форма разработана пользователем и позволяет другим пользователям заполнять форму. После сохранения формы данные экземпляра сериализуются в столбец в базе данных. Я вызываю данные этого экземпляра, и мне нужно разобрать их, но у меня возникают проблемы с десериализацией - с использованием стандартной десериализации C #. Это одна форма для пользователя, но данные экземпляра фактически состоят из «подформ» - это формы, из которых состоит форма, которую видит пользователь.

Вот формат XML-документа:

 <Thing>
  <TheSections>
    <TheSection>
      <TheForms>
        <TheForm name="SomeUserForm">
          <Property name="BackgroundColor"/>
          <Control name="GroupHeading1" type="header" hasdata="N">
            <Control name="GroupHeading2" type="subheader" hasdata="N">
              <Control name="TextEntry1" type="detail" hasdata="Y">
                <Property name="ValueField">I want to order 3 of these</Property>
                <Property name="Type">TextField</Property>
              </Control>
            </Control>
          </Control>
        </Form>
        <Form>....</Form>
        <Form>....</Form>
        <Form>....</Form>
      </TheForms>
    </TheSection>
    <TheSection>...</TheSection>
  </TheSections>
</Thing>

Как видите, элементы управления могут быть вложены в другие элементы управления, а свойства являются частью элемента управления.

У меня десериализация работает до уровня формы, однако, когда я пытаюсь десериализовать элементы управления, они ломаются.

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

Есть ли способ заставить десериализацию взглянуть на этот XML, как если бы все элементы управления были на одном уровне, независимо от их иерархии, и просто десериализовать все вложения автоматически?

Спасибо за любые советы!

Вот XSD, сгенерированный из файла XML в Visual Studio 2008 (как вы увидите, исходный XML не имеет форм выше каждой формы или разделов над каждым разделом - я добавляю это при загрузке XML:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Thing">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="TheSection">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="TheForm">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element maxOccurs="unbounded" name="Control">
                      <xs:complexType mixed="true">
                        <xs:sequence>
                          <xs:element name="Group">
                            <xs:complexType>
                              <xs:sequence minOccurs="0">
                                <xs:element maxOccurs="unbounded" name="GroupItem">
                                  <xs:complexType>
                                    <xs:attribute name="name" type="xs:string" use="required" />
                                    <xs:attribute name="taborder" type="xs:unsignedByte" use="required" />
                                    <xs:attribute name="posneg" type="xs:string" use="required" />
                                    <xs:attribute name="qualifier" type="xs:string" use="required" />
                                  </xs:complexType>
                                </xs:element>
                              </xs:sequence>
                              <xs:attribute name="name" type="xs:string" use="required" />
                              <xs:attribute name="render" type="xs:string" use="required" />
                              <xs:attribute name="size" type="xs:unsignedByte" use="required" />
                              <xs:attribute name="indent" type="xs:string" use="required" />
                              <xs:attribute name="newline" type="xs:string" use="required" />
                            </xs:complexType>
                          </xs:element>
                          <xs:element minOccurs="0" maxOccurs="unbounded" name="Control">
                            <xs:complexType mixed="true">
                              <xs:sequence minOccurs="0">
                                <xs:element maxOccurs="unbounded" name="Property">
                                  <xs:complexType>
                                    <xs:simpleContent>
                                      <xs:extension base="xs:string">
                                        <xs:attribute name="name" type="xs:string" use="required" />
                                      </xs:extension>
                                    </xs:simpleContent>
                                  </xs:complexType>
                                </xs:element>
                              </xs:sequence>
                              <xs:attribute name="name" type="xs:string" use="required" />
                              <xs:attribute name="hasdata" type="xs:string" use="required" />
                              <xs:attribute name="type" type="xs:string" use="required" />
                              <xs:attribute name="font" type="xs:string" use="required" />
                              <xs:attribute name="size" type="xs:unsignedByte" use="required" />
                              <xs:attribute name="indent" type="xs:string" use="required" />
                              <xs:attribute name="bold" type="xs:string" use="required" />
                              <xs:attribute name="bullet" type="xs:string" use="required" />
                              <xs:attribute name="newline" type="xs:string" use="required" />
                              <xs:attribute name="render" type="xs:string" use="required" />
                              <xs:attribute name="forceparagraph" type="xs:string" use="required" />
                              <xs:attribute name="startnewsentence" type="xs:string" use="required" />
                              <xs:attribute name="commadelimited" type="xs:string" use="required" />
                              <xs:attribute name="qualifier" type="xs:string" use="required" />
                            </xs:complexType>
                          </xs:element>
                          <xs:element minOccurs="0" name="RenderText" type="xs:string" />
                        </xs:sequence>
                        <xs:attribute name="name" type="xs:string" use="required" />
                        <xs:attribute name="hasdata" type="xs:string" use="required" />
                        <xs:attribute name="type" type="xs:string" use="required" />
                        <xs:attribute name="font" type="xs:string" use="required" />
                        <xs:attribute name="size" type="xs:unsignedByte" use="required" />
                        <xs:attribute name="indent" type="xs:string" use="required" />
                        <xs:attribute name="bold" type="xs:string" use="required" />
                        <xs:attribute name="bullet" type="xs:string" use="required" />
                        <xs:attribute name="newline" type="xs:string" use="required" />
                        <xs:attribute name="render" type="xs:string" use="required" />
                        <xs:attribute name="forceparagraph" type="xs:string" use="required" />
                        <xs:attribute name="startnewsentence" type="xs:string" use="required" />
                        <xs:attribute name="commadelimited" type="xs:string" use="required" />
                        <xs:attribute name="qualifier" type="xs:string" use="required" />
                        <xs:attribute name="headinglevel" type="xs:unsignedByte" use="required" />
                        <xs:attribute name="normalgroup" type="xs:string" use="required" />
                        <xs:attribute name="renderwithdata" type="xs:string" use="required" />
                        <xs:attribute name="grouptype" type="xs:string" use="required" />
                        <xs:attribute name="label" type="xs:string" use="required" />
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                  <xs:attribute name="id" type="xs:string" use="required" />
                  <xs:attribute name="name" type="xs:string" use="required" />
                  <xs:attribute name="type" type="xs:string" use="required" />
                  <xs:attribute name="font" type="xs:string" use="required" />
                  <xs:attribute name="size" type="xs:unsignedByte" use="required" />
                  <xs:attribute name="indent" type="xs:string" use="required" />
                  <xs:attribute name="bold" type="xs:string" use="required" />
                  <xs:attribute name="bullet" type="xs:string" use="required" />
                  <xs:attribute name="newline" type="xs:string" use="required" />
                  <xs:attribute name="forceparagraph" type="xs:string" use="required" />
                  <xs:attribute name="startnewsentence" type="xs:string" use="required" />
                  <xs:attribute name="commadelimited" type="xs:string" use="required" />
                  <xs:attribute name="qualifier" type="xs:string" use="required" />
                  <xs:attribute name="render" type="xs:string" use="required" />
                  <xs:attribute name="rendercount" type="xs:unsignedByte" use="required" />
                </xs:complexType>
              </xs:element>
            </xs:sequence>
            <xs:attribute name="type" type="xs:string" use="required" />
            <xs:attribute name="id" type="xs:unsignedByte" use="required" />
            <xs:attribute name="name" type="xs:string" use="required" />
            <xs:attribute name="render" type="xs:string" use="required" />
            <xs:attribute name="font" type="xs:string" use="required" />
            <xs:attribute name="size" type="xs:unsignedByte" use="required" />
            <xs:attribute name="indent" type="xs:string" use="required" />
            <xs:attribute name="bold" type="xs:string" use="required" />
            <xs:attribute name="bullet" type="xs:string" use="required" />
            <xs:attribute name="newline" type="xs:string" use="required" />
            <xs:attribute name="forceparagraph" type="xs:string" use="required" />
            <xs:attribute name="rendercount" type="xs:unsignedByte" use="required" />
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Вот пример класса, который я использую для десериализации:

[ XmlRoot("Section")
    ]
    public class MySectionData
    {
        private MyFormData[] _Forms = new MyFormData[0];

        [ XmlArray("Forms")
        ]
        [ XmlArrayItem("Form")
        ]
        public MyFormData[] Forms
        {
            set
            {
                this._Forms = value;
            }
            get
            {
                return this._Forms;
            }
        }

        [ XmlAttribute("id")
        ]
        public String Id
        {
            set;
            get;
        }
        [XmlAttribute("name")
     ]
        public String name
        {
            set;
            get;
        }

    }

Ответы [ 2 ]

2 голосов
/ 27 марта 2011

Вы могли бы потратить много времени и энергии, выясняя нюансы сериализации XML и пытаясь построить классы, чтобы они могли более или менее работать с этим форматом. Однако я думаю, что это проще:

  1. Создайте класс Control, который можно сериализовать в XML. Создайте сериализуемый класс, который имеет коллекцию Control объектов, заполните его и сериализуйте. Теперь вы знаете, какой ввод требуется десериализатору XML для этого класса.

  2. Напишите XSLT-преобразование, которое преобразует входной XML, который у вас есть, во нужный вам входной XML.

0 голосов
/ 27 марта 2011

Вы пытались использовать xsd.exe для создания классов на основе вашей схемы?Если «элементы управления» оказываются вложенными, вы все равно можете написать функцию, чтобы «сгладить» их и вернуть весь набор, верно?

Он находится здесь: C: \ Program Files (x86) \ Microsoft SDKs\ Windows \ v7.0A \ Bin \ NETFX 4.0 Tools \

...