...或者为什么这些文件在Visual Studio 2010中验证,而不是在xmllint 1中验证?
我目前正在处理一个已发布的xml架构,其中原作者的习惯是将架构分解为几个.xsd文件,但某些架构文件具有相同的.xsd-files 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"
Run Code Online (Sandbox Code Playgroud)
(完整的文件内容如下.)
然后我有一个xml文件data.xml,带有以下内容:
<?xml version="1.0"?>
<foo bar="1" xmlns="uri:tempuri.org:a" xmlns:xs="http://www.w3.org/2001/XMLSchema" />
Run Code Online (Sandbox Code Playgroud)
很长一段时间,我相信所有这些都是正确的,因为Visual Studio显然允许这种架构风格.但是,今天我决定设置一个命令行实用程序来验证xml文件,我选择了xmllint.
当我跑步时xmllint --schema a.xsd data.xml,我收到了这个警告:
a.xsd:4:元素导入:模式解析器警告:元素'{ http://www.w3.org/2001/XMLSchema } import':跳过位于'b2.xsd'的模式导入名称空间'uri: tempuri.org:b',因为这个名称空间已经导入了位于'b1.xsd'的模式.
b2.xsd跳过导入的事实显然会导致此错误:
a.xsd:9:element属性:模式解析器错误:属性decl.'bar',属性'type':QName值'{uri:tempuri.org:b} barType'无法解析为(n)简单类型定义.
如果xmllint是正确的,我正在努力解决的已发布规范中会出现错误.在那儿?Visual Studio会出错.是吗?
我的确意识到之间的差别xs:import和xs:include.现在,我只是看不出如何xs:include解决问题,因为:
b1.xsd并b2.xsd拥有相同的targetNamespacetargetNamespace的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>
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
笔记:
1)我使用的Windows移植的libxml2/xmllint在发现www.zlatkovic.com.
ska*_*man 28
这里问题的症结在于,当你有两个不同的<import>元素时,它们意味着什么,当它们都引用相同的命名空间时.
当您认为schemaLocation属性<import>完全是可选的时,它有助于澄清含义.当你把它遗漏时,你只是说"我想将命名空间XYZ的模式导入到这个模式中".这schemaLocation只是一个提示,在哪里可以找到其他模式的定义.
<import>当你阅读W3C规范时,确切的意思是有点模糊,可能是故意的.因此,解释各不相同.
某些XML处理器可以容忍<import>同一命名空间的多个,并且基本上将所有XML 合并schemaLocation到一个目标中.
其他处理器更严格,并确定<import>每个目标命名空间只有一个有效.我认为这是更正确的,当你认为这schemaLocation是可选的.
除了你提供的VS和xmllint示例之外,Xerces-J也是超严格的,并且<import>对于相同的目标命名空间忽略后续,提供与xmllint相同的错误.另一方面,XML Spy更宽松(但是,后来,XML Spy的验证非常不稳定)
为了安全起见,你应该不会有这些多进口.给定的命名空间应该有一个"主"文档,而<include>每个子文档又有一个"主" 文档.这个主人通常是高度人为的,仅作为一个容器.这些子文件.
从我所看到的情况来看,这通常包括XML Schema的"最佳实践",当涉及到最大的工具兼容性时,但是有些人会认为它是一种破坏优雅架构设计的黑客.
咩.