我目前正在针对已发布的xml架构,其中原始作者的习惯是将模式分解成多个.xsd文件,但是某些模式文件具有相同的targetNamespace。这是真的“允许”吗?
示例(极简):
File targetNamespace Contents ------------------------------------------------------------ b1.xsd uri:tempuri.org:b complex type "fooType" b2.xsd uri:tempuri.org:b simple type "barType" a.xsd uri:tempuri.org:a imports b1.xsd and b2.xsd definition of root element "foo",that extends "b:fooType" with an attribute of "b:barType"
<?xml version="1.0"?> <foo bar="1" xmlns="uri:tempuri.org:a" xmlns:xs="http://www.w3.org/2001/XMLSchema" />
很久以来,我相信这一切都是正确的,因为Visual Studio显然允许这种架构风格。然而,今天我决定设置一个命令行实用程序来验证xml文件,我选择了xmllint。
当我运行xmllint –schema a.xsd data.xml时,我看到了这个警告:
a.xsd:4: element import: Schemas parser warning : Element ‘{07000}import’:
Skipping import of schema located at ‘b2.xsd’ for the namespace ‘uri:tempuri.org:b’,since this
namespace was already imported with the schema located at ‘b1.xsd’.
b2.xsd的导入被跳过的事实显然导致了这个错误:
a.xsd:9: element attribute: Schemas parser error : attribute decl. ‘bar’,attribute ‘type’:
The QName value ‘{uri:tempuri.org:b}barType’ does not resolve to a(n) simple type definition.
如果xmllint是正确的,那么在我正在努力发布的规范中会出现错误。在那儿? Visual Studio会出错。是吗?
我确实意识到xs:import和xs:include之间的区别。现在,我只是看不到xs:include可以修复的东西,因为:
> b1.xsd和b2.xsd具有相同的targetNamespace
他们在targetNamespace和a.xsd中都有所不同
>他们不(需要)彼此了解
这是原始模式规范的缺陷吗?我开始认为第三个要点是至关重要的。他们彼此不了解的事实是否导致将它们放在不同的命名空间中呢?
b1.xsd:
<?xml version="1.0" encoding="utf-8"?> <xs:schema targetNamespace="uri:tempuri.org:b" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:complexType name="fooType" /> </xs:schema>
b2.xsd:
<?xml version="1.0" encoding="utf-8"?> <xs:schema targetNamespace="uri:tempuri.org:b" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:simpleType name="barType"> <xs:restriction base="xs:integer" /> </xs:simpleType> </xs:schema>
a.xsd:
<?xml version="1.0" encoding="utf-8"?> <xs:schema targetNamespace="uri:tempuri.org:a" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:b="uri:tempuri.org:b"> <xs:import namespace="uri:tempuri.org:b" schemaLocation="b1.xsd" /> <xs:import namespace="uri:tempuri.org:b" schemaLocation="b2.xsd" /> <xs:element name="foo"> <xs:complexType> <xs:complexContent> <xs:extension base="b:fooType"> <xs:attribute name="bar" type="b:barType" /> </xs:extension> </xs:complexContent> </xs:complexType> </xs:element> </xs:schema>
笔记:
1)我正在使用www.zlatkovic.com的libxml2/xmllint的Windows端口。
当您认为< import>的schemaLocation属性时,它有助于澄清意义。是完全可选的。当你离开它时,你只是说“我想将命名空间XYZ的模式导入到这个模式”。 schemaLocation只是一个提示,即在哪里可以找到该另一个模式的定义。
< import>的确切含义当您阅读W3C规范时,有可能会有所模糊,可能是故意的。因此,解释有所不同。
一些XML处理器容忍多个< import>对于相同的命名空间,并且将所有的schemaLocation基本上合并到单个目标中。
其他处理器更严格,并且决定只有一个< import>每个目标命名空间有效。我认为这是更正确的,当你认为schemaLocation是可选的。
除了您给出的VS和xmllint示例之外,Xerces-J也是超严格的,并忽略后续的< import>对于相同的目标命名空间,给出与xmllint相同的错误。另一方面,XML Spy更为宽容(但是,XML Spy的验证是非常脆弱的)
为了安全起见,您不应该有这些多重导入。一个给定的命名空间应该有一个单独的“主”文档,而这个文档又具有< include>对于每个子文档。这位主人经常是高度人为的,只能作为一个容器。对于这些子文件。
从我所看到的,这通常由XML Schema的“最佳实践”组成,当涉及到最大程度的工具兼容性,但有些人会认为这是一个黑客,从优雅的模式设计中脱颖而出。
咩。