是否可以添加新的XML标签以便它对XSD验证是透明的?

问题描述:

A具有描述XML对象(简化的示例)的XSD架构:是否可以添加新的XML标签以便它对XSD验证是透明的?

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      targetNamespace="http://my-custom-ns.com"> 
    <xs:element name="item"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element name="active" type="xs:boolean"/> 
       <xs:element name="value" type="xs:string"/> 
      </xs:sequence> 
     </xs:complexType> 
    </xs:element> 
</xs:schema> 

即模式是内置在一个应用程序作为资源和安装在许多工作站。 该应用程序使用XML文件并根据此架构验证它们。 这里就是这样一个XML的(简体)例如:

<my:item xmlns:my="http://my-custom-ns.com"> 
    <active>true</active> 
    <value>foo</value> 
</my:item> 

现在,我想我的XML文件,而无需改变XSD得到一个新的元素(新标签):

<my:item xmlns:my="http://my-custom-ns.com"> 
    <active>true</active> 
    <value>foo</value> 
    <tag>bar</tag> 
</my:item> 

我不会改变XSD,所以很明显,验证会在新标签上失败。 有没有办法让XML中有一个新的标签,以便它透明地“通过”验证(即完全忽略)?

我尝试添加在希望XSD验证会忽略它的XML一个新的命名空间,但是这并没有帮助:

<my:item xmlns:my="http://my-custom-ns.com" xmlns:new="http://new-ns.com"> 
    <active>true</active> 
    <value>foo</value> 
    <new:tag>bar</new:tag> 
</my:item> 

的背景是:它应该对当前的应用程序成为可能版本来处理具有附加标签的XML文件,简单地忽略它。但是,如上所述,该应用程序对XSD有很强的验证。也许有另一种方法来做到这一点?

+0

如果应用程序位于不同的名称空间中,应用程序如何查看该新项目?我相信如果没有架构修改,这是不可能的。 –

+0

@AlexeyR,命名空间只是一个(不幸的)例子。实际上,我需要一种方法,使标签对XSD验证完全透明,而不会明确允许* undefined *标签。恐怕似乎是不可能的。 – dymanoid

是的,没有。如果原始模式有一个特殊的标签,有一种方法可以实现这一点。

如果你事先知道文件可能有额外的元素,但你不提前知道这些元素,那么模式可以以向前兼容的方式使用xs:any标签设计,就像这样:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://my-custom-ns.com"> 
    <xs:element name="item"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element name="active" type="xs:boolean"/> 
       <xs:element name="value" type="xs:string"/> 
       <xs:any namespace="##other" processContents="lax" minOccurs="0"/> 
      </xs:sequence> 
     </xs:complexType> 
    </xs:element> 
</xs:schema> 

这份文件是针对上述模式是有效的:

<my:item xmlns:my="http://my-custom-ns.com" xmlns:new="http://new-ns.com"> 
    <active>true</active> 
    <value>foo</value> 
</my:item> 

还有这样一条:

<my:item xmlns:my="http://my-custom-ns.com" xmlns:new="http://new-ns.com"> 
    <active>true</active> 
    <value>foo</value> 
    <new:tag>bar</new:tag> 
</my:item> 

可以通过更改namespaceprocessContents属性的值来调整xs:any的行为。

但是,如果模式已经完成,并且超出了您的控制范围,那么额外的元素只有在原始设计者允许的情况下才会出现。

一个例子是... XML Schema本身。 XML Schema元素可能包含外部名称空间中的任意属性(几种标准是以这种方式构建在XML Schema上的),这是因为Schema的XML Schema明确允许其他名称空间中的属性。

+0

是的,我想过使用'xs:any'模式元素。但不幸的是,该模式已经在目标机器上,并且不升级应用程序版本就无法更改(由于特殊原因这是不可能的)。显然,原始的模式设计者不允许使用额外的元素...... – dymanoid

另一个答案是重构XML实例。 XML Schema允许在更大的实例中嵌套经过模式验证的XML(无需修改)。

<new:wrapper xmlns:my="http://my-custom-ns.com" xmlns:new="http://new-ns.com"> 
    <my:item> 
    <active>true</active> 
    <value>foo</value> 
    </my:item> 
    <new:tag>bar</new:tag> 
</new:wrapper> 

这可以通过导入前者和引用元素my:item的新模式来实现。

只要嵌套XML严格验证它,前面的模式不需要任何修改。

+0

那么,如果我可以将新模式提供给应用程序用户,那将是可能的。但不幸的是,由于特殊原因,应用程序版本无法升级,所以我坚持使用旧版本。 – dymanoid