如何提高XSD验证的详细程度

时间:2014-01-15 13:34:45

标签: c# xml validation xsd

我使用XmlDocument.Validate(ValidationEventHandler)XDocument.Validate(schemas, ValidationEventHandler)XmlReader通过传递给它的架构将结果发送到ValidationEventHandler回调,使用xsd探索了各种类型的xml验证

然而,回调实际上只提供严重性和错误字符串。我收到的消息如下:

The 'name' attribute is invalid - The value '' is invalid according to
its datatype 'TNonEmptyStringNoWhitespacesAtBeginningAndEnd' - The
Pattern constraint failed.

现在这远非理想的错误消息。回调参数不提供父引发的内容,也不提供XML行或任何实际的内容。

在我的场景中,并非所有名称都属于上面给定的类型,其中一些名称可能只是空字符串(因为它们是可选的)。

现在可能有数百个带有名称的xml节点,因此找到上面的问题非常烦人,因为没有关于位置的上下文信息,甚至没有xml节点的信息。

如何延长此类验证的详细程度? Notepad ++例如使用XML Tools插件将上面的消息输出为:

使用XML架构验证当前文件:

ERROR: Element 'LightSource', attribute 'name': [facet 'minLength'] The value '' has a length of '0'; this underruns the allowed minimum length of '1'.
ERROR: Element 'LightSource', attribute 'name': [facet 'pattern'] The value '' is not accepted by the pattern '.*\S'.
ERROR: Element 'LightSource', attribute 'name': '' is not a valid value of the atomic type 'TNonEmptyStringNoWhitespacesAtBeginningAndEnd'.

这更详细,并且至少表明一些上下文信息,例如LightSource元素上出现的问题,以及底层类型究竟出了什么问题。

是否有其他设施允许通过增加的上下文信息进行正确的C#XSD验证?

使用XDocumentXmlDocument对XML的内存中表示进行了验证,并使用XmlReader从文件中读取。显然行号等仅在已经编写了xml文件的上下文中才有意义,但是其他信息(如父元素等)会很方便,所以我至少可以输出xml上下文来查看。


为了完整起见,一些代码:

    var schemas = new XmlSchemaSet();
    schemas.Add("", xsdPath);
    var doc = XDocument.Load(xmlFile);
    doc.Validate(schemas,ValidationEventHandler);

    public void ValidationEventHandler(object sender, ValidationEventArgs e)
    {
        // Not much in e
        switch (e.Severity)
        {
            case XmlSeverityType.Error:
                Console.WriteLine("Error: {0}", e.Message);
                break;
            case XmlSeverityType.Warning:
                Console.WriteLine("Warning {0}", e.Message);
                break;
        }

    }

另一个看起来很有希望的尝试是http://msdn.microsoft.com/en-us/library/as3tta56%28v=vs.110%29.aspx,但根本没有增加任何冗长。

<小时/> 其余部分的一些解释。

我有一些形成约束的类型:

<xs:simpleType name="TNonEmptyStringNoWhitespacesAtBeginn">
    <xs:restriction base="xs:string">
        <xs:pattern value="\S.*" /> 
        <xs:minLength value="1"/>
    </xs:restriction>
</xs:simpleType>

<xs:simpleType name="TNonEmptyStringNoWhitespacesAtBeginningAndEnd">
    <xs:restriction base="TNonEmptyStringNoWhitespacesAtBeginn">
        <xs:pattern value=".*\S" />
        <xs:minLength value="1"/>
    </xs:restriction>
</xs:simpleType>

忽略TNonEmptyStringNoWhitespacesAtBeginn它是一个允许AND-ing限制的帮手。因此,当我的属性name具有上面的类型只是一个空字符串时,我从C#的XSD验证和Notepads ++ XML Tools Plugin所做的信息中获得了大量不同的信息。 为了完整起见,以下是不同的消息:

C#

The 'name' attribute is invalid - The value '' is invalid according to
its datatype 'TNonEmptyStringNoWhitespacesAtBeginningAndEnd' - The
Pattern constraint failed.

记事本++

ERROR: Element 'LightSource', attribute 'name': [facet 'minLength'] The value '' has a length of '0'; this underruns the allowed minimum length of '1'.
ERROR: Element 'LightSource', attribute 'name': [facet 'pattern'] The value '' is not accepted by the pattern '.*\S'.
ERROR: Element 'LightSource', attribute 'name': '' is not a valid value of the atomic type 'TNonEmptyStringNoWhitespacesAtBeginningAndEnd'.

利用异常内容提供的信息,我可以检索XML元素并显示它,但是说TNonEmptyStringNoWhitespacesAtBeginningAndEnd失败的约束比告诉我细节失败的部分要少得多。我知道我得到了提示,模式约束失败但任何获得此类消息的人都需要找到类型并检查其约束以获得有关约束的知识。通过检查异常中的数据,这似乎是详细程度。

XML Tools插件似乎能够公开每个验证项目并提供更多细节。这不仅仅是从XSD中推断出来的,而是看起来像是通过每个约束的处理步骤获得的信息。

我所希望的是一种增加验证器详细程度以获取更多信息的方法。

1 个答案:

答案 0 :(得分:4)

Re:行号...对于XDocument,如果启用行信息捕获

XDocument xdoc = XDocument.Load(reader, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo | LoadOptions.SetBaseUri);

然后您的验证处理程序会在您发布的ValidationEventHandlercode(IXmlLineInfo)中提取类似的内容:

IXmlLineInfo node = sender as IXmlLineInfo;
if (node != null && node.HasLineInfo()) ...

这应该涵盖您想要的信息......

对于传统DOM,您可以选择检查Exception属性(至少提供LineNumberLinePosition),至少在理论上,通过Exception属性,您也可以获得SchemaObjectProperty。在我的所有代码中,我使用的是XDocument,这确实可行。

这应该让你开始至少在行/位置方面提供一个更好的位置(即使它在内存中也可以工作)。

(基于修改过的问题的更新)

C#不会为您提供您所看到的插件所看到的内容......对我而言,这是一个实现选择。 XSD方面协同工作;因此,任何失败都会认为整个无效。

.NET的内置XSD验证器是一个通用的,没有太多的验证调整(唯一的一个是做或不做独特的粒子归因)。为了平衡性能,上述情况适用于简单类型验证。

该插件似乎是为交互性而设计的...它似乎想要尽可能多地分辨它,无论它需要什么......