【问题标题】:XML Validation against XSD always returns true针对 XSD 的 XML 验证始终返回 true
【发布时间】:2016-01-29 22:36:03
【问题描述】:

我有一个 C# 脚本,它根据 XSD 文档验证 XML 文档,如下所示:

    static bool IsValidXml(string xmlFilePath, string xsdFilePath)
    {

        XmlReaderSettings settings = new XmlReaderSettings();
        settings.Schemas.Add(null, xsdFilePath);
        settings.ValidationType = ValidationType.Schema;
        settings.Schemas.Compile();

        try
        {
            XmlReader xmlRead = XmlReader.Create(xmlFilePath, settings);
            while (xmlRead.Read())
            { };
            xmlRead.Close();
        }
        catch (Exception e)
        {
            return false;
        }

        return true;
    }

在查看了许多 MSDN 文章和问题后,我已经编译了这里的解决方案。它确实正确地验证了 XSD 的格式是否正确(如果我弄乱了文件,则返回 false)并检查 XML 的格式是否正确(弄乱时也返回 false)。

我也尝试了以下方法,但效果完全相同:

    static bool IsValidXml(string xmlFilePath, string xsdFilePath)
    {

        XDocument xdoc = XDocument.Load(xmlFilePath);
        XmlSchemaSet schemas = new XmlSchemaSet();
        schemas.Add(null, xsdFilePath);

        try
        {
            xdoc.Validate(schemas, null);
        }
        catch (XmlSchemaValidationException e)
        {
            return false;
        }

        return true;
    }

我什至从互联网上提取了一个完全随机的 XSD 并将其放入两个脚本中,并且它仍然可以在两个脚本中验证。我在这里错过了什么?

在 SSIS 作业中使用 .NET 3.5。

【问题讨论】:

  • 您没有提供任何细节,但如果您使用随机模式验证 XML,那么这可能是意料之中的。如果文档在架构中没有任何匹配的元素,您将得到的最好的结果是警告。
  • 检查 XML 文档中的名称空间是否与架构所针对的名称空间相匹配。发布您尝试验证的架构和 xml 文件的示例可能会有所帮助
  • @CharlesMager 看看你现在建议的副本,看起来很有希望,谢谢。

标签: c# xml validation xsd


【解决方案1】:

在 .NET 中,您必须自己检查验证器是否真正匹配架构组件;如果没有,则不会引发异常,因此您的代码将无法按预期工作。

匹配意味着以下一项或两项:

  • 架构集中有一个全局元素,其限定名称与 XML 文档元素的限定名称相同。
  • 文档元素有一个 xsi:type 属性,它是一个限定名称,指向架构集中的全局类型。

在流式传输模式下,您可以轻松地进行此检查。这种伪代码应该会给您一个想法(未显示错误处理等):

using (XmlReader reader = XmlReader.Create(xmlfile, settings))
{
    reader.MoveToContent();
    var qn = new XmlQualifiedName(reader.LocalName, reader.NamespaceURI);
    // element test: schemas.GlobalElements.ContainsKey(qn);
    // check if there's an xsi:type attribute: reader["type", XmlSchema.InstanceNamespace] != null;
    // if exists, resolve the value of the xsi:type attribute to an XmlQualifiedName
    // type test: schemas.GlobalTypes.ContainsKey(qn);
    // if all good, keep reading; otherwise, break here after setting your error flag, etc.
}

您还可以考虑XmlNode.SchemaInfo,它表示作为模式验证的结果已分配给节点的后模式验证信息集。我会测试不同的条件,看看它如何适用于您的场景。建议使用第一种方法来减少 DoS 攻击中的攻击面,因为它是检测完全虚假负载的最快方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-10
    • 2012-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多