从DTD迁移到XSD,由于某种原因,转换是一个颠簸的过渡.我知道如何在<xs:schema>根标记内部定义模式,但是通过标题和名称空间声明的内容对我来说尤其令人困惑.
我一直在努力遵循W3S上精心布置的教程,但即使是那个教程也似乎预先承担了很多知识.
我想我正在寻找的是国王的英语解释,哪些属性做什么,他们去哪里,以及为什么:
在某些情况下,我看到这些元素/属性的不同变体,例如xsi它们似乎有两个不同的符号,如xsi:schemaLocation="..."和xs:import schemaLocation="...".
我想在所有这些微小的变化之间我似乎无法做出每个人所做的正面或反面.在此先感谢您为这种混乱带来任何清晰度!
G_H*_*G_H 63
您需要了解的第一件事是XML命名空间.如果你有时间浪费,你可以阅读规范.我发现这是与XML相关的更清晰的规范之一.如果你不理解它说的一切都没关系,这是一个很好的基础.但这是一个快速的破坏.
XML元素和属性具有名称.当你看到<test att="hello"/>,你正在看一个名为"test"的元素,其中我们有一个名为"att"的属性.但这不是真正的整个故事......
XML是一种语法,允许您混合来自不同标记语言的内容.例如,当使用XSLT将XML文档转换为XHTML页面时,您将处理至少三种XML定义的标记语言:输入文档,XSLT和XHTML.如果每个人保留自己的元素/属性名称并且不允许任何冲突,那么这样的混合将变得相当困难.
输入XML名称空间.XML命名空间定义了一个"球体",其中元素和属性名称具有实际的语义.元素"template"在XSLT名称空间中具有明确定义的含义.元素"complexType"在XML Schema名称空间中具有明确定义的含义.如果您希望使用自己的标记语言使用XML,那么只要您在不同的命名空间中这样做,就可以这样做.
为了确保命名空间是唯一的,您需要提供一些唯一标识符.该规范决定了URI的使用,通常以HTTP URL的形式.原因很简单:这样的URL往往是很好的唯一标识符.但它也是造成混淆的一个常见原因,因为人们认为URL确实具有意义,或者在XML处理期间将通过网络访问.很清楚,情况并非如此!该URL不需要指向任何现有资源.它不会经历任何转换或被解析为网络地址.即使两个URL指向完全相同的东西,当它们相差一个字符时,它们也被视为不同的名称空间.命名空间标识符只是一个字符串,并且区分大小写.而已.
随着名称空间的引入,XML元素或属性的名称突然由两部分组成:命名空间和本地名称.那个"测试" <test/>只是本地名称.所谓的"完全限定名称"由命名空间和本地名称的一种不可见的组合组成.有时使用符号{namespace URI}local-name,但这只不过是惯例.
所以现在我们需要能够在XML文档中使用名称空间.为了声明命名空间,XML具有硬编码机制.它使用特殊字符串xmlns来允许进行名称空间声明.它可以通过以下两种方式之一完成:将命名空间绑定到前缀,或将其声明为默认命名空间.
绑定到前缀时,表单如下所示:xmlns:prefix="namespace URI".这是XML文档中的一个示例:
<foo:root xmlns:foo="http://www.foo.com">
<foo:test />
</foo:root>
Run Code Online (Sandbox Code Playgroud)
我们现在将命名空间绑定http://www.foo.com到前缀foo.无论此前缀放在元素或属性名称的前面,我们都声明它们是该命名空间的一部分.
这里需要注意的是,实际的前缀绝对没有任何意义.以下XML文档在语义上完全相同:
<bar:root xmlns:bar="http://www.foo.com">
<bar:test />
</bar:root>
Run Code Online (Sandbox Code Playgroud)
前缀只是表示命名空间的便捷方式.它使我们不必每次都完全使用URI.
接下来是默认命名空间.可以使用声明默认命名空间xmlns="namespace URI".您可以抽象地将此视为将命名空间绑定到空前缀.再次使用相同的XML文档,但这次没有前缀:
<root xmlns="http://www.foo.com">
<test />
</root>
Run Code Online (Sandbox Code Playgroud)
使用起来更方便一些.那为什么要有前缀呢?当我们混合来自不同命名空间的内容时,他们开始扮演一个角色:
<root xmlns="http://www.foo.com">
<so:test xmlns:so="http://stackoverflow.com" />
</root>
Run Code Online (Sandbox Code Playgroud)
这次是一个不同的XML文档.我们的root元素位于http://www.foo.com命名空间中,但test元素在于http://stackoverflow.com因为我们必须使用so前缀并使用它test.
您还注意到,可以在XML文档中的任何元素上声明名称空间.该声明的范围(以及绑定到前缀,如果适用)然后成为该元素及其内容.
这有时会变得令人困惑,甚至更多,因为声明可能会互相覆盖.查看此文档:
<root xmlns="http://www.foo.com">
<test />
<so:test xmlns:so="http://www.stackoverflow.com" xmlns="http://www.bar.com">
<test />
</so:test>
</root>
Run Code Online (Sandbox Code Playgroud)
花点时间弄清楚每个元素的命名空间......这是一个很好的练习.
root在命名空间中http://www.foo.com.第一个test元素也在该命名空间中,因为我们没有使用前缀但我们在该默认命名空间的范围内.test带前缀的第二个元素so位于命名空间中,http://www.stackoverflow.com因为这是我们绑定前缀的内容.
那么就是第三个最里面的test元素.它的名称空间是什么?它没有前缀,因此它必须位于默认命名空间中.但是,我们在第二个测试元素中更改了默认命名空间!所以现在最里面的元素属于http://www.bar.com命名空间,而不是http://www.foo.com.
困惑了吗?请记住以下内容:
唷.现在,进入W3C XML Schema.所有这些与它有什么关系?
那么,对于初学者来说,XML Schema本身就是一种用XML定义的标记语言.所以它有理由得到它自己的命名空间.这个命名空间是正式的http://www.w3.org/2001/XMLSchema.如果你把它S写成小写,那就错了.开始明白为什么有些人真的讨厌命名空间?
以下三个文件完全相同:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
</xsd:schema>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
</xs:schema>
<schema xmlns="http://www.w3.org/2001/XMLSchema">
</schema>
Run Code Online (Sandbox Code Playgroud)
重要的是我们正在使用来自XML Schema名称空间的东西.但是,作为惯例,人们倾向于使用前缀xs或xsdXML Schema.
当我们有XML文档时,我们可能希望指定它的架构所在的位置.不止一个模式可能与XML文档相关,因为正如我们所说,语言可以用XML混合.为了说XML文档是模式的一个实例,再次提供了一个特殊的命名空间:http://www.w3.org/2001/XMLSchema-instance.按照惯例,我们倾向于将此命名空间绑定到前缀xsi.但同样,这不是强制性的.
在该架构实例命名空间中定义了几个属性.其中有schemaLocation和noNamespaceSchemaLocation.看看这个文件:
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.foo.com/schema">
</root>
Run Code Online (Sandbox Code Playgroud)
那里发生了什么?首先,我们声明我们将xsi命名空间绑定到命名空间http://www.w3.org/2001/XMLSchema-instance.然后我们在该命名空间中使用了一个属性:noNamespaceSchemaLocation.该属性告诉我们模式的位置,以验证文档中不在任何特定命名空间中的那些部分.以下XML文档在语义上完全相同:
<root xmlns:huh="http://www.w3.org/2001/XMLSchema-instance" huh:noNamespaceSchemaLocation="http://www.test.com/schema">
</root>
Run Code Online (Sandbox Code Playgroud)
请记住,前缀名称没有任何意义.他们是占位符.那么,该noNamespaceSchemaLocation属性是什么?基本上,它告诉我们在哪里可以找到模式.现在与名称空间URI相反,这绝对是可用于从网络或本地存储中获取内容的东西.验证文档中声明的模式的XML处理器可能会尝试获取它.
然后有一个事实,它被称为noNamespaceSchemaLocation.模式定义"目标名称空间".这样做是说明它定义的元素和属性的命名空间是什么.但是可以省略目标命名空间.在这种情况下,我们有一个没有命名空间的XML文档的模式.可以参考这样的模式noNamespaceSchemaLocation.
在许多情况下,模式实际上将定义命名空间.为了说明哪个模式属于哪个命名空间,我们可以使用http://www.w3.org/2001/XMLSchema-instance命名空间中的另一个属性:schemaLocation.该属性可以包含名称空间URI和模式URI的对(由空格分隔).假设我们有名称空间的模式http://www.foo.com位于http://www.myschemas.com/foo-schema.然后我们可以说如下:
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.foo.com http://www.myschemas.com/foo-schema">
</root>
Run Code Online (Sandbox Code Playgroud)
这是一个包含多个命名空间位置对的示例:
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.foo.com http://www.myschemas.com/foo-schema http://www.bar.com http://www.randomschemas.com/bar-schema">
</root>
Run Code Online (Sandbox Code Playgroud)
你需要记住的是,http://www.w3.org/2001/XMLSchema-instance这些东西是用在作为模式实例的XML文档中.命名空间http://www.w3.org/2001/XMLSchema是用于定义模式本身的命名空间.
所以到现在为止,我们依靠URI和具有特殊含义的怪异属性.这就是名称空间:它们看起来非常复杂,直到你弄清楚它们有多简单.只需密切关注什么前缀绑定到什么名称空间URI,并知道该URI定义了什么.
关于你的问题我还需要解决两个关于模式的问题:xs:import和xs:include.请注意我在xs这里使用了前缀约定,因为我们讨论的是W3C XML Schema.
include元素可用于将模式与相同的目标名称空间组合在一起.基本上它允许我们将模式模块化为更小的部分并将它们组合在一起.
import元素的排序相同,但对于具有不同目标名称空间的模式.这允许我们组合不同标记语言的模式.
所以回顾一下:
xmlns:用于指定默认命名空间.xmlns:prefix:用于绑定命名空间prefix.http://www.w3.org/2001/XMLSchema:XML Schema的命名空间.按惯例,通常绑定到前缀xs,但这不是强制性的,也不是自动完成的.http://www.w3.org/2001/XMLSchema-instance:命名空间,用于定义一组有用的内容,用于声明XML文档如何作为模式实例的详细信息.按惯例,通常绑定到前缀xsi,但这不是强制性的,也不是自动完成的.targetNamespace:可以在XML Schema(在根元素上)中使用的属性,用于指定这是作为模式定义的命名空间.schemaLocation:命名空间定义的属性之一http://www.w3.org/2001/XMLSchema-instance,用于指示可以为一个或多个命名空间找到一个或多个模式的位置.我的最后建议:找到一些方便的方法来验证文档和模式,并玩一下.试验命名空间,包含和导入.使用多个名称空间创建文档并尝试范围.
之后,检查XML本身,XML命名空间和XML Schema的规范.这是硬核阅读,但如果你顺利通过它,你将会理解许多人在使用XML多年后似乎仍然想念它.最终这一切都有意义.
祝好运!
| 归档时间: |
|
| 查看次数: |
17074 次 |
| 最近记录: |