XML基础

虽说我认为上面的东西基本上不言自明,但我也意识到,很多人并不是很清楚XML的基本概念。所以,我准备把上面的东西解释一遍,只解释那些我认为确实有必要解释的东西。
一个XML文档就是一个文本文档。跟普通文本文档完全相同。只不过,它可能会比别的文本文档多了一些限制而已。一般来说,我们对于XML文档的直观认识就是:里面有大量的尖括号:)。是的,确实如此。XML文档被要求是Unicode字符集的文本文档。当然,它可能有多种编码方式(比如:utf7、utf8、utf16le、utf16ge等等),但这不是我们关注的焦点。顺便说一句,xml文档一般不需要bom字符,当然如果你加上了bom,你的xml必须没有prolog。后面我会讲到prolog是啥。
xml的基本思想就是对文本数据打上标记,用以更精确的表达这些文本数据的含义。举个例子1977/2/19 5:55:00这个文本数据,我们直觉它应该是一个timestamp,但是实际上它可能是任意东西,比如一种食品的名称:),虽然显得有些怪异。而如果我们用<birthday>1977/2/19 5:55:00</birthday>来表达这个数据,我们就有把握的说,这个数据是一个生日。注意:尖括号中的数据是用来说明原始数据的,它们被称作标签。前面的那个叫做前标签,后面的那个叫做后标签。tag。注意它们的特征。前后相同,后面多了一个/,都是用<>括起来的。这就是XML,也就是一种给数据打标签的方式。数据加上标签作为一个整体被称为一个元素。Element。

XML中的X表达的是可扩展性,其基本意思就是说:XML本身没有定义任何tag,你可以用你觉得舒服的任何tag对数据作标记,设想一下我们比较熟悉的HTML,会发觉其实它就是规定了tag集合的一种标记语言。

<深入>
有时候我们也会迷惑,如果没有任何预定义的tag,我们对数据进行标记岂不是成了自己逗自己玩?是啊,我自己用了一个标记,想用来表达某些含义,可是谁知道是什么含义呢?除了我自己?如果大家都不知道,我这个标记还有更大的意义么?
可以说,上面这个问题是一个本质问题。如果我们找不到XML存在的意义,我们就不值得去学习它,不是么?
我要提到的一个概念叫做XML Application。什么是XML Application?它就是:规定了一系列tag的含义的一个XML规范。我们可以而且也只能用这些被规定好的tag来标记数据了。又有人不明白了,这……这跟HTML还有区别么?我们说,现在看来暂时没有:)。不过马上我就告诉你其中的区别了。
一、HTML是一个全世界统一的标准,而我们的XML Application可以是在一个范围内有效的标准。
这提供了什么好处呢?最大的好处就是,我可以只需要试图说服一部分人而不是所有人都遵守,这样,我的这个约定就比较容易实施。
二、可以有多个约定,也就是说,可以有多个XML Application。
这个的用处大家就比较清楚了,我可以约定一套用于数学公式的标签集合,也可以约定一套用于音乐的标签集合,两者互不干扰。而HTML只有一套tag集合。却试图表达整个世界。
三、这多个XML Application可以互相混合。
哇,太好了,我真的可以描述整个世界了。可是这又会引发一个问题——这些标签冲突怎么办?
这儿,XML引入了一个namespace的概念。简单的说,不是同一个namespace中的标签,就算其名字相同,我们也知道它们是两码事,不会冲突。可是怎么保证namespace的名字不冲突呢?毕竟,我说我的标签都是dup这个namespace里面的,而这并不能阻止你让你的标签也是dup这个namespace。我们的W3C委员会非常聪明的解决了这个问题:它们规定namespace必须是一个URI,通俗的说,就是一个网址。我们知道,网址是保证全球唯一的。但是,由于网址的书写不过方便——毕竟太长了(更深层次的原因是:它们有些字符是不允许出现的),我们被允许可以起一个别名。当然,这个方案对于故意捣乱者也是无能为力……,不过,这就是另一回事情了。
备注:其实,现在已经定义了好多XML Appliction了。有很多已经被公认了,大家都在用:)。当然,这并不阻止你自己定义自己的Application。顺便说一句,定义Application需要使用Schema,有各种Schema可以用,包括DTD,XML Schema(schemaLocation),Schematron,RELAX NG等等。其中,很多都是一个具体的XML Application。哦,我要晕了。
关于名字空间,我给大家一个直观的感受,看例子:
<music:goal xmlns:music = "http://www.music.com/schemas/music">
<music:time music:duration = "3d"/>
<math:item xmlns:math = "http://www.math.com.cn/">
<math:line path = "12, 38, 42, 77"/>
<music:timeStamp math:value = "20082324234" />
</math:item>
</music:goal>
上面的例子中,涉及到两个名字空间,http://www.music.com/schemas/music和http://www.math.com.cn/,对于这俩名字空间,我们起的别名分别是music和math,这样,我们的元素的tag就可以用namespaceName:前缀来区分了。如果我们不理会名字空间,我们完全可以把namespaceName:tagName看成一个整体。另外,强调一下,名字空间的别名是可以随便起的,只要在同一个文档中不重复就行了。
</深入>

一个XML文档要求最多一个元素。不过,需要提醒大家的是,元素可以嵌套,嵌套的层次(深度)没有任何限制。我举个例子大家就会很明白了:
<person>
<name>dup</name>
<birthday>1977/2/19 5:55:00</birthday>
<description>
<strongPoint id = "first">smalltalk</strongPoint>
<strongPoint id = "second">eat</strongPoint>
<interest>play pingpang</interest>
</description>
</person>
上面就是一个元素嵌套的例子。我想大家应该觉得非常简单。形式是不重要的(比如缩进换行什么的)。只要保证正常的嵌套关系没有搞混乱就行。

元素可以直接或者间接递归。比如:x元素可以有叫做x的子元素,或者其子孙中有叫做x的元素。

顺便我把子,子孙,父,祖先这个几个概念说一下。还是上面的例子,name,birthday,description是person的子。所有的子以及子的所有的子,依次递推下去,这些元素的总和叫做子孙。也就是说,直接的子和间接的子。父相对于子。一个元素只能有一个父。比如:strongPoint的父是description。祖先是父以及其父,依次递推直至最上层元素的那个集合,比如:strongPoint的祖先是description,person。

XML文档中,除了Element以外,还有一些别的东西,我一一道来:)。

其实,上面那个嵌套的元素就已经有一些新鲜的玩艺儿了,比如:如果你仔细注意了的话,有几个(确切的说是两个)元素的前标签里面有一些我们以前没有提及的东西,我们把那东西叫属性。Attribute。Attribute的形式是:n = “v”,其中n是任意的字符串。v也是。一个元素可以有任意多个Attribute,它们的n不能重复。n被称作属性名,v被称作属性值。元素的属性一定是放在前标签里面的。

我们把前标签和后标签之间的文本称作Text。这些Text被称作元素的内容。一个元素的内容可以是Text,也可以是其它元素或者其他元素们,甚至可以是空白。当然,还可以是这些东西的组合。

如果一个Text是以<![CDATA[开头,并且以]]>结尾,那么这个Text就被称做是CDATASection,CDATA段。CDATA段一个显著的用意就是禁止被解释。也就是说,CDATA段中的内容,一律按照其原始的形式存在。甚至里面的标签什么的也不会被认为是标签了。只是普通字符而已。

注释是另一种东西,跟元素没有什么关系,它可以出现在在除了标签以外的任何地方,用来进行一个人可以理解的说明。注释的形式如下:<!-- ... -->其中...可以是任何东西,除了--。

DocumentType。文档类型,其实就是用来指定该XML文档所遵循的XML Application的Schema标准的那种东西。到现在为止,我只知道怎么使用它搞定用DTD定义的Schema,对于别的Schema,我不会使用这种方式,而是采用schemaLocation这个属性的方式来引用相关的文档类型定义。说实话,我不知道用schemaLocation这种方式引用Schema算不算文档类型。需要注意的是,如果一个XML没有引用相关的文档类型定义,也就是用于规定标签集合的Schema,那么这个文档就是普通的格式良好的。如果引用了,那么,XML文档的解释器会使用Schema规定的标签集及其结构验证该XML文档是否满足Schema的规定,故此,这时候的XML文档称作可验证的。DocumentType基本上是这样的语法: <!DOCTYPE schemaName PUBLIC "publicId" SYSTEM "systemId">,或许还有一些别的东西,比如规定实体(Entity)和记号(Notation)的,以及规定内部子集的。但是遗憾的是:这些语法我不明白,所以就不描述它们了。深入的东西可以看看inline DTD。
我举个例子说明一个DocumentType是什么样子的:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
这就是一个特别常见和特别有用的DocumentType,其实说到这儿,我似乎应该深入的描述一下publicId的语法结构,但是,巾短话多,我就不烦你了,如果你有兴趣,参见W3C的规范。

Notation就是记号。这个东西说起来也很绕,原因是:我没有搞明白。所以略而不说。不过,可以告诉大家,在XML文档中碰到这个东西的时候非常好,而且就算碰到你也不会有感觉。所以不说也没有什么问题。
<高级>
记号是一个比较高级的主题,涉及到关于不可解析实体的处理问题。由于XML文档是一个纯文本文档,其中需要用tag作一些标记,用来规定数据的一些意义。这样,XML文档只能用来描述那些文本性质的数据。这些数据被称作可解析数据。也就是说,它们能够被XML解释器解析。但是,我们能用XML描述非文本性质的数据么?比如:二进制的数据,更具体的说,比如一个图片,一段音频什么的?我们说:我们的愿望是无穷的,不能这样就屈服了。我们就是要用XML描述二进制文件!可是我们XML的铁律就是不想让它去处理二进制数据啊。这时候,我们就需要Notation了,其实,Notation只是一个名字,一个记号,一个媒体类型,一个指示XML解析器用什么解释器来解释这种媒体。比如:我们定义了一种叫做PNG的Notation,我们就可以这样使用它了,首先,我们要在Schema中定义元素的某个属性,比如:image元素的src属性,然后,我们在XML文档中这样使用了,这样<image src="hello.png" style="width:20px; height:80px" show="embed" />,看看,我们能够描述二进制数据了吧。
在这个过程中,我们的XML解释器就很清楚的知道,image的src属性是一个PNG,它需要用PNG的解释器来帮助它解释这个数据。
也就是说,Notation这样的设施就给了XML部分的表达二进制数据的方式,这种数据从本质上讲是XML解析器不可解析的数据。前面的CDATASection就是一种XML解析器不会去解析的数据,是文本形式的。后面还会讲到的ProcessingInstruction也是一种描述不可解析的数据的手段,也是文本形式的。
</高级>

Entity,实体。最常见的也是必须的几个实体定义是:lt,gt,amp,quot,apos,分别表示<,>,&,",',它们本身是标签和属性需要使用的元字符,所以必须用实体引用来引用它们。

EntityReference就是那种&name;的那种东西,name是实体的名字,实体引用会被在引用处替换为实体本身。

ProcessingInstruction,处理指令。其基本语法如下:<?target content?>target是一个外部程序,content是一个字符串,这个字符串是将会被交给target这个外部程序去解释和处理的。我举个例子来说明:<?php print "hello"?>,这就是一个处理指令,content可以任意复杂,都会交给target取处理。另一个用法是:<?xml-stylesheet href="trans.xsl" type="text/xsl"?>它是一种类似于HTML Link的东西,表示引用trans.xsl这个样式单。这种PI的content的组成方式跟Element前标签的Attributes很像,我们一般称它们为伪属性。

一个比较奇特的符合处理指令语法的但是不是处理指令的东西是:<?xml version="1.0" encoding="UTF-8"?>它跟上面的那个xml-stylesheet PI很像,但用途市绝对不一样的。这个语法要素要么不出现,要么只出现一次,而且必须出现在开头,绝对的开头,它前面不能有任何空白字符。它在某种程度上完成了BOM的作用。

上面所有的东西都被称为节点。所有的这些节点组合以来就是XML文档。Document。

PS:XML规范中对于字符的处理是非常复杂的,但是,我没有描述这些东西,因为,这些东西不太重要(对于普通用户来说),而且,XML规范中对于字符的处理也有点太复杂了。达到了夸张的地步。

好了,这就是XML文档,其实是非常简单的。但是,这个我们上一篇文章中给出的XML Core DOM有什么关系呢?

XML文档是一个普通的文本字节流,而XML Core DOM是一个XML文档解析器根据这个XML文档构造的一颗树,一棵结点组成的树,其根就是称作Document的东西。ok,这就是XML基础的全部。我们可以通过XML Core DOM提供的接口,遍历这一棵树,访问和修改各个节点,凭空生成和插入新的节点,删除某些节点。处理各种用户自定义的数据等等。现在,你能够看明白上一篇文章 的那些接口及其含义了么?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值