Schema验证XML

9

我有一个XSD文件和一个XML文件,如何检查XML是否符合XSD文件的正确模式?

我知道在XmlDocument类中有一个验证函数,但它需要一个事件处理程序,而我只需要true或false。

附注:我正在使用Visual Studio 2010。

3个回答

24

有一种更简单的方法:

private void ValidationCallBack(object sender, ValidationEventArgs e)
{  
    throw new Exception();
}

public bool validate(string sxml)
{
    try
    {
        XmlDocument xmld=new XmlDocument ();
        xmld.LoadXml(sxml);
        xmld.Schemas.Add(null,@"c:\the file location");
        xmld.validate(ValidationCallBack);
        return true;
    }
    catch
    {
        return false;
    }
}

附言:我没有在VS中编写这段代码,因此可能会出现大小写不正确的单词,但是这段代码可以正常工作!


与其他解决方案相比,这个非常简单易用,谢谢! - JBeagle

3
您可以使用XmlReaderSettings类和Create方法创建一个验证的XmlReader实例。

private bool ValidateXml(string xmlFilePath, string schemaFilePath, string schemaNamespace, Type rootType)
{
    XmlSerializer serializer = new XmlSerializer(rootType);

    using (var fs = new StreamReader(xmlFilePath, Encoding.GetEncoding("iso-8859-1")))
    {
        object deserializedObject;
        var xmlReaderSettings = new XmlReaderSettings();
        if (File.Exists(schemaFilePath))
        {
            //select schema for validation  
            xmlReaderSettings.Schemas.Add(schemaNamespace, schemaPath); 
            xmlReaderSettings.ValidationType = ValidationType.Schema;
            try
            {
            using (var xmlReader = XmlReader.Create(fs, xmlReaderSettings))
            {                
                if (serializer.CanDeserialize(xmlReader))
                {
                    return true;
                    //deserializedObject = serializer.Deserialize(xmlReader);
                }
                else
                {
                    return false;
                }
            }
            }
            catch(Exception ex)
            { return false; }
        }
    }
}

以上代码将在模式无效或无法反序列化XML时抛出异常。rootType是等效类层次结构中根元素的类型。

例子: XML Schema 教程中的模式。将文件保存为D:\SampleSchema.xsd

运行xsd.exe

  1. 打开“开始菜单>所有程序>Microsoft Visual Studio 2010>Visual Studio工具>Visual Studio 2010命令提示符”
  2. 在命令提示符中,键入:xsd.exe /c /out:D:\"D:\SampleSchema.xsd"
  3. xsd选项:/out选项用于指定输出目录,/c用于指定生成类的工具
  4. 输出类层次结构位于D:\SampleSchema.cs
  5. 生成的类层次结构看起来像这样,

//------------------------------------------------------------------------------
// 
//     This code was generated by a tool.
//     Runtime Version:2.0.50727.4952
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// 
//------------------------------------------------------------------------------

using System.Xml.Serialization;

// 
// This source code was auto-generated by xsd, Version=2.0.50727.3038.
// 


/// 
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class note {

    private string toField;

    private string fromField;

    private string headingField;

    private string bodyField;

    /// 
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string to {
        get {
            return this.toField;
        }
        set {
            this.toField = value;
        }
    }

    /// 
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string from {
        get {
            return this.fromField;
        }
        set {
            this.fromField = value;
        }
    }

    /// 
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string heading {
        get {
            return this.headingField;
        }
        set {
            this.headingField = value;
        }
    }

    /// 
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string body {
        get {
            return this.bodyField;
        }
        set {
            this.bodyField = value;
        }
    }
}

将该类添加到Visual Studio项目中。
对于上面的XSD示例,根类是note
调用该方法,

bool isXmlValid = ValidateXml(@"D:\Sample.xml", 
                              @"D:\SampleSchema.xsd", 
                              @"http://www.w3.org/2001/XMLSchema", 
                              typeof(note));

更多信息:


1
这不会验证任何内容,因为没有设置ValidationFlags。这只是反序列化xml。 - Steven K.
我应该输入什么作为rootType? - aharon
rootType 是从 xsd 文件创建的类模型的根元素类型。例如,如果您使用 .NET 的 xsd.exe 工具创建一个类模型,则类型将为“Product”(对于 @Steven 给出的示例 xsd)。 - Devendra D. Chavan
使用.NET的xsd工具创建类层次结构。例如,如果模式文件位于“D:\ testSchema.xsd”,则工具使用应为> xsd / c / out:D:\“D:\ testSchema.xsd”。这是一个命令行工具。更多信息请参见:http://msdn.microsoft.com/en-us/library/x6c1kb0s%28v=VS.100%29.aspx - Devendra D. Chavan
啊?这跟类型有什么关系?我应该怎么写类型呢? - aharon

1
你可以像这样做。
public class XmlValidator
{
    private bool _isValid = true;

    public bool Validate(string xml)
    {
        _isValid = true;

        // Set the validation settings as needed.
        var settings = new XmlReaderSettings { ValidationType = ValidationType.Schema };
        settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
        settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
        settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
        settings.ValidationEventHandler += ValidationCallBack;

        var reader = XmlReader.Create(new StringReader(xml), settings);

        while(reader.Read())
        {
            // process the content if needed
        }

        return _isValid;
    }

    private void ValidationCallBack(object sender, ValidationEventArgs e)
    {
        // check for severity as needed
        if(e.Severity == XmlSeverityType.Error)
        {
            _isValid = false;
        }
    }
}

class Program
{

    static void Main(string[] args)
    {
        var validator = new XmlValidator();

        var result =
            validator.Validate(@"<?xml version=""1.0""?>
                 <Product ProductID=""1"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:noNamespaceSchemaLocation=""schema.xsd"">
                     <ProductName>Chairs</ProductName>
                 </Product>");

}

架构。

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <xsd:element name="Product">
      <xsd:complexType>
         <xsd:sequence>
            <xsd:element name="ProductName" type="xsd:string"/>
         </xsd:sequence>
         <xsd:attribute name="ProductID" use="required" type="xsd:int"/>
      </xsd:complexType>
   </xsd:element>
</xsd:schema>

我怎样才能在不输入整个 XML 到函数调用中的情况下完成它?"while" 循环应该做什么?函数如何使用方案? - aharon
你可以将路径传递给 Validate 函数,并使用 'var reader = XmlReader.Create(path, settings);' 而不是 'var reader = XmlReader.Create(new StringReader(xml), settings);' - Steven K.
好的。但是“while”循环应该做什么?函数如何使用方案? - aharon
while循环解析xml文档,并在此过程中验证xml。xml包含对模式的引用:<Product ProductID = ""1"" xmlns:xsi = ""http://www.w3.org/2001/XMLSchema-instance"" xsi:noNamespaceSchemaLocation = ""schema.xsd"">。 - Steven K.
a. 在 while 循环中需要编写什么代码? b. 如果代码中没有对模式的引用,而是在属性中,那么它能正常工作吗? - aharon
a: 没有什么,你可以像这样留下它:while(reader.Read()); b: 当模式位于执行目录中并且像这样被引用:<Product xmlns:xsi="w3.org/2001/XMLSchema-instance"; xsi:noNamespaceSchemaLocation="schema.xsd"> 那么它将起作用。 - Steven K.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接