Какая структура класса будет имитировать XML-документ с чередующимися тегами - PullRequest
1 голос
/ 01 октября 2019

Я пытаюсь воспроизвести структуру файла XML программно, используя c #. Файловая структура доставляет мне трудности в том смысле, что она использует тег в качестве пустого набора данных или родительский тег для дочерних элементов в узлах. Как пример:

<?xml version="1.0" encoding="UTF-8"?>
<A>
  <B>
    <C>
      <E></E>
      <E></E>
      <F>false</F>
      <F>true</F>
      <F>false</F>
      <G>
        <H/>
      </G>
    </C>
    <B>
      <D>
        <E>continue</E>
        <G>
          <F>false</F>
          <E>1</E>
        </G>
      </D>
      <B/>
      <D>
        <E></E>
      </D>
      <B/>
    </B>
  </B>
</A>

Определенные узлы, вызывающие у меня трудности, это <B> узлы. Я не уверен, как структурировать класс так, чтобы он мог содержать список элементов узла в дополнение к самому себе, которые могут иметь или не иметь значения и которые могут быть сериализованы в XML-документ. Любая помощь будет приветствоваться, это может быть сложно объяснить, поэтому я с удовольствием уточню.

1 Ответ

0 голосов
/ 01 октября 2019

Если бы мы создали схему для вашего <B> узла, она бы состояла из последовательности из выбора узлов, где элемент типа <C>, <D> или <B> само по себе может быть выбрано.

Если бы мы смоделировали это в c #, естественным способом было бы использовать список полиморфных объектов, элементы которых соответствовали бытри типа элементов. К счастью, как объяснено в этом ответе на Использование XmlSerializer для сериализации производных классов от Марк Гравелл , этот сценарий поддерживается XmlSerializerаннотируя полиморфную коллекцию атрибутами [XmlElement(String, Type)], по одному для каждого конкретного типа, который может появиться в коллекции.

Таким образом, вы можете определить свою модель данных следующим образом:

public class BaseNode 
{
}

public class B : BaseNode
{
    [XmlElement("B", typeof(B))]
    [XmlElement("C", typeof(C))]
    [XmlElement("D", typeof(D))]
    public List<BaseNode> Nodes { get; } = new List<BaseNode>();
}

public class C : BaseNode
{
    [XmlElement(ElementName="E")]
    public List<string> E { get; set; }
    [XmlElement(ElementName="F")]
    public List<bool> F { get; set; }
    [XmlElement(ElementName="G")]
    public G1 G { get; set; }
}

public class D : BaseNode
{
    [XmlElement(ElementName="E")]
    public string E { get; set; }
    [XmlElement(ElementName="G")]
    public G2 G { get; set; }
}

public class G1
{
    public string H { get; set; }
}

public class G2 
{
    public string F { get; set; }
    public string E { get; set; }
}

[XmlRoot("A")]
public class A
{
    public B B { get; set; }
}

Примечания:

  • Я сделал 3 типа, которые могут появиться в коллекции B.Nodes, наследовать от общего предка BaseNode, так что добавить его невозможноне относящиеся к делу предметы в коллекцию во время выполнения. Если вы не хотите этого, вы можете исключить BaseNode и объявить свою коллекцию как List<object>.

  • По моему опыту, различные инструменты, упомянутые в Генерация класса C # из XML не всегда генерирует оптимальные классы c # из XML, который имеет сложные <xsd:choice> + <xsd:sequence> сценарии.

    Однако, если у вас был правильный XSD, инструменты из Как генерировать классы .NET 4.0 из xsd? сгенерировали бы правильные классы c #.

  • В вашем примере у вас есть два узла с именем <G>, которые, кажется, имеют разные схемы, поэтому мне пришлось создать два типа G1 и G2.

Демонстрационная скрипка здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...