0

我正在编写一个需要验证 XML 文件的 WPF 应用程序。我有以下类来针对一个或多个 XSD 文件验证 XML:

public class XSDValidator
{
    public List<XmlSchema> Schemas { get; set; }
    public List<String> Errors { get; set; }
    public List<String> Warnings { get; set; }

    public XSDValidator()
    {
        Schemas = new List<XmlSchema>();
    }

    /// <summary>
    /// Add a schema to be used during the validation of the XML document
    /// </summary>
    /// <param name="schemaFileLocation">The file path for the XSD schema file to be added for validation</param>
    /// <returns>True if the schema file was successfully loaded, else false (if false, view Errors/Warnings for reason why)</returns>
    public bool AddSchema(string schemaFileLocation)
    {
        // Reset the Error/Warning collections
        Errors = new List<string>();
        Warnings = new List<string>();

        XmlSchema schema;

        if (!File.Exists(schemaFileLocation))
        {
            throw new FileNotFoundException("The specified XML file does not exist", schemaFileLocation);
        }

        using (var fs = new FileStream(schemaFileLocation, FileMode.Open))
        {
            schema = XmlSchema.Read(fs, ValidationEventHandler);
        }

        var isValid = !Errors.Any() && !Warnings.Any();

        if (isValid)
        {
            Schemas.Add(schema);
        }

        return isValid;
    }

    /// <summary>
    /// Perform the XSD validation against the specified XML document
    /// </summary>
    /// <param name="xmlLocation">The full file path of the file to be validated</param>
    /// <returns>True if the XML file conforms to the schemas, else false</returns>
    public bool IsValid(string xmlLocation)
    {
        if (!File.Exists(xmlLocation))
        {
            throw new FileNotFoundException("The specified XML file does not exist", xmlLocation);
        }

        using (var xmlStream = new FileStream(xmlLocation, FileMode.Open))
        {
            return IsValid(xmlStream);
        }
    }

    /// <summary>
    /// Perform the XSD validation against the supplied XML stream
    /// </summary>
    /// <param name="xmlStream">The XML stream to be validated</param>
    /// <returns>True is the XML stream conforms to the schemas, else false</returns>
    private bool IsValid(Stream xmlStream)
    {
        // Reset the Error/Warning collections
        Errors = new List<string>();
        Warnings = new List<string>();

        var settings = new XmlReaderSettings
        {
            ValidationType = ValidationType.Schema
        };
        settings.ValidationEventHandler += ValidationEventHandler;

        foreach (var xmlSchema in Schemas)
        {
            settings.Schemas.Add(xmlSchema);
        }

        var xmlFile = XmlReader.Create(xmlStream, settings);

        while (xmlFile.Read()) { }

        return !Errors.Any() && !Warnings.Any();
    }

    private void ValidationEventHandler(object sender, ValidationEventArgs e)
    {
        switch (e.Severity)
        {
            case XmlSeverityType.Error:
                Errors.Add(e.Message);
                break;
            case XmlSeverityType.Warning:
                Warnings.Add(e.Message);
                break;
        }
    }
}

上面的代码是开源的,可以在这里找到。现在,它是这样调用的:

var validator = new XSDValidator();
validator.AddSchema(@"C:\code\xml\books.xsd");

foreach (CheckableListItem file in FileFullPathChecklist)
{
    if (file.IsChecked)
    {
        if (validator.IsValid(file.Filename)) 
        {
            ValidatedXMLFiles++;
        }
    }
}

在我对 XSD 验证的测试中,我使用了 4 个 XML 文件:其中一个books.xml,对应于硬编码模式books.xsd。其他三个是我从其他来源提取的随机 XML 文件,我已经验证它们对books.xsd. 但是,在运行代码时,ValidatedXMLFiles显示的值为 4 而不是 1。

我已经在XSDValidator课堂上尽可能多地验证了;我尝试手动将随机字符串添加到Errors,并IsValid在这种情况下返回 false 。我认为有趣的一件事是,当我尝试将模式文件名更改为不存在的东西时,TargetInvocationException抛出了 a 而不是FileNotFoundException我预期的。我不知道这是否意味着什么,但这是我见过的唯一奇怪的行为。任何人都可以提供任何帮助吗?

4

1 回答 1

0

您假设验证引擎将自动知道使用 books.xsd 模式来验证所有 xml 文件。

这是不正确的。xml 需要告诉验证器应该针对哪个 XSD 进行验证。

为了表明这一点,您在 xml 文档中设置了 xmlns 属性。

例如:

<MyXml xmlns="http://MySchemaNamespace">
    ...
</MyXml>

和架构:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
           targetNamespace="http://MySchemaNamespace" 
           xmlns="http://MySchemaNamespace" 
           elementFormDefault="qualified">
    ...
</xs:schema>

否则,XML“有效”的唯一标准是格式正确。

于 2013-10-08T13:02:35.187 回答