2

短篇小说:

我想在代码中使用 XSD 架构验证 XSD 文件(所有 XSD 本身都是 XML),并获得与 Visual Studio 在其(xml 作为文本)编辑器中打开相同 XSD 文件时显示的相同警告或错误。

Visual Studio 在其 xml 编辑器中显示警告(见下文)。

我的问题是,在代码中完成的验证是 100% 成功的。没有警告,什么都没有。我错过了什么?

长篇大论:

XSD 文件根据定义是一个 XML 文件,因此我正在使用针对 W3C xsd 模式的 XML 验证来验证我的自定义 XSD。

这是要验证的 XSD 和 VS 2010 显示的警告:(
单击 img 放大)

XML 警告

为了避免你眯眼,这里有一些警告:

通配符“##any”允许元素“Com.Example.Config:permissionConfig”,并导致内容模型变得不明确。必须形成一个内容模型,以便[... tl;dr]

这是我的自定义 XSD:

<?xml version="1.0" encoding="utf-8" ?>
<xs:schema 
    xmlns:tns="Com.Example.Config" 
    elementFormDefault="qualified" 
    targetNamespace="Com.Example.Config" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:complexType name="Com.Example.Config.PermissionConfigCT" />
  <xs:complexType name="Com.Example.Config.PermissionsCT">
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="unbounded" name="permissionConfig" type="tns:Com.Example.Config.PermissionConfigCT" />

      <!-- next line triggers the warning -->
      <xs:any minOccurs="0" processContents="lax" />

    </xs:sequence>
  </xs:complexType>
</xs:schema>

检查 VS 用于验证的模式(从菜单 XML -> 模式)显示它正在使用:

  • xsdschema.xsd(FWIW,它源自W3C 的 XSD 原始模式没有DTD 部分)
  • xml.xsd(在上一个 xsd 中引用,由一个 relative include

这两个文件都驻留在(在我的机器上)这里:

C:\Program Files (x86)\Microsoft Visual Studio 10.0\xml\Schemas

我将它们都复制到与可执行文件相同的目录中,以便于参考。

为了完整起见,以下是xsdschema.xsd定义其命名空间的方式:

<xs:schema 
  targetNamespace="http://www.w3.org/2001/XMLSchema" 
  blockDefault="#all" 
  elementFormDefault="qualified"  
  xmlns:xs="http://www.w3.org/2001/XMLSchema" 
  xml:lang="EN" version="1.0"
  xmlns:vs="http://schemas.microsoft.com/Visual-Studio-Intellisense">

  <xs:import namespace="http://www.w3.org/XML/1998/namespace"/>

  <xs:complexType name="openAttrs">
  [...]

...所以我继续编写了一些快速验证代码,使用与 VS 相同的 XSD。这是代码:

var configXsdPath = "XMLFile1.xml"; 
  //that's my custom XSD file, don't let the extension fool you

var xmlSchemaForXsdPath = "xsdschema.xsd";

var settings = new XmlReaderSettings
    {
        ValidationType = ValidationType.Schema,
        ValidationFlags = XmlSchemaValidationFlags.ReportValidationWarnings
                        | XmlSchemaValidationFlags.ProcessSchemaLocation
                        | XmlSchemaValidationFlags.ProcessIdentityConstraints
    };


using (var tr = XmlReader.Create(xmlSchemaForXsdPath))
{
    settings.Schemas.Add(XmlSchema.Read(tr, (i_sender, i_args) 
      => {throw new InvalidOperationException(
                 "The validating XSD is itself invalid");} ));
}

settings.ValidationEventHandler += (i_sender, i_args) 
  => { throw new Exception(i_args.Message); };

var reader = XmlReader.Create(configXsdPath, settings);
while (reader.Read())
//parse it all
{ }

...并且没有任何异常弹出...

更新接下来我尝试提供完全无效的 XML:我在自定义 XSD 中的某处添加了这个元素:

<aaa!></aaa>

并且代码给出了预期的错误*:

命名空间“ http://www.w3.org/2001/XMLSchema ”中的元素“模式”具有无效的子元素“aaa”。预期的可能元素列表:名称空间“ http://www.w3.org/2001/XMLSchema ”中的“simpleType、complexType、组、attributeGroup、元素、属性、符号、注释” 。

--

  • 我曾简要说明过添加无效 XML 不会产生任何错误。那是PEBKAC的一个例子。
4

2 回答 2

2

来自Petru Gardea的回答的深刻见解中获得了深刻的见解:仅在验证时将 XSD 视为 XML,因此将其视为 XSD,而不是(或除此之外)!

就这么简单:

var schemas = new XmlSchemaSet();
using (var tr = XmlReader.Create(xsdPath))
{
    schemas.Add(null, tr);
              //null means 'use the target namespace specified in the XSD'
}
//schemas.CompilationSettings.EnableUpaCheck = true; //it's true by default

schemas.Compile();

运行上面的代码会抛出XmlSchemaExceptionVisual Studio 给出的确切描述:

System.Xml.Schema.XmlSchemaException:通配符“##any”允许元素“Com.Example.Config:permissionConfig”,并导致内容模型变得不明确。必须形成一个内容模型,使得在元素信息项序列的验证过程中,直接、间接或隐含地包含在其中的粒子,用于依次尝试验证序列中的每个项目,可以唯一地确定,而无需检查其内容或属性。该项目,并且没有关于序列其余部分中的项目的任何信息。

于 2013-02-19T12:34:51.330 回答
2

简而言之,你试图next line triggers the warning通过验证你的 XSD来实现 - 你的验证器 -W3C xsd schema永远不会工作。这就是所谓的Unique Particle Attribution,这是 XSD 语言无法描述的。问题是,这只是开始;您最终使用的 XSD 功能越多,您提议的验证就越不可靠。

如果您真的想验证 XSD,至少在 .NET 上,请使用XmlSchemaSet。要打开和关闭 UPA 检查,您就是这样做的。

于 2013-02-19T01:03:48.457 回答