问题描述
我正在编写一个需要验证 XML 文件的 WPF 应用程序.我有以下类来针对一个或多个 XSD 文件验证 XML:
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:
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++;
}
}
}
在我对 XSD 验证的测试中,我使用了 4 个 XML 文件:其中之一,books.xml
,对应于硬编码模式 books.xsd
.其他三个是我从其他来源提取的随机 XML 文件,我已经验证它们对 books.xsd
无效.但是,在运行代码时,ValidatedXMLFiles
显示的值为 4 而不是 1.
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.
我已经从 XSDValidator
类中验证了我能想到的所有内容;我尝试手动向 Errors
添加一个随机字符串,在这种情况下 IsValid
返回 false.我认为有趣的一件事是,当我尝试将架构文件名更改为不存在的名称时,抛出了 TargetInvocationException
而不是我期望的 FileNotFoundException
.我不知道这是否意味着什么,但这是我见过的唯一奇怪的行为.任何人都可以提供任何帮助吗?
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?
推荐答案
您假设验证引擎将自动知道使用 books.xsd 架构来验证所有 xml 文件.
You are assuming that the validation engine will automotically know to use the books.xsd schema to validate all the xml files.
这是不正确的.xml 需要告诉验证器它应该针对哪个 XSD 进行验证.
This is not correct. The xml needs to tell the validator which XSD it is supposed to be validated against.
为了表明这一点,您在 xml 文档中设置了 xmlns 属性.
To indicate this you set the xmlns attribute in your xml document.
例如:
<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 是否有效"的唯一标准就是格式正确.
Otherwise the only criteria for the XML to be "valid" is that it's well formed.
这篇关于需要帮助在 C# 中针对 XSD 验证 XML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!