【问题标题】:XML verification with XSD: attribute is not declared. But it is - see example使用 XSD 进行 XML 验证:未声明属性。但它是 - 见例子
【发布时间】: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


    【解决方案1】:

    elementFormDefault 不会对属性做任何事情,为您需要的attributeFormDefault 设置等效项。但是,默认情况下,这两个都设置为“不合格”。

    方法 2 - a:myBool="true" - 失败的原因是因为 attributeFormDefault 值没有被覆盖。如果要命名空间属性,可以将其设置为“qualified”将属性声明本身的form 属性设置为“qualified”,如下所示:

    <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 属性设置为“不合格”,以防 XSLT 引擎在未声明它们时无法识别它们的默认设置。像这样:

    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://foo.com/"
           attributeFormDefault="unqualified"
           xmlns="http://foo.com/">
    

    【讨论】:

    • 我认为如果元素在某个命名空间中(显式或使用 elementFormDefault),则 in 中的所有属性都将默认为相同的命名空间...我添加了 form="qualified",这确实使第二种形式有效。但是现在第一个无效。是否有验证两者的模式?他们似乎和我一样,我错过了什么吗?
    • 我认为没有一种模式可以同时允许两者。至少,这两者是不等价的——因为默认命名空间仅适用于元素,而不适用于属性。这大概是因为假设 ONE 作者可以控制一个元素的格式,因此属性名称中的名称冲突不是问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-13
    • 1970-01-01
    • 2014-03-27
    • 2016-10-18
    • 1970-01-01
    相关资源
    最近更新 更多