.NET XmlSerializer(de)使用模式编译器xsd.exe和错误的命名空间绑定从不同的命名空间序列化派生类型

时间:2012-10-28 17:05:19

标签: c# .net xml xml-serialization xsd

我正在尝试使用XML Schema Definition Tool从以下架构生成CS代码:

A.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xs:complexType name="Bar">
        <xs:sequence>
            <xs:element name="v" type="xs:double"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="Base"/>
    <xs:element name="root" type="Base" />
</xs:schema>

B.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ns1="v2" targetNamespace="v2" elementFormDefault="qualified">
    <xs:import schemaLocation="A.xsd"/>
    <xs:complexType name="Derived">
        <xs:complexContent>
            <xs:extension base="Base">
                <xs:sequence>
                    <xs:element name="b" type="Bar"/>
                </xs:sequence>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
</xs:schema>

我执行xsd.exe架构编译器,如下所示:

xsd.exe A.xsd B.xsd / c

并获取一个B_A.cs文件(很多代码,可以自己重新生成)。

有两个意想不到的行为。

序列化: 如果序列化Derived类型的Bar实例:

    XmlSerializer serializer = new XmlSerializer(typeof(Base));
    Derived d = new Derived();
    d.b = new Bar();
    d.b.v = 12.123;
    serializer.Serialize(Console.Out, d);

你明白了:

<?xml version="1.0" encoding="ibm850"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:q1="v2" xsi:type="q1:Derived">
  <q1:b>
    <q1:v>12.123</q1:v>
  </q1:b>
</root>

由于b中的v元素是以q1为前缀的名称空间,因此不会对B.xsd进行验证。摆脱前缀,它验证,因为(我相信)是正确的。

同样,反过来说。获取此实例文档,该文档验证:

<?xml version="1.0" encoding="utf-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:q1="v2" xsi:schemaLocation="v2 B.xsd" xsi:type="q1:Derived">
  <q1:b>
    <v>12.123</v>
  </q1:b>
</root>

尝试使用生成的代码对其进行反序列化,如下所示:

    XmlSerializer serializer = new XmlSerializer(typeof(Base));
    Bar p = (Bar)serializer.Deserialize(new FileStream(@"..\..\test.xml", FileMode.Open));
    Console.Out.WriteLine(p.v);

得到0.0输出,因为默认初始化为v。将q1:前缀添加到实例文档的v元素,它可以工作,但无效。

有人会同意这是XML Schema定义工具的错吗?我不相信它会生成正确的序列化代码,但很难归咎于这些工具。如果我们将带有Namespace =“”的XmlElement属性添加到v,它可以工作,但现在我正在修改生成的代码,这是不可取的(我正在工作的项目生成代码作为构建的一部分 - 我们不是应该改变它。)

我有什么想法可以解决这个问题吗?

1 个答案:

答案 0 :(得分:0)

好吧,我有一些我认为可以使用的东西 - 我会在单独的cs模块中向Bar分部类添加一个XmlRootAttribute(Namespace =“”)。