我遇到了针对架构验证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应该是有效的。甚至错误消息也表明解析器正在寻找我期望它的属性,但却找不到它。我可以通过将myBool更改为myBool来使其验证。为什么它不以第一种形式起作用而在另一种形式起作用?
答案 0 :(得分:1)
elementFormDefault
无法对属性做任何事情,为您需要的人attributeFormDefault
设置等值。但是,默认情况下,这两个都设置为&#34;不合格&#34;。
原因方法2 - a:myBool="true"
- 失败是因为attributeFormDefault
值未被覆盖。如果要命名空间属性,可以将其设置为&#34; qualified&#34; 或将属性声明本身的form
属性设置为&#34; qualified&#34;,如下所示:
<xs:attribute name="myBool" type="myBool" use="optional" form="qualfied"/>
这应该使这成为方法2的有效元素开始:
<a:foo xmlns:a="http://foo.com/" a:myBool="true">
至于为什么方法1失败,我不确定,你的XSD和XML匹配。可能值得添加将根XSD元素上的attributeFormDefault
属性设置为&#34;不合格&#34;,以防万一XSLT引擎在它们不是时不识别它们的默认设置声明。像这样:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://foo.com/"
attributeFormDefault="unqualified"
xmlns="http://foo.com/">