需要帮助在C#中针对XSD验证XML

时间:2022-05-15 17:17:19

I'm writing a WPF application that requires XML files to be validated. I have the following class to validate XML against one or more XSD files:

我正在编写一个需要验证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;
        }
    }
}

The above code is open-source and can be found here. Now, it is called like so:

上面的代码是开源的,可以在这里找到。现在,它被称为:

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++;
        }
    }
}

In my testing of the XSD validation, I'm using 4 XML files: one of them, books.xml, corresponds to the hard-coded schema books.xsd. The other three are random XML files I pulled from other sources, and I have verified that they are not valid against books.xsd. However, upon running the code, ValidatedXMLFiles shows a value of 4 instead of 1.

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

I've verified as much as I can think of from the XSDValidator class; I tried manually adding a random string to Errors, and IsValid returned false in that case. One thing that I thought was interesting was, when I tried changing the schema file name to something that doesn't exist, a TargetInvocationException was thrown instead of the FileNotFoundException that I expected. I don't know if that means anything, but that's the only strange behavior I've seen. Can anyone provide any assistance?

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

1 个解决方案

#1


0  

You are assuming that the validation engine will automotically know to use the books.xsd schema to validate all the xml files.

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

This is not correct. The xml needs to tell the validator which XSD it is supposed to be validated against.

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

To indicate this you set the xmlns attribute in your xml document.

要指明这一点,请在xml文档中设置xmlns属性。

For example:

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

And the schema:

架构:

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

Otherwise the only criteria for the XML to be "valid" is that it's well formed.

否则,XML“有效”的唯一标准就是它的形成良好。

#1


0  

You are assuming that the validation engine will automotically know to use the books.xsd schema to validate all the xml files.

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

This is not correct. The xml needs to tell the validator which XSD it is supposed to be validated against.

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

To indicate this you set the xmlns attribute in your xml document.

要指明这一点,请在xml文档中设置xmlns属性。

For example:

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

And the schema:

架构:

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

Otherwise the only criteria for the XML to be "valid" is that it's well formed.

否则,XML“有效”的唯一标准就是它的形成良好。