使用XSD架构进行XML验证 - ValidationEventHandler信息

时间:2017-08-10 12:07:49

标签: xml validation c#-4.0 xsd schema

我有一个架构:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="address">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="name" type="xs:string"/>
                <xs:element name="street" type="xs:string"/>
                <xs:element name="city" type="xs:string"/>
                <xs:element name="country">
                    <xs:simpleType>
                        <xs:restriction base="xs:string">
                            <xs:minLength value="5"/>
                            <xs:maxLength value="8"/>
                        </xs:restriction>
                    </xs:simpleType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

简单的XML文件(这是唯一的例子):

<address xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="address.xsd"> 
  <name>John Smith</name>
  <street>109 Abbey Close</street>
  <city>Hayes</city>
  <country>UK</country>
</address>

我正在使用ValidationEventHandler,但我需要对此进行编码,以便为客户端提供有关错误的明确信息。例如,对于只有4个长度的国家,我将得到“country”字段长度小于MinValue的错误。

但我想向客户提供有关“MinValue”的信息,因此本例为“5”。

我很长时间都在搜索,但我找不到这个。

你知道我怎么做吗?

现在我有了这段代码:

public static bool Validate(Stream xml, Stream xsd) 
{
    ClearErrorMessage();
    try {
        XmlTextReader tr = new XmlTextReader(xsd);
        XmlSchemaSet schema = new XmlSchemaSet();

        schema.Add(null, tr);

        XmlReaderSettings settings = new XmlReaderSettings();
        settings.ValidationType = ValidationType.Schema;
        settings.Schemas.Add(schema);
        settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
        settings.ValidationEventHandler += new ValidationEventHandler(ErrorHandler);
        XmlReader reader = XmlReader.Create(xml, settings);

        while(reader.Read()) {
        }
        reader.Close();

        if(numErrors > 0)
            throw new Exception(msgError);

        return true;
    }
    catch(Exception e) {
        msgError = "Validation failed\r\n" + msgError + " " + e.Message;
        return false;
    }
}

private static void ErrorHandler(object sender, ValidationEventArgs args) 
{
    msgError = msgError + "\r\n" + args.Message + " " + args.Exception.LineNumber;
    numErrors++;
}

1 个答案:

答案 0 :(得分:0)

我所知道的大多数架构验证器都允许很少自定义错误报告。要生成为最终用户设计的错误消息,最好使用Schematron,它将此作为其主要设计目标之一。

另一种方法是使用Saxon的模式验证器,它能够生成XML验证报告,然后您可以使用XSLT将其转换为最终用户术语。对于您的示例,验证报告将是:

<?xml version="1.0" encoding="UTF-8"?>
<validation-report xmlns="http://saxon.sf.net/ns/validation"
                   system-id="file:/Users/mike/Desktop/temp/test.xml">
   <error line="6"
          column="14"
          path="/Q{}address[1]/Q{}country[1]"
          xsd-part="2"
          constraint="cvc-datatype-valid.1">The content "UK" of element &lt;country&gt; does not match the required simple type. Value "UK" contravenes the minLength facet "5" of the type of element country</error>
   <meta-data>
      <validator name="SAXON-EE" version="9.8.0.3"/>
      <results errors="1" warnings="0"/>
      <schema file="test.xsd" xsd-version="1.1"/>
      <run at="2017-08-10T18:36:16.694+01:00"/>
   </meta-data>
</validation-report>

您可以尝试在此处使用XSLT模式匹配,以使消息更加方便最终用户。

(我的意图是最终为此验证报告添加更多语义标记,以便更轻松,例如撰写<facet>minLength</facet><facetValue>5</facetValue>。但这仍然是一个愿望。)