【发布时间】:2013-12-27 20:55:13
【问题描述】:
我在根据架构验证 XML 时遇到问题。简化代码和示例:
验证码:
public static void ValidateXmlAgainstSchema(StreamReader xml, XmlSchema xmlSchema)
{
var settings = new XmlReaderSettings { IgnoreWhitespace = true, IgnoreComments = true };
settings.Schemas.Add(xmlSchema);
settings.ValidationType = ValidationType.Schema;
settings.ValidationEventHandler += (obj, args) => { if (args.Exception != null) throw args.Exception; };
using (var reader = XmlReader.Create(xml, settings))
using (XmlReader validatingReader = XmlReader.Create(reader, settings))
{
while (validatingReader.Read()){}
}
}
架构:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://foo.com/"
xmlns="http://foo.com/">
<xs:simpleType name="myBool">
<xs:restriction base="xs:string">
<xs:enumeration value="true"/>
<xs:enumeration value="false"/>
<xs:enumeration value="file_not_found"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="dataType">
<xs:sequence>
<xs:element name="id" type="xs:string" minOccurs="1" maxOccurs="1" />
<xs:element name="name" type="xs:string" minOccurs="0" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
<xs:element name="foo">
<xs:complexType>
<xs:sequence>
<xs:element name="data" type="dataType" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute name="myBool" type="myBool" use="optional" />
</xs:complexType>
</xs:element>
</xs:schema>
XML:
1.
<?xml version="1.0"?>
<foo xmlns="http://foo.com/" myBool="true">
<data>
<id>1</id>
<name>abc</name>
</data>
</foo>
本例抛出异常:
System.Xml.Schema.XmlSchemaValidationException:命名空间“http://foo.com/”中的元素“foo”具有无效的子元素“数据” 在命名空间“http://foo.com/”中。预期的可能元素列表:“数据”。
我的理解是,如果为一个元素定义了命名空间,那么所有子元素都将具有相同的命名空间,除非另有定义。但它不起作用。我可以通过将 elementFormDefault="qualified" 添加到架构来使其验证,这使得所有元素都默认为 targetNamespace。这是一个好方法吗?
2.
<?xml version="1.0"?>
<a:foo xmlns:a="http://foo.com/" a:myBool="true">
<a:data>
<a:id>1</a:id>
<a:name>abc</a:name>
</a:data>
</a:foo>
此示例失败并显示以下消息:
“http://foo.com/:myBool”属性未声明。
每个元素和属性都有一个明确的命名空间,所以 xml 应该是有效的。甚至错误消息表明解析器正在寻找我期望的属性,但找不到它。我可以通过将 a:myBool 更改为 myBool 来验证它。为什么它在第一种形式中不起作用而在另一种形式中起作用?
【问题讨论】:
标签: c# xml xsd xsd-validation