为什么XmlReader没有验证限制约束

时间:2014-01-21 08:21:53

标签: c# xml validation xsd xmlreader

我正在尝试使用架构验证xml字符串,并且遇到了使用facets无法识别xsd中的限制的问题。我已经创建了一个单元测试,我将一个对象序列化为xml,使用我的模式验证xml并将xml反序列化回对象。一切都很好,但由于某些原因,当我的纬度在模式中指定的范围内时,我没有收到错误。我已经将纬度定义在-90到90之间但是当我超出界限时我没有收到错误。这是序列化后得到的xml:

<?xml version="1.0" encoding="utf-8"?>
<Messages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Message>    
    <Blocks>
      <Location>
        <Latitude>110.5</Latitude>
        <Longitude>11.5</Longitude>
        <IsValid>true</IsValid>
        <PrecisionKilometers>1</PrecisionKilometers>
      </Location>      
    </Blocks>
  </Message>  
</Messages>

我正在使用的架构如下所示。纬度的相关部分位于中间。 (我知道它有点难看,我试图让他们优化他们的模式生成代码)

<?xml version="1.0" encoding="utf-16"?>
<xs:schema xmlns:VL="http://customUri" elementFormDefault="qualified" targetNamespace="http://customUri" id="MessageList" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Messages">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="1" maxOccurs="unbounded" name="Message" nillable="true">
          <xs:complexType>
            <xs:sequence>
              <xs:element minOccurs="1" maxOccurs="unbounded" name="Blocks">
                <xs:complexType>
                  <xs:all>

                    <xs:element minOccurs="0" maxOccurs="1" name="Location" nillable="true">
                      <xs:complexType>
                        <xs:sequence>
                          <xs:element minOccurs="1" maxOccurs="1" name="Latitude">
                            <xs:simpleType>
                              <xs:restriction base="xs:double">
                                <xs:minInclusive value="-90" />
                                <xs:maxExclusive value="90" />
                              </xs:restriction>
                            </xs:simpleType>
                          </xs:element>
                          <xs:element minOccurs="1" maxOccurs="1" name="Longitude">
                            <xs:simpleType>
                              <xs:restriction base="xs:double">
                                <xs:minInclusive value="-180" />
                                <xs:maxExclusive value="180" />
                              </xs:restriction>
                            </xs:simpleType>
                          </xs:element>
                          <xs:element minOccurs="1" maxOccurs="1" name="IsValid" type="xs:boolean" />
                          <xs:element minOccurs="0" maxOccurs="1" name="PrecisionKilometers" nillable="true" type="xs:double" />
                        </xs:sequence>
                      </xs:complexType>
                    </xs:element>

                  </xs:all>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

我读取xml的设置是:(注意我为ReportValidationWarnings和ProcessIdentityContraints指定了标志,并使用验证处理程序来检测警告)

    var settings = new XmlReaderSettings
          {
            ValidationType = ValidationType.Schema,
            ValidationFlags =         
              XmlSchemaValidationFlags.ReportValidationWarnings |
              XmlSchemaValidationFlags.ProcessInlineSchema |
              XmlSchemaValidationFlags.ProcessSchemaLocation |
              XmlSchemaValidationFlags.ProcessIdentityConstraints |
              XmlSchemaValidationFlags.AllowXmlAttributes,
            IgnoreWhitespace = true,
            IgnoreComments = true,
          };
settings.ValidationEventHandler += (o, ex) =>
          {            
            if (ex.Severity == XmlSeverityType.Warning || ex.Severity == XmlSeverityType.Error)
            {
              //do something
            }
          };
    settings.Schemas.Add(mySchemaSet);

我用来反序列化的代码非常标准。

XmlReader reader = XmlReader.Create(memoryStreamContainingXml, settings);
var serializer = new XmlSerializer(typeof(MessageList));
MessageList returned = ser.Deserialize(reader) as MessageList;

我也尝试过while(reader.read(){})而不是反序列化,看看是否抛出了验证错误,但我没有遇到任何问题。

1 个答案:

答案 0 :(得分:1)

使用以下XML尝试您的代码:

<ns0:Messages xmlns:ns0="http://customUri">
  <ns0:Message>
    <ns0:Blocks>
      <ns0:Location>
        <ns0:Latitude>110.0</ns0:Latitude>
        <ns0:Longitude>11.5</ns0:Longitude>
        <ns0:IsValid>true</ns0:IsValid>
        <ns0:PrecisionKilometers>1</ns0:PrecisionKilometers>
      </ns0:Location>
    </ns0:Blocks>
  </ns0:Message>
</ns0:Messages>

正如Vadim在评论中所说,您需要告诉验证者XML中的类型是模式中定义的类型。这样做的方法是在XML实例中包含模式的目标名称空间。

如果没有这个,所有验证器都可以检查XML是否格式正确。这就是它返回有效结果的原因。

<强>更新

enter image description here

enter image description here