【问题标题】:XmlDocument.Validate does not check for an invalid namespaceXmlDocument.Validate 不检查无效的命名空间
【发布时间】:2011-12-15 14:07:31
【问题描述】:

我使用以下代码根据 XSD 文件验证 XML 文件。当发现错误并且 XML 文件中 xmlns 的值有效时,它会成功调用验证处理程序。当它无效时,不会调用验证处理程序。

private void ui_validate_Click(object sender, EventArgs e)
{
    try
    {
        ui_output.Text = "";

        XmlDocument xml_document = new XmlDocument();
        xml_document.LoadXml(ui_XML.Text);
        xml_document.Schemas.Add(null, XmlReader.Create(new System.IO.StringReader(ui_XSD.Text)));
        xml_document.Validate(validation_handler);
    }
    catch (Exception ex)
    {
        ui_output.Text = "Exception: " + ex.Message;
    }
}

private void validation_handler(object sender, ValidationEventArgs e)
{
    switch (e.Severity)
    {
        case XmlSeverityType.Error:
            ui_output.Text += "Error: " + e.Message + Environment.NewLine;
            break;
        case XmlSeverityType.Warning:
            ui_output.Text += "Warning: " + e.Message + Environment.NewLine;
            break;
    }
}

更新 已接受答案的示例:

XmlDocument xml_document = new XmlDocument();
xml_document.Load(@"C:\temp\example.xml");
xml_document.Schemas.Add(null, @"C:\temp\example.xsd");
xml_document.Schemas.Compile();

XmlQualifiedName xml_qualified_name = new XmlQualifiedName(xml_document.DocumentElement.LocalName, xml_document.DocumentElement.NamespaceURI);
bool valid_root = xml_document.Schemas.GlobalElements.Contains(xml_qualified_name);

【问题讨论】:

    标签: .net xml xsd xml-namespaces


    【解决方案1】:

    我处理这个问题的方法是首先实际检查文档元素(根元素)在您的XmlReaderSettings.Schemas 中有一个 XmlSchemaElement;如果没有,您将无法运行验证,这就是您不会收到错误的原因。

    所以,请确保您的 XmlSchemaSet is compiled;然后使用LocalNameNamespaceUri 构建XmlQualifiedName;使用它来查找XmlSchemaElement,使用GlobalElements

    只有在 i) 您的架构编译成功并且 ii) 您确实有文档的根元素的定义时,您才应该尝试验证。

    希望对你有帮助……

    【讨论】:

      【解决方案2】:

      如果文档中根元素的命名空间与架构的目标命名空间不匹配,则验证器无法找到包含根元素(或任何元素,很可能)定义的架构。这意味着验证器不能报告无效结构,因为它不知道正确的结构。在这种情况下,验证器通常可以跳过验证、执行宽松的验证(仅验证找到了架构定义的元素)或发出有关未找到架构定义的警告。

      快速想到您至少有两个选择:1)从文档中读取命名空间并使用单独的检查来验证它是否正确或 2)检查是否有可能通过更改验证器的设置来更改其行为以便它会通知未找到给定命名空间的定义。

      【讨论】:

        【解决方案3】:

        @PetruGardea - 非常感谢您的回答!!!

        我只是在这里放了一些代码来演示您的解决方案,这样其他人就不必谷歌了:

        var doc = new XmlDocument();
        var set = new XmlSchemaSet();
        
        var xsdString = @"<xs:schema
          xmlns=""http://www.sample.ru/system""
          targetNamespace=""http://www.sample.ru/system""
          xmlns:xs=""http://www.w3.org/2001/XMLSchema""
          elementFormDefault=""qualified"">
        
          <xs:element name=""Test"">
            <xs:complexType>
              <xs:sequence>
                <xs:element name=""B"" >
                </xs:element>
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        
        </xs:schema>";
        
        using (var memStream = new MemoryStream())
        {
            var data = Encoding.Default.GetBytes(xsdString);
            memStream.Write(data, 0, data.Length);
            memStream.Position = 0;
            using (var reader = XmlReader.Create(memStream))
            {
                set.Add(@"http://www.sample.ru/system", reader);
            }
        }
        
        //doc.LoadXml(@"<a1:Test xmlns:a1=""http://www.sample.ru/system""><a1:B /></a1:Test>"); // valid xml - no errors
        //doc.LoadXml(@"<a1:Test xmlns:a1=""http://www.sample.ru/system""><a1:B1 /></a1:Test>"); // invalid xml - error about B1
        doc.LoadXml(@"<a1:Test xmlns:a1=""http://www.sample.ru/system1""><a1:B1 /></a1:Test>"); // invalid xml with bad namespace - error about namespace
        //doc.LoadXml(@""); // no need to worry that doc.FirstChild is null - in this case this line throws exception
        
        doc.Schemas.Add(set);
        
        // !!!! you need to add this code to check for wrong namespace !!!! 
        var baseUri = doc.FirstChild.NamespaceURI;
        if (!doc.Schemas.Contains(baseUri))
        {
            Console.WriteLine("Error: there is not xsd to validate this document (uri = {0})", baseUri);
        }
        
        // the rest of the code just prints validation errors and warnings
        doc.Validate((sender, e) =>
        {
            Console.WriteLine(e.Message);
        });
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-03-12
          • 1970-01-01
          • 2019-02-25
          • 1970-01-01
          • 1970-01-01
          • 2016-12-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多