我正在尝试使用XML 模式定义工具从以下模式生成 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,它可以工作,但现在我正在修改生成的代码,这是不可取的(我正在工作的项目生成代码作为构建的一部分 - 我们不是应该改变它)。
有什么想法可以解决这个问题吗?