【问题标题】:XSD2Code classes require duplicate-named element containing collection of elementsXSD2Code 类需要包含元素集合的重复命名元素
【发布时间】:2016-06-09 14:32:14
【问题描述】:

给定 XSD 喜欢:

  <xs:complexType name="accident">
    <xs:sequence>
      <xs:element name="NAME" type="xs:string" />
      <xs:element name="DESCRIPTION" type="xs:string" />
      <xs:element name="CREATIONDATE" type="xs:dateTime" />
    </xs:sequence>
  </xs:complexType>

  <xs:element name="accidents">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="accident" type="accident" maxOccurs="unbounded" minOccurs="0"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

我希望 XML 像:

<?xml version="1.0" encoding="UTF-8"?>
<accidents>
  <accident>
    <NAME>Accident 123</NAME>
    <DESCRIPTION>Car crash</DESCRIPTION>
    <CREATIONDATE>2016-01-20T12:08:00+00:00</CREATIONDATE>
  </accident>
</accidents>

我使用 XSD2Code 生成 C# 类,因此我可以轻松地从 Web 服务反序列化 XML。但他们工作不正常 - 他们像我的示例一样成功加载了测试 XML,但 accident 元素为零。

所以我决定扭转这个过程:

    accidents aa = new accidents();
    accident a = new accident();
    a.NAME = "test";
    aa.accident.Add(a);
    aa.SaveToFile("accidents.xml");

这发出了以下 XML:

<?xml version="1.0"?>
<accidents xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <accident>
    <accident>
      <NAME>test</NAME>
      <CREATIONDATE>0001-01-01T00:00:00</CREATIONDATE>
    </accident>
  </accident>
</accidents>

如果我尝试反序列化该 XML,它工作得很好。但请注意,有一个嵌套的 accident 不正确,我不知道它会这样做或如何解决它!

这似乎是一个类似的问题,但由于它没有引起太多关注并且不包括 XSD,我不确定:xsd2code creates extra nested collection when serializing lists

【问题讨论】:

    标签: c# xml xsd xsd2code


    【解决方案1】:

    我在现场有点晚了,但不管怎样!

    我自己使用 Xsd2Code 已经有一段时间了,以利用一些很酷的功能,但我发现它确实有一些烦人的怪癖。我同意您描述的这个问题看起来像一个错误。但是,我发现如果您的集合本身就是另一种复杂类型的子元素,问题就会消失。例如,如果您很高兴您的“事故”作为“报告”的属性存在,那么您可以按如下方式更改您的架构:

     <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
      <xs:complexType name="accident">
        <xs:sequence>
          <xs:element name="NAME" type="xs:string" />
          <xs:element name="DESCRIPTION" type="xs:string" />
          <xs:element name="CREATIONDATE" type="xs:dateTime" />
        </xs:sequence>
      </xs:complexType>
      <xs:complexType name="accidents">
         <xs:sequence>
           <xs:element name="accident" type="accident" maxOccurs="unbounded" minOccurs="0"/>
         </xs:sequence>
      </xs:complexType>
      <xs:complexType name="report">
        <xs:sequence>
          <xs:element name="accidents" type="accidents"/>
        </xs:sequence>
      </xs:complexType>   
    </xs:schema>
    

    当您通过 Xsd2Code 工具运行它时,您会发现 生成的代码将报告类型的事故属性创建为事故列表,并将按照您期望的方式进行序列化。

    您的测试代码应该看起来更像这样:

            report r = new report();
            r.accidents = new List<accident>();
            accident a = new accident();
            a.NAME = "test";
            r.accidents.Add(a);
            r.SaveToFile("accidents.xml");
    

    不幸的是,仍然会生成狡猾的 accidents 类 - 这可能会导致其他开发人员感到困惑,但有一种方法可以防止这种情况发生。 首先,将 accidentaccidents complexType 定义放在一个 文件,accidents.xsd。然后将 report 定义放在 report.xsd 中 引用 accidents.xsd 的包含语句。只通过 report.xsd 通过 Xsd2Code 工具。格式错误的 accidents 类不会出现在生成的代码中。当然,这只是一个说明性示例 - 根据需要扩展。在没有修复的情况下,这对我来说是一个非常好的解决方案 - 希望它会满足您的需求。

    【讨论】:

      【解决方案2】:

      您可以从在 XSD 中指定目标名称空间和显式限定标志开始。也就是说,将您的 xsd 转换为:

      <?xml version="1.0" encoding="utf-8"?>
      <xs:schema attributeFormDefault="unqualified"
               elementFormDefault="qualified"
               xmlns:xs="http://www.w3.org/2001/XMLSchema"
               targetNamespace="http://example.com/foo"
               xmlns="http://example.com/foo">
      
      <xs:complexType name="accident">
        <xs:sequence>
          <xs:element name="NAME" type="xs:string" />
          <xs:element name="DESCRIPTION" type="xs:string" />
          <xs:element name="CREATIONDATE" type="xs:dateTime" />
        </xs:sequence>
      </xs:complexType>
      
      <xs:element name="accidents">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="accident" type="accident" maxOccurs="unbounded" minOccurs="0"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      
      </xs:schema>
      

      和你的 XML 到:

      <?xml version="1.0" encoding="UTF-8"?>
      <accidents xmlns="http://example.com/foo"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://example.com/foo foo.xsd">
        <accident>
          <NAME>Accident 123</NAME>
          <DESCRIPTION>Car crash</DESCRIPTION>
          <CREATIONDATE>2016-01-20T12:08:00+00:00</CREATIONDATE>
        </accident>
      </accidents>
      

      (您需要将您的 xsd 文件另存为 foo.exe 以便上述参考工作)。

      我不确定这是否能解决您的 XSD2Code 问题,但我已将此标头格式与 xsd.exe 一起用于许多等效(并且更复杂)的代码。它可以让您在 XML 中获得 Intellisense,并且可能也足以让 XSD2Code 正常运行。

      【讨论】:

      • 我测试了这些东西,但它们没有帮助。我正在考虑使用 Xsd.exe 而不是 Xsd2Code 但这似乎是一种作弊 - 它不会自动创建保存/加载和 [de] 序列化代码:(
      • 啊,太糟糕了。如果您决定放下自尊并使用 xsd.exe,您可以创建一个模板化的静态 XmlSerializationHelper 类,其中包含可以从任何地方调用的公共 Serialize 和 Deserialize 方法。
      • 这似乎是 Xsd2Code 中的一个相当大的错误,所以我假设它是用户错误......否则当 Xsd.exe 已经可用时,他们不会费心去做:)
      • 按照stackoverflow.com/questions/37747126/…,无论如何,我基本上都是按照您的建议作为临时解决方案
      猜你喜欢
      • 2012-12-01
      • 1970-01-01
      • 2021-02-12
      • 2013-01-10
      • 2012-07-01
      • 2022-07-05
      • 1970-01-01
      • 1970-01-01
      • 2017-12-02
      相关资源
      最近更新 更多