根据 C # 中引用的 XSD 验证 XML

我有一个具有指定模式位置的 XML 文件,如下所示:

xsi:schemaLocation="someurl ..\localSchemaPath.xsd"

我想在 C # 中验证。当我打开文件时,VisualStudio 根据架构验证它并完美地列出错误。然而,不知怎么的,我似乎不能在 C # 中自动验证它,除非指定要验证的模式,比如:

XmlDocument asset = new XmlDocument();


XmlTextReader schemaReader = new XmlTextReader("relativeSchemaPath");
XmlSchema schema = XmlSchema.Read(schemaReader, SchemaValidationHandler);


asset.Schemas.Add(schema);


asset.Load(filename);
asset.Validate(DocumentValidationHandler);

我是否应该能够使用 XML 文件中指定的模式自动进行验证?我错过了什么?

259195 次浏览

我曾经在 VB 中做过这种自动验证,我是这样做的(转换成 C #) :

XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags = settings.ValidationFlags |
Schema.XmlSchemaValidationFlags.ProcessSchemaLocation;
XmlReader XMLvalidator = XmlReader.Create(reader, settings);

然后,我在读取文件时订阅了 settings.ValidationEventHandler事件。

您需要创建一个 XmlReaderSettings 实例,并在创建时将其传递给 XmlReader。然后可以在设置中订阅 ValidationEventHandler以接收验证错误。您的代码最终将如下所示:

using System.Xml;
using System.Xml.Schema;
using System.IO;


public class ValidXSD
{
public static void Main()
{


// Set the validation settings.
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);


// Create the XmlReader object.
XmlReader reader = XmlReader.Create("inlineSchema.xml", settings);


// Parse the file.
while (reader.Read()) ;


}
// Display any warnings or errors.
private static void ValidationCallBack(object sender, ValidationEventArgs args)
{
if (args.Severity == XmlSeverityType.Warning)
Console.WriteLine("\tWarning: Matching schema not found.  No validation occurred." + args.Message);
else
Console.WriteLine("\tValidation error: " + args.Message);


}
}

下面的 例子验证 XML 文件并生成适当的错误或警告。

using System;
using System.IO;
using System.Xml;
using System.Xml.Schema;


public class Sample
{


public static void Main()
{
//Load the XmlSchemaSet.
XmlSchemaSet schemaSet = new XmlSchemaSet();
schemaSet.Add("urn:bookstore-schema", "books.xsd");


//Validate the file using the schema stored in the schema set.
//Any elements belonging to the namespace "urn:cd-schema" generate
//a warning because there is no schema matching that namespace.
Validate("store.xml", schemaSet);
Console.ReadLine();
}


private static void Validate(String filename, XmlSchemaSet schemaSet)
{
Console.WriteLine();
Console.WriteLine("\r\nValidating XML file {0}...", filename.ToString());


XmlSchema compiledSchema = null;


foreach (XmlSchema schema in schemaSet.Schemas())
{
compiledSchema = schema;
}


XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add(compiledSchema);
settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);
settings.ValidationType = ValidationType.Schema;


//Create the schema validating reader.
XmlReader vreader = XmlReader.Create(filename, settings);


while (vreader.Read()) { }


//Close the reader.
vreader.Close();
}


//Display any warnings or errors.
private static void ValidationCallBack(object sender, ValidationEventArgs args)
{
if (args.Severity == XmlSeverityType.Warning)
Console.WriteLine("\tWarning: Matching schema not found.  No validation occurred." + args.Message);
else
Console.WriteLine("\tValidation error: " + args.Message);


}
}

前面的示例使用以下输入文件。

<?xml version='1.0'?>
<bookstore xmlns="urn:bookstore-schema" xmlns:cd="urn:cd-schema">
<book genre="novel">
<title>The Confidence Man</title>
<price>11.99</price>
</book>
<cd:cd>
<title>Americana</title>
<cd:artist>Offspring</cd:artist>
<price>16.95</price>
</cd:cd>
</bookstore>

Books.xsd

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="urn:bookstore-schema"
elementFormDefault="qualified"
targetNamespace="urn:bookstore-schema">


<xsd:element name="bookstore" type="bookstoreType"/>


<xsd:complexType name="bookstoreType">
<xsd:sequence maxOccurs="unbounded">
<xsd:element name="book"  type="bookType"/>
</xsd:sequence>
</xsd:complexType>


<xsd:complexType name="bookType">
<xsd:sequence>
<xsd:element name="title" type="xsd:string"/>
<xsd:element name="author" type="authorName"/>
<xsd:element name="price"  type="xsd:decimal"/>
</xsd:sequence>
<xsd:attribute name="genre" type="xsd:string"/>
</xsd:complexType>


<xsd:complexType name="authorName">
<xsd:sequence>
<xsd:element name="first-name"  type="xsd:string"/>
<xsd:element name="last-name" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>


</xsd:schema>

如果使用.NET 3.5,一种更简单的方法是使用 XDocumentXmlSchemaSet验证。

XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add(schemaNamespace, schemaFileName);


XDocument doc = XDocument.Load(filename);
string msg = "";
doc.Validate(schemas, (o, e) => {
msg += e.Message + Environment.NewLine;
});
Console.WriteLine(msg == "" ? "Document is valid" : "Document invalid: " + msg);

请参阅 MSDN 文档获得更多帮助。

就我个人而言,我更倾向于不用回调就进行验证:

public bool ValidateSchema(string xmlPath, string xsdPath)
{
XmlDocument xml = new XmlDocument();
xml.Load(xmlPath);


xml.Schemas.Add(null, xsdPath);


try
{
xml.Validate(null);
}
catch (XmlSchemaValidationException)
{
return false;
}
return true;
}

(见 Timiz0r 在 同步 XML 模式验证? . NET 3.5中的文章)