【问题标题】:How can I force compliance with a given schema in .NET?如何强制遵守 .NET 中的给定架构?
【发布时间】:2013-02-12 10:30:54
【问题描述】:

假设我有一个模式,我希望输入文档遵守该模式。我根据这样的架构加载文件:

// Load the ABC XSD
var schemata = new XmlSchemaSet();
string abcSchema = FooResources.AbcTemplate;
using (var reader = new StringReader(abcSchema))
using (var schemaReader = XmlReader.Create(reader))
{
    schemata.Add(string.Empty, schemaReader);
}

// Load the ABC file itself
var settings = new XmlReaderSettings
{
    CheckCharacters = true,
    CloseInput = false,
    ConformanceLevel = ConformanceLevel.Document,
    IgnoreComments = true,
    Schemas = schemata,
    ValidationType = ValidationType.Schema,
    ValidationFlags = XmlSchemaValidationFlags.ReportValidationWarnings
};

XDocument inputDoc;
try
{
    using (var docReader = XmlReader.Create(configurationFile, settings))
    {
        inputDoc = XDocument.Load(docReader);
    }
}
catch (XmlSchemaException xsdViolation)
{
    throw new InvalidDataException(".abc file format constraint violated.", xsdViolation);
}

这可以很好地检测文件中的琐碎错误。但是,因为 schema 被锁定到一个命名空间,所以像下面这样的文档是无效的,但是会偷偷溜进去:

<badDoc xmlns="http://Foo/Bar/Bax">
  This is not a valid document; but Schema doesn't catch it
  because of that xmlns in the badDoc element.
</badDoc>

我想说只有我拥有架构的命名空间才能通过架构验证。

【问题讨论】:

    标签: c# .net schema xmlreader


    【解决方案1】:

    虽然看起来很愚蠢,但您要查看的内容实际上是在 XmlReaderSettings 对象上:

    settings.ValidationEventHandler += 
        (node, e) => Console.WriteLine("Bad node: {0}", node);
    

    【讨论】:

    • @codekaizen - 哈哈,很公平,这是一个“更好”的例子,虽然我确实喜欢我原来的暗示的惊讶:)
    • 同意,但可能有一些原因(例如,不破坏整个堆栈和解析状态),但由于它几乎不令人惊讶,我希望“愚蠢”这个绰号能够占据所有有责任突出这种扭曲。
    • @codekaizen 你说得太周到了;获得尊重。 :)
    • 这似乎还是让无效文件通过了。但至少有一个通知。不幸的是,这会导致有效案例失败;例如,命名空间 xml 是在 XML 中隐式定义的,因此在文档中对 xml:space 的任何有效使用都无法通过这种方式进行验证。
    • @billy-oneal 哦,设置上有另一个标志,您可以告诉它忽略某些命名空间 - 当我回到我的办公桌时,我会查找它。
    【解决方案2】:

    我最终确定的解决方案是检查根节点是否在我期望的命名空间中。如果不是,那么我会像对待真正的模式验证失败一样对待它:

    // Parse the bits we need out of that file
    var rootNode = inputDoc.Root;
    if (!rootNode.Name.NamespaceName.Equals(string.Empty, StringComparison.Ordinal))
    {
        throw new InvalidDataException(".abc file format namespace did not match.");
    }
    

    【讨论】:

      【解决方案3】:

      【讨论】:

      • 没用。仍然让无效文件通过。相应地更新了示例代码。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-08
      • 1970-01-01
      • 1970-01-01
      • 2011-12-07
      相关资源
      最近更新 更多