为什么这个XML要验证,而它不应该验证

本文关键字:验证 不应该 XML 为什么 | 更新日期: 2023-09-27 18:05:43

我有以下XSD文件:

ReadFile.xsd:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns="elsag:lprcore" elementFormDefault="qualified" targetNamespace="elsag:lprcore" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:include schemaLocation="Read.xsd" />
  <xs:element name="reads" type="ReadFile" />
  <xs:complexType name="ReadFile">        
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="unbounded" name="read" nillable="true" type="read">
      </xs:element>
    </xs:sequence>
  </xs:complexType>
</xs:schema>

Read.xsd:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns="elsag:lprcore" elementFormDefault="qualified" targetNamespace="elsag:lprcore" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:include schemaLocation="Snapshot.xsd"/>
  <xs:include schemaLocation="GPS.xsd"/>
  <xs:simpleType name="guid">
    <xs:restriction base="xs:string">
      <xs:pattern value="[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}" />
    </xs:restriction>
  </xs:simpleType>
  <xs:element name="read" type="read"/>
  <xs:complexType name="read">
    <xs:complexContent mixed="false">
      <xs:extension base="snapshot">
        <xs:sequence>
          <xs:element minOccurs="1" maxOccurs="1" name="timestamp" type="xs:dateTime" />
          <xs:element minOccurs="1" maxOccurs="1" name="plate" type="xs:string" />
          <xs:element minOccurs="0" maxOccurs="1" name="state" type="xs:string" />
          <xs:element minOccurs="1" maxOccurs="1" name="confidence" type="xs:int" />
          <xs:element minOccurs="1" maxOccurs="1" name="overviews">
            </xs:annotation>
            <xs:complexType>
              <xs:sequence>
                <xs:element minOccurs="0" maxOccurs="unbounded" name="snapshot" type="snapshot"/>
              </xs:sequence>
            </xs:complexType>
          </xs:element>
          <xs:element minOccurs="1" maxOccurs="1" name="gps" type="gps" />
        </xs:sequence>
        <xs:attribute name="id" type="guid" use="required" />
        <xs:attribute name="camera" type="xs:string" use="required" />
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
</xs:schema>

请注意,还有更多的文件组成了XSD,但我不相信他们是相关的问题,所以我没有包括他们。

我使用以下代码验证正在处理的XML文件。我想拒绝任何没有验证错误的文件:

StringBuilder validationErrors = new StringBuilder();
inDoc.Validate( schemas, ( o, e ) => {
    validationErrors.AppendLine( e.Message );
} );
if ( !string.IsNullOrWhiteSpace( validationErrors.ToString() ) ) {
    . . .
}

我将下面的XML文件传递给上面的代码,代码没有为它生成任何验证错误消息。

<read>
  <timestamp>2015-07-17T16:20:18.1540000-04:00</timestamp>
  <plate>FED456</plate>
</read>

我本以为缺少read标记周围的reads标记会导致XML验证失败。问题是在验证代码中,还是在XSD中,或者这是正常的?

编辑:

下面是初始化schemas变量的代码:

XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add( "elsag:lprcore", @"XML'ReadFile.xsd" );

为什么这个XML要验证,而它不应该验证

因为您已经定义了

<xs:element name="read" type="read"/>

read元素是XML的有效根元素。每个<xs:schema>的直接子元素都有资格成为根元素(即使是在包含的模式中)。

感谢gloria findel在回答中发布的信息和overlack发布的链接,我已经能够在我的程序中获得XML验证。

问题是程序不会将不包含命名空间的XML文件标记为无效。原因是XDocument.Validate扩展方法创建了一个XmlReader对象,其XmlReaderSettings属性不包含ReportValidationWarnings标志。因此,传递给该方法的ValidationEventHandler委托不会为这些文件调用。

为了使验证逻辑工作,我定义了一个新的扩展方法,它包含了标志:

internal static class XmlValidationExtension {
    public static void ValidateWithWarnings( this XDocument doc, XmlSchemaSet schemas, ValidationEventHandler validationCallback ) {
        XmlReaderSettings settings = new XmlReaderSettings();
        settings.ValidationType = ValidationType.Schema;
        settings.Schemas.Add( schemas );
        settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
        settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
        settings.ValidationEventHandler += new ValidationEventHandler( validationCallback );
        XmlReader reader = XmlReader.Create( doc.CreateReader(), settings );
        while ( reader.Read() ) ;
    }
}

这基本上与overlack所链接的问题的代码完全相同,但是XmlReader是通过调用XDocment对象的CreateReader方法创建的。

这段代码现在认为任何没有使用正确名称空间的XML文件都是无效的。XML中与XSD不匹配的任何其他部分也会被标记。