使用XSD验证XmlDocument

4

我正在开发一个系统,该系统将通过Web服务接收XML(XmlDocument)。我不会在硬盘上拥有这个XML(XmlDocument),它将在内存中管理。

我有一个XSD文件来验证从WebService接收到的XML(XmlDocument)。我正在尝试做一个示例来验证这个Xml。

我的XML:

<?xml version="1.0"?>
<note>
  <to>Tove</to>
  <from>Jani</from>
  <heading>Reminder</heading>
  <body>Don't forget me this weekend!</body>
</note>

此外,我还有自己的XSD:

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.w3schools.com"
xmlns="http://www.w3schools.com"
elementFormDefault="qualified">
  <xs:element name="note">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="to" type="xs:string"/>
        <xs:element name="from" type="xs:string"/>
        <xs:element name="heading" type="xs:string"/>
        <xs:element name="body" type="xs:int"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

我们可以看到,我将 body 字段设为 int,只是为了模拟错误。

为了尝试获取错误信息,我有以下代码:

//event handler to manage the errors
private static void verifyErrors(object sender, ValidationEventArgs args)
{
    if (args.Severity == XmlSeverityType.Warning)
        MessageBox.Show(args.Message);
}

点击按钮后,我有以下操作:

        private void button1_Click(object sender, EventArgs e)
        {

            try
            {
                // my XmlDocument (in this case I will load from hardisk)
                XmlDocument xml = new XmlDocument();
                // load the XSD schema.. is this right?
                xml.Schemas.Add("http://www.w3schools.com", "meuEsquema.xsd");

                // Load my XML from hardisk
                xml.Load("meusDados.xml");

                // event handler to manage the errors from XmlDocument object
                ValidationEventHandler veh = new ValidationEventHandler(verificaErros);

                // try to validate my XML.. and the event handler verifyError will show the error
                xml.Validate(veh);
            }
            catch {
              // do nothing.. just to test
            }
        }

问题在于我将 body 字段更改为 int,但该字段中存在字符串值,而我没有收到错误提示。
2个回答

7
问题出在XML命名空间上。
在你的XSD中,你将targetNamespace=xmlns=都定义为"http://www.w3schools.com":
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://www.w3schools.com"
           xmlns="http://www.w3schools.com"
           elementFormDefault="qualified">

然而,你的XML文档 不包含 任何XML命名空间。

<?xml version="1.0"?>
<note>
  <to>Tove</to>
  <from>Jani</from>
  <heading>Reminder</heading>
  <body>Don't forget me this weekend!</body>
</note>

基本上,该XSD根本没有验证此XML。
您需要从XSD中删除这些命名空间:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           elementFormDefault="qualified">

或者,您可以将XSD中定义的默认XML命名空间(没有前缀)添加到您的XML中:

<?xml version="1.0"?>
<note xmlns="http://www.w3schools.com">
  <to>Tove</to>
  <from>Jani</from>
  <heading>Reminder</heading>
  <body>Don't forget me this weekend!</body>
</note>

如果你的XSD中有XML命名空间,那么它们也必须存在于XML中 - 反之亦然。
一旦你执行其中一个解决方案,你应该会得到类似以下的验证错误:
Validation error: The 'body' element is invalid - The value 'Don't forget me this weekend!' is invalid according to its datatype
'http://www.w3.org/2001/XMLSchema:int' - The string 'Don't forget me this weekend!' is not a valid Int32 value.

嗨Marc,我尝试添加命名空间但没有成功。我的命名空间是:<note xmlns:xsi="http://www.w3.org/2001/XMLSchema" xsi:noNamespaceSchemaLocation="./Schema.xsd"> 我做错了什么? - Dan
@Dan:请使用我在回复中发布的版本:<note xmlns="http://www.w3schools.com"> - marc_s
你好 @marc_s。你能用 PayPal 帮我解决这个问题并支付 10 美元吗?我真的不知道出了什么错误。我知道你是自愿来这里帮忙的,但我是一个 C# 的新手程序员,现在还在学习 XML。谢谢, 丹 - Dan
@Dan:给我发一封电子邮件-查看我的个人资料-我会尝试通过电子邮件提供帮助,这可能比在这里更容易和更有效。 - marc_s

0

我希望我能在这里帮到您。我遇到了类似的问题(有关 Xml 的误报)。

在我的特定情况下,我发现了两个错误,其中一个可能是相关的。您必须通过XmlReaderSettings选择各种 Xml 验证。以下是一个简单的用法(摘自上面的邮件)

string schemaFileName = @"sampleSchema.xsd"; 
string xmlFileName = @"sampleXml.xml"; 
XmlReaderSettings settings = new XmlReaderSettings 
{ 
    ValidationType = ValidationType.Schema, 
    ValidationFlags =  
        XmlSchemaValidationFlags.ProcessInlineSchema | 
        XmlSchemaValidationFlags.ProcessSchemaLocation |  
        XmlSchemaValidationFlags.ReportValidationWarnings, 
}; 
settings.Schemas.Add (schema); 
settings.ValidationEventHandler +=  
    (o, e) => { throw new Exception("CRASH"); }; 

XmlSchema schema =  
    XmlSchema.Read ( 
    File.OpenText (schemaFileName),  
    (o, e) => { throw new Exception ("BOOM"); }); 

// obviously you don't need to read Xml from file, 
// just skip the load bit and supply raw DOM object
XmlReader reader = XmlReader.Create (xmlFileName, settings); 
while (reader.Read ()) { } 

1
这并不会解决真正的问题 - XSD 中定义的 XML 命名空间在 XML 中不存在..... - marc_s

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