赵工的个人空间


专业技术部分转网页计算转业余爱好部分


  网站建设

首页 > 专业技术 > 网站建设 > XML可扩展标记语言
XML可扩展标记语言

XML是Extensible Markup Language的缩写,即可扩展标记语言。XML没有固定的标记,允许用户定义数量不限的标记来描述文档中的资料。
XML来自SGML(Standard Generalized Markup Language),是SGML的子集,最初的目的是为了实现电子数据交换EDI,是跨平台的,还出现了数学标记语言MathML和化学标记语言CML等。

1. XML的语法规范:

XML是一种描述数据的标记语言,以.xml为文件名后缀,它不提供固定的标记,而是允许用户自定义数量不限的标记来描述数据,且允许使用嵌套的信息结构。一个XML文档示例:
<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Frank</to>
<from>John</from>
<head></head>
<body>Don't forget the metting!</body>
</note>
编写XML文档必须遵循一些语法规则。

1)标记、元素和属性:
⑴标记:
XML标记都是由小于号“<”开始,由大于号“>”结束。标记有起始标记和结束标记之分,起始标记由“<”开始,由“>”结束;结束标记由“</”开始,由“>”结束。
⑵元素:
XML元素是指从一个起始标记到它的结束标记间的一段内容。元素是XML文档的基本单位,一个XML文档可以由一个或多个元素构成。有一种空元素,即起始标记与结束标记之间没有内容,如<head></head>,空元素可以简写为<head/>。
⑶属性:
一个元素可以带有属性,属性是XML元素的附加信息,写在起始标记里,位于元素名称的后面。如:
<books ISBN="123456789">
一个XML元素可以有一个或多个属性,每个属性都以空格分开。在XML中,使用属性值通常能够简化文档的书写,但不利于日后的维护和更新。

2)XML语法规则:
⑴每个起始标记必须有对应的结束标记。
⑵一个XML文档只能有一个根元素。XML文档是树状结构,必须有根,也只能有一个根。
⑶所有的XML元素必须正确嵌套。
⑷标记区分大小写,起始标记与相应的结束标记的大小必须一致。
⑸XML元素之间有父子、兄弟关系。XML文档是树状结构,只有一个根元素,其他元素都是根元素的后代。
⑹属性的值必须加引号。XML属性是以名称和值的形式配对出现的,属性名称区分大小写。XML属性的值应用引号围起来,可以用双引号,也可以用单引号,通常使用双引号。如果属性的值里包含双引号,就用单引号包围属性值;如果属性值里面包含单引号,就用双引号包含属性值。如:<site info="wo'you'xian.net">。
⑺一个XML元素不能有相同的属性。
⑻使用xml:space属性。在XML规范中,空白包括空格、制表符和空行,使用空白来分隔标记可以获得较好的可读性。xml:space的属性值有default和preserve,使用default允许程序根据需要处理空白,而preserve指示应用程序按原样保留空白,暗示空白可能有含义。

3)XML名称的命名规则:
XML名称可以包含英文字母、数字以及下划线等其他字符,但不能以数字或标点符号开头,不能以xml开头。XML名称不能包含空格,虽然可以包含非英文字符,但读取XML文档的软件未必支持多语言,所以不建议使用。
XML名称支持下划线、连字符、点、冒号,但名称开头不能使用连字符、点、冒号,因为是XML Namespace的保留符号,所以一般只使用下划线,其他尽量不用。
自定义的名称要具有描述性,要比较简短,避免使用连字符、点和冒号,因为在XML中往往有特定含义。

4)XML实体引用:
在XML中,一些字符有特殊含义,如小于号,如果在文档内容中出现,会造成解析错误。如果在XML文档内容中使用小于号,要使用实体引用entity reference,即“<”来替换。
XML中5个预定的实体引用为:

实体引用

字符

说明

&lt;

<

小于号

&gt;

>

大于号

&amp;

&

&apos;

'

单引号

&quot;

"

双引号

XML解析器解析含有上述实体引用的XML文档时,会将这些实体引用转换成相应的字符。

5)XML的CDATA区:
如果用户需要在XML文档中写一段内容,里面包含很多特殊字符,对每个字符转换成实体引用会比较繁琐,这时可以使用CDATA区来定义这段内容。
CDATA区指不应由XML解析器进行解析的文本数据,其中可以不必使用实体引用。CDATA区以“<![CDATA[”开始,以“]]>”结束。示例:
<![CDATA[
<html>
<head>
<title>test</title>
</head>
<body>
test
</body>
</html>
]]>
在CDATA区内,不能出现字符串“]]>”,也不允许嵌套CDATA区,而且“]]>”不能包含空格或换行。如果CDATA区的内容中包含“]]>”,就需要使用“]]>”来替换。

6)XML注释:
如果需要在XML文档中写注释,要以“<!--”开始,以“-->”结束。示例:
<!--This is a comment-->
为了避免解析错误,XML注释中不能有连续的两个连字符。注释只能放在XML内容中,而不能放在标记内。

7)XML声明:
XML文档应该以XML声明declaration开始,但不是必须的。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
如果一个XML文档含有声明,必须放在XML文档的第一行。XML文档声明主要有3个参数:
·版本version:版本表示遵循的是W3C的XML1.0标准。
·字符编码encoding:表示该XML使用的字符编码。
·独立standalone:如果XML的standalone属性值为no,表示它需要DTD。

8)命名空间:
指定XML命名空间标准的初衷是为了解决XML文档中命名冲突问题。命名空间通过给标识名称加一个唯一资源标识符URI定位的方法,来区分名称相同的标识。
为命名空间URI定义的前缀用来限定XML数据中的元素和属性的名称以实现关联,命名空间可防止元素和属性名称冲突,并允许以不同的方式处理和验证同名的元素和属性。
命名空间使用xmlns:属性在元素中声明,此属性的值就是标识该命名空间的URI。命名空间声明的语法是xmlns:<name>=<"uri">,其中<name>是命名空间前缀的名称,<"uri">是说明命名空间URI的字符串。一旦声明后,前缀就可以用来限定XML文档中的元素和属性,并将它们与命名空间URI关联。因为命名空间的前缀会在整个文档中使用,所以其长度应较短。
若要表明元素是特定命名空间的一部分,应事先在其前面添加命名空间前缀,从而使其称为一个完全限定的元素名称。示例:
<mybook:BOOK xmlns:mybook=""http://www.book.com/books.dtd">
任何没有用命名空间前缀完全限定的元素均属于默认命名空间。当在xml文档中使用多个命名空间时,将其中一个命名空间定义为默认命名空间可以使文档更加简洁,只有来自非默认命名空间的元素需要完全限定。默认命名空间声明示例:
<BOOK xmlns:mybook=""http://www.book.com/books.dtd">
默认命名空间只适用于元素,不适用于属性。命名空间声明有范围,包括默认范围和限定范围。默认范围命名空间是在根元素中声明命名空间,它应用于文档中所有未限定的元素。限定范围命名空间是在一个更具体的命名空间,在文档中某个位置重写时声明的。

9)错误处理:
创建XML文档时,难免会出现错误。当XML解析器发现XML文档中的错误时,会根据文档错误的类型是一般性错误或致命性错误而采取相应的处理方式。如果发生一般性错误,解析器能够恢复错误,并继续解析XML文件;如果发生致命性错误,则解析器停止处理文档并报告相关的错误信息。任何破坏XML文档格式规则的错误都被认为是致命性错误。
现在大多数浏览器都提供错误报告工具,可以帮助用户查找文档中不易觉察的错误,这些错误报告工具是非常严格的,一旦发现文档中的错误,将立即终止对文档的处理,即使该错误没有被定义为致命错误。
XML解析器通常以连续的工作方式检查错误,它们从头开始读取文件,一旦遇到错误就停止对文件的进一步解析,并立即报告错误,所以每一次只显示一个错误。待修复错误后,解析器就可进一步解析文件,遇到错误再次停止对文件的解析,并立即报告错误。如此反复,直至所以错误均被修复,然后浏览器就可以正确地显示整个XML文档。

10)DTD和XML Schema:
DTD(Document Type Definition)文档类型定义,是一套关于标记符的语法规则。DTD是一种保证XML文档格式正确的有效方法,可以通过比较XML文档和DTD文档来查看文档是否符合规范,元素和标记使用是否正确。
一个DTD文档是一个ASCII码文本文件,后缀名为.dtd,其中包含元素的定义规则、元素间关系的定义规则、元素可使用的属性、可使用的实体或符合规则。只需定义好标准的DTD,就能够依照DTD来建立XML文件,并且进行验证,如此就可以建立标准和交换数据。
每一个XML文档都可携带一个DTD,用来对该文档格式进行描述,测试该文档是否为有效的XML文档。DTD不是必须的,但它为文档的编制带来了方便,加强了文档标记内参数的一致性,使XML语法分析器能够确认文档。DTD有外部和内部之分。
DTD采用了非XML语法规则,不支持数据类型,扩展性较差。目前XML Schema已经成为W3C的正式推荐标准,因而推荐来验证XML文件。
XML Schema也用于定义和描述XML文档的结构和内容模式,可以定义XML文档中元素及元素之间的关系,还可以定义元素和属性的数据类型。XML Schema本身是一个XML文档,符合XML语法结构,可以用通用的XML解析器解析。
XML Schema对DTD进行了扩充,引入了数据类型、命名空间,使用XML Schema能够书写XML文档以及验证文档的合法性,通过特定的映射机制还可以将不同的Schema进行转换,以实现更高层次的数据交换。

2. 解析XML文档:

XML只是用来保存信息,为了获取其中的信息需要对XML数据进行处理。用于处理XML文档的软件称为解析器。
XML解析器能够读、写和操作XML文档,一般有两种模型,流模型和文档对象模型DOM。
1)DOM:
DOM是用与平台和语言无关的方式表示XML文档的W3C标准,是以层次结构组织的节点或信息片段的集合。这个层次结构为树形,允许开发人员在树中寻找特定信息,分析该结构通常需要加载整个文档和构造层次结构,然后才能做其他工作。
DOM以及广义的基于树的处理有很多优点,树在内存中是持久的,因此可以修改以便应用程序能对数据和结构做出更改,还可以在任何时候在树中上下导航。但对于较大的文档,解析和加载整个文档会较慢且很耗资源。
2)SAX:
SAX是流模型的,分析能够立即开始,而不是等待所有数据被处理后才进行,应用程序不必解析整个文档,可以在某个条件得到满足时立即停止解析,速度较快。SAX基于事件模型,在解析XML文档时可以触发一系列事件,当发现给定的标记时可以激活一个回调方法。SAX对内存的要求通常比较低,对只需要处理文档中所包含的部分数据时有优势,但很难同时访问同一个文档中的多处不同的数据。
3)XPath:
XPath是从XML基础规范上派生出的技术,用于快速检索和查询XML文档。XPath是W3C定义的用于在单个XML文档中快速检索和定位XML文档节点的规范,也是XSLT技术的基础。
XML采用树状层次结构,类似文件系统的目录结构FilePath,因此可以将文件路径名的概念用到XML文档中,就形成了XPath路径。处理XML文档时可以一层层查找所需的XML节点,也可以指定XPath路径字符串来快速定位XML节点,使用反斜线符号来分隔各个层次的XML元素名称。
文件目录系统中,可以使用绝对路径名,也可以使用相对路径名,使用一个点号表示当前目录,使用两个点号表示父目录。在XPath中,从XML文档根节点出发指定的XPath路径为绝对路径,从某个XML节点开始转到其他节点所经过的路径为相对路径。XML也是用一个点表示当前节点,使用两个点来表示父节点。
文件系统中,同一个目录下面不能有相同名称的对象;而在XML文档中,同一个XML节点下可以存在多个具有相同名称的子节点,因此XPath路径可能无法唯一地确定一个XML节点,XPath采用了内嵌条件判断语句的方法来解决这个问题。
4)XSLT:
XSLT是用于将一种XML文档转换为另外一种XML文档,或者可被浏览器识别的其他类型文档,如HTML和XHTML。通过XSLT,可以向或从输出文件添加或移除元素和属性,可重新排列元素,执行测试并决定隐藏或显示哪个元素等。XSLT使用XPath在XML文档中查找信息,XPath被用来通过元素和属性在XML文档中进行导航。
XSLT转换过程会涉及三个文本文档,一是要处理的原始XML文档,二是XSLT样式表文档,三是XSLT处理输出的文档。XSLT文档包含了XSLT代码,代码本身是XML格式,但使用了XML的名称空间。XSLT转换输出的是文本文档,包括XML文档、HTML文档、SQL语句字符串或其他任意格式的字符串数据。

3. XML命名空间:

在XML中,元素名称是由开发者定义的,当两个不同的文档使用相同的元素名称时,就会发生命名冲突问题。XML命名空间提供避免元素命名冲突的方法。
XML命名空间是由国际化资源标识符URI标识的XML元素和属性集合,该集合通常称为XML词汇。W3C XML命名空间的建议旨在创建一个机制,以便XML文档中来自不同标记词汇表的元素和属性可以被明确标识和组合,而无须处理命名所产生的问题。
XML的一个主要目的是跨系统、跨机构共享数据,用户会用到大量来自外部系统的XML格式,无法保证XML文档中的所有元素和属性的名称都是独一无二的,来自外部的XML文档可能具有相同的名称,所以在使用这些文档的一些阶段需要用到命名空间。
W3C组织推荐用户使用URIs或URNs去产生唯一的命名空间。由于大多数企业和独立软件开发商有自己的注册域名,因而用自己的域名作为XML文档命名空间的起点已经成为业界的推荐标准,其后的部分可以使用自己最想要的字符任意组合,但应避免使用空格和问号。命名空间是区分大小写的,应尽量用全小写字母。

1)声明命名空间:
命名空间被声明为元素的属性,不一定只在根元素中声明命名空间,而是可以在XML文档的任何元素中进行声明。
声明默认命名空间,包含所有元素。示例:
<?xml version="1.0" encoding="UTF-8" ?>
<hrEmployees xmlns="http://www.dwen.com/namespace/hr/employee">
<employee firstName="Joe" lastName="Fawcett"/>
<employee firstName="Danny" lastName="Ayers"/>
</hrEmployees>
这样就为XML文档声明了一个默认命名空间,根元素及其包含的所有元素都与默认命名空间相关联,但元素的属性不属于该默认命名空间。默认命名空间声明可以通过将xmlns属性的值设置为空字符串来取消声明。
属性也可以添加命名空间,格式为:
{http://wrm.com/namespace/hr/employee}firstName
但使用这种方法比较繁琐,也容易造成文档杂乱,可以采用将命名空间映射到特定的前缀:
<someElement xmlns:prefix="namespace"/>
然后在特定元素或属性名前面加上这个前缀,即可与这个命名空间相关联。除非属性的名称有前缀,否则命名空间声明不应用于属性。
在使用命名空间的大多数XML文档中,经常是定义元素属于一个特定的命名空间,而很少定义属性属于一个特定的命名空间。这是因为,属性总是与一个元素相关联,不能脱离元素而独立存在,因此如果该元素本身就已经属于一个命名空间,则其属性已经是唯一可识别的,没有必要为属性再指定一个命名空间了。
XML文档中声明的命名空间具有有效范围,起始于声明该命名空间的元素,并应用于该元素的所有内容,直到被具有相同前缀名称的其他命名空间声明所覆盖。
W3C XML命名空间标准规定,xml开头的字母序列前缀被保留(任何大小写组合),供XML相关规范使用,前缀xml根据定义绑定到命名空间http://www.w3.org/XML/1998/namespace上。只有已声明并绑定到命名空间的前缀才能使用。

2)创建多个命名空间:
许多XML文档使用多个命名空间,一般情况下指定一个默认命名空间,而为其他元素定义明确的命名空间。示例:
<applicationUsers xmlns="http://wrm.com/namespace/application/hr/config"
xmlns:ent="http://wrm.com/namespace/general/entities">
<ent:user firstName="Joe" lastName="Fawcett"/>
<ent:employee firstName="Danny" lastName="Ayers"/>
</applicationUsers>
两个声明都在根元素中,所以有效范围为整个文档。文档中没有任何前缀的元素属于默认命名空间,而任何具有ent前缀的元素属于明确的命名空间。在声明命名空间时,不能用相同的前缀指向不同的命名空间。

3)无命名空间:
如果范围内没有默认命名空间,可以说元素位于无命名空间中。当已声明的默认命名空间被取消声明时,也将应用无命名空间。

4)常见的命名空间:
⑴“xml:”命名空间:
在每个XML文档中,前缀xml都已经隐式地绑定到URI http://www.w3.org/XML/1998/命名空间,这是硬编码到所有XML解析器的,用户不必自己声明。用户可以在自己的XML文档中使用各种特殊属性,如使用xml:lang来设置元素的本地化语言信息。
在xml命名空间可能遇到的其他属性好标识符有:
·xml:space,用于设置下游应用程序应该怎样处理解析器传递的空格等字符,属性值只能为default或preserve,default表示应用程序可自行处理空格等字符,preserve表示应用程序应把空格等字符作为普通文本字符来处理。
·xml:base,提供一种通过显示的方式指定一个基准URI,并通过此基准URI来解析指向外部资源的相对URI方式。
·xml:id,用于表示XML文档元素的唯一标识符,应用程序将所有指定为xml:id的属性视为唯一标识符。
目前只有3个有关XML的规范XLink、XML InfoSet和Cannonical xml是基于XML Base的,将其作为它们标准引用的一部分。
⑵xmlns命名空间:
xmlns是xml namespace的缩写。xmlns前缀被绑定到URI http://www.w3.org/2000/xmlns/命名空间,这是硬编码到XML解析器。xmlns属性可以在文档中定义一个或多个可供选择的命名空间,该属性可以放置在文档中任何元素的起始标记中。
⑶XML模式Schema:
此命名空间具有URI http://www.w3.org/2001/XMLSchema,被用于模式文档中。这个命名空间中包含W3C XML模式结构规范和W3C XML模式数据类型规范中定义的元素、属性和数据类型,如十进制数据、字符串和布尔值。习惯上常将前缀xs或xsd绑定到此命名空间。
⑷XSLT命名空间:
XSLT主要用于将XML文档转换成不同的格式,如其他格式的XML文档、HTML文档,或纯文本文件。XSLT命名空间的URI是http://www.w3.org/1999/XSL/Transform,常用xsl或xslt前缀来绑定到此命名空间。
⑸版本控制:
可以将元素的命名空间名称用于版本控制,W3C已经将该方法用于各种XML技术,包括SOAP、XHTML、XML架构和RDF。对于使用命名空间控制版本的文档,其命名空间URI格式采用:
http://my.domain.example.org/product/[year/month][/area]
通过修改后续版本中的命名空间来控制XML文档的版本遇到的主要问题,这种对于版本不需要经常更改的文档格式是适宜的。
⑹SVG:
可缩放矢量图形Scalable Vector Graphics是基于XML,用于描述二维矢量图形的一种图形格式。SVG严格遵从XML语法,并用文本格式的描述语言来描述图形内容,是一种和图像分辨率无关的矢量图形格式。SVG可以内嵌于其他XML文档中,而SVG文档也可以嵌入其他的XML内容,各个不同的SVG图形可以方便地组合。SVG文件必须以.svg为后缀名,也有一个DOCTYPE和自己的命名空间http://www.w3.org/2000/svg。
用户在一个网页中使用SVG,就要确保浏览器分清哪些部分是传统HTML,哪一部分需要作为SVG插件处理,需要使用不同的命名空间来区分两个不同的部分。
在网页中嵌入SVG,有3种方法:
·使用<embed>元素,这种方法适用于大多数浏览器,但不是严格的XHTML的一部分。
·使用<object>元素,这种方法适用于Firefox和Chrome浏览器,但在IE中可能会有问题。
·使用<iframe>元素,这是最简单易用的方法,可以使所有浏览器都能显示SVG文档。
<iframe src="shapes.svg" width="400" height="400"></iframe>

4. 使用JavaScript操作XML文档:

JavaScript是一种广泛应用于客户端浏览器的脚本语言,它是基于对象Object和事件驱动Event Driven并具有安全性能的脚本语言。

1)使用DOM操作XML文档:
XML文档对象模型DOM定义访问和操作XML文档的标准方法,DOM将XML文档作为一个树形结构,而树叶被定义为节点。
按照W3C的定义,DOM是一种允许程序或脚本动态地访问更新文档内容、结构和样式的、独立于平台和语言的规范化接口。DOM以树形结构表示HTML和XML文档,定义了遍历这个树和检查、修改树的节点的方法和属性。DOM中,代表XML文档的程序设计对象称为节点nodes,DOM会将XML文件的节点建构成树状结构。
根据DOM,XML文档中的每个成分都是一个节点,整个文档是一个文档节点,每个XML标记是一个元素节点,包含在XML元素中的文本是文本节点,每一个XML属性是一个属性节点,注释属于注释节点。节点树中的节点彼此之间都有等级关系,用父、子和同级节点来描述这种关系。节点树中,顶端的节点称为根节点,根节点之外的每个节点都有一个父节点,节点可以有任何数量的子节点,同级节点是拥有相同父节点的节点。
XML DOM节点属性有:

属性

描述

attributes

包含当前节点属性的数组

childNodes

包含子节点数组

firstChild

指向当前节点的第一个子节点

lastChild

指向当前节点的最后一个子节点

nextSibling

返回当前节点的下一个邻居节点

nodeName

返回当前节点的名字

nodeType

返回当前节点的类型

nodeValue

包含当前节点的文本

ownerDocument

返回文档的根元素

parentNode

指向当前节点的父节点

previousSibling

返回当前节点的前一个邻居节点

text

返回当前节点的内容或当前节点及其子节点的文本(IE支持)

xml

以字符串返回当前节点及其子节点的XML(IE支持)

应用JavaScript调用XML DOM的API函数来操作XML文档时,不同浏览器之间及不同版本的浏览器之间有差异。操作XML文档时,无论是读取文档还是修改文档,首先要做的是将文档读入内存空间,即加载文档。

2)加载XML文档:
加载客户端XML文档与加载服务器端XML文档的方法有不同,而且不同浏览器之间也有差别。
⑴在IE浏览器中加载XML文档:
xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
XmlDoc.async="false";
xmlDoc.load("books.xml");
上面的代码用来加载一个XML文档。下面的代码则是加载字符串进入解析器:
xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
XmlDoc.async="false";
xmlDoc.loadXML(txt);
⑵在Firefox及其他浏览器中加载XML文档:
xmlDoc=document.implementation.createDocument("","",null);
XmlDoc.async="false";
xmlDoc.load("books.xml");
而将字符串载入解析器代码为:
parser=new DOMParser();
xmlDoc=parser.parseFromString(txt,"text/xml");
⑶加载服务器端的XML文档:
服务器端加载XML文档与加载客户端XML文档完全不同,不同浏览器之间也有差别,为了方面使用,可以把代码存储在单独的JavaScript文件中:
function loadXMLDoc(filename){
if(window.XMLHttpRequest){
xhttp=new XMLHttpRequest();
}else{
xhttp=new ActiveVObject("Microsoft.XMLHTTP");
}
xhttp.open("GET",filename,false);
xhttp.send();
return xhttp.responseXML;
}
⑷XML DOM方法:
XML DOM还提供了一系列方法来操作XML文档,常用的方法是:
x.getElementsByTagName(name) //用来获取指定标记名称的所有元素
x.appendChild(node) //向x插入子节点
x.removeChild(node) //从x删除子节点

3)读取XML文档:
⑴获取元素的值:
下面的代码将从xml中获取第一个<title>元素的文本:
txt=xmlDoc.getElementsByTagName("title")[0].childNodes[0].nodeValues;
getElementsByTagName()方法总会返回数组。
⑵访问节点:
可以通过3种方法来访问节点,通过getElementsByTagName()方法、通过循环遍历节点树以及通过利用节点的关系在节点树中导航。示例:
xmlDoc=loadXMLDoc("books.xml");
x=xmlDoc.getElementsByTagName("title");
for(i=0;i<x.length;i++){
document.write(x[i].childNodes[0].nodeValue);
document.write("<br/>");
}
nodeName属性是节点的名称,节点的nodeType属性是节点的类型。通过使用属性节点的nodeValue属性或getAttribute()方法都可以获取属性的文本值,还可以应用getAttributeNode()方法结合nodeValue属性来获得节点的属性值。
可以通过x.parentNode.nodeName来获取父节点的名称。
不同浏览器之间在处理空白和换行的方式是有差别的,Firefox及IE外的浏览器把空白或换行当作文本节点,这会在firstChild、lastName、nextSibling、previousSibling时产生问题,为了避免定位到空的文本节点,需要用函数检查节点的类型:
function get_nestSibling(n){
y=n.nextSibling;
while(y.nodeType!=1){
y=y.nextSibling;
}
return y;
}

4)写入XML文档:
⑴改变节点内容:
在DOM中,每种成分都是节点。元素节点没有文本值,文本存储在子节点中,这个节点称为文本节点。改变元素文本的方法是改变子节点的值。
x.nodeValue="Hello World";
遍历文本节点的方法为:
x=xmlDoc.getElementsByTagName("title");
for(i=0;i<x.length;i++){
x[i].childNodes[0].nodeValue="Unavaliable";
document.write(x[i].childNodes[0].nodeValue);
document.write("<br/>");
}
在DOM中,属性也是节点,属性节点拥有文本值,改变属性的值的方法就是改变它的文本值,可以通过使用setAttribute()方法来实现:
x[0].setAttribute("category","child");
如果属性不存在,则创建一个拥有指定名称和值的新属性。
也可以通过属性节点的nodeValue来改变属性的值:
y=x.getAttributeNode("category");
y.nodeValue="child";
⑵创建节点:
创建节点包括创建元素节点、属性节点、文本节点、CDATA块和注释节点。
·创建新的元素节点使用createElement()方法:
newel=xmlDoc.createElement("edition");
x=xmlDoc.getElementsByTagName("book")[0];
x.appendChild(newel);
·创建新的属性节点使用createAttribute()或setAttribute()方法:
newatt=xmlDoc.createAttribute"edition");
newatt.nodeValue="first";
x=xmlDoc.getElementsByTagName("title");
x[0].setAttributeNode(newatt);
setAttribute()方法可以在属性不存在情况下创建新的属性:
x[0].setAttributeNode("edition","first");
·创建新的文本节点使用createTextNode()方法:
newel=xmlDoc.createElement("edition");
newtext=xmlDoc.createTextNode("first");
newel.appendChild(newtext);
x=xmlDoc.getElementsByTagName("book")[0];
x.appendChild(newel);
·创建新的CDATA块节点使用createCDATASection()方法:
newCDATA=xmlDoc.createCDATASection("Special Offer & Book Sale");
x=xmlDoc.getElementsByTagName("book")[0];
x.appendChild(newCDATA);
·创建注释节点使用createComment()方法:
newComment=xmlDoc.createComment("Revised March 2008");
x=xmlDoc.getElementsByTagName("book")[0];
x.appendChild(newComment);
⑶添加节点:
添加节点包括追加节点、插入节点、添加新属性和向文本节点添加文本。appendChild()方法向已存在的节点添加子节点,新节点会追加到任何已存在的子节点之后。
insertBefore()方法用于在指定的子节点之前插入节点:
newNode=xmlDoc.createElement("book");
x=xmlDoc.documentElement;
y=xmlDoc.getElementsByTagName("book");
x.insertBefore(newNode,y[3]);
insertData()方法可将数据插入已有的文本节点中,方法带有2个参数,offset指定在何处插入字符,string指定要插入的字符串:
x=xmlDoc.getElementsByTagName("title")[0].childNodes[0];
x.insertData(0,"Hello ");
⑷克隆节点:
cloneNode()方法看创建指定节点的副本,方法有一个参数,true或false,该参数指示被复制的节点是否包括原节点的所有属性和子节点:
x=xmlDoc.createElement("book")[0];
cloneNode=x.cloneNode(true);
xmlDoc.documentElement.append(cloneNode);
⑸替换节点:
指替换节点和替换文本节点中的数据。replaceChild()方法用于替换节点:
x=xmlDoc.documentElement;
newNode=xmlDoc.createElement("book");
y=xmlDoc.getElementsByTagName("book")[0];
x.replaceChild(newNode,y);
replaceData()方法用于替换文本节点中的数据,方法有三个参数,offset用于指定在何处开始替换字符,length用于指定要替换多少字符,string用于指定要插入的字符串。示例:
x=xmlDoc.getElementsByTagName("title")[0].childNodes[0];
x.replaceData(0,8,"Hello");
用nodeValue属性来替换文本节点中数据更加容易。示例:
x=xmlDoc.getElementsByTagName("title")[0].childNodes[0];
x.nodeValue="Hello";
⑹删除节点:
删除节点包括删除元素节点、删除当前节点、删除文本节点、清空文本节点、根据名称删除属性节点和根据对象删除属性节点。
·删除元素节点:
removeChild()方法用于删除指定的节点。当一个节点被删除,其所有子节点也会被删除。
lastNode=get_lastchild(xmlDoc.documentElement);
delNode=xmlDoc.documentElement.removeChild(lastNode);
·删除当前节点:当已定位需要删除的节点后,就可以通过使用parentNode属性和removeChild()方法来删除此节点。
x=xmlDoc.getElementsByTagName("book")[0];
x.parentNode.removeChild(x);
·删除文本节点:
x=xmlDoc.getElementsByTagName("title")[0];
y=x.childNodes[0];
x.removeChild(y);
·清空文本节点:
nodeValue属性可用于改变或清空文本节点的值。
x=xmlDoc.getElementsByTagsName("title")[0].childNodes[0];
x.nodeValue="";
·根据名称删除属性节点:
removeAttribute(name)方法用于根据名称删除属性节点。
x=xmlDoc.getElementsByTagName("book")[0];
x[0].removeAttribute("category");
·根据对象删除属性节点:
removeAttributeNode(node)方法通过使用node对象作为参数,来删除属性节点。
x=xmlDoc.getElementsByTagName("book");
for(i=0;i<x.length;i++){
while(x[i].attributes.length>0){
attnode=x[i].attributes[0];
old_att=x[i].removeAttributeNode(attnode);
}
}

5. 定义XML架构:

架构是XML文档内容的向导,可以使用两种方法表示,DTD和XML架构。

1)DTD文件:
DTD是一个文件类型定义Document Type Definition。
⑴包含DTD:
将DTD与一个XML文件结合起来,放置一个引用行:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE rootelement [definition]>
这里声明数据的根元素rootelement,也可以定义XML数据中许可的元素:
<!DOCTYPE rootelement SYSTEM "/path/to/filename.dtd">
其中,filename.dtd是要包含的文件,/path/to/是指向服务器上的文件URI。
既然XML文件引用的DTD,那么这个文件必须创建,这个过程称为文档建模。
⑵定义元素:
DTD定义了标记语言中使用的所有元素和属性,语法为:
<!ELEMENT name TYPE>
其中,name是新标记的名字,将包含类型为TYPE的内容。

类型

关联元素

(#PCDATA)

一般文本,特指已解析字符数据

(#CDATA)

一般文本,特指为解析字符数据

EMPTY

ANY

任何数据

比如可以定义如下元素:
<!ELEMENT name (#PCDATA)>
<!ELEMENT size (#PCDATA)>
<!ELEMENT picture EMPTY>
<!ELEMENT product (name,size,picture)>
还可以通过使用OR字符来进一步扩展该元素定义,一个元素可以包含其他元素:
<!ELEMENT thing (other_element|#PCDATA|EMPTY)>
⑶定义属性:
要允许元素有属性,需要在DTD内制作一张属性表,但只有在定义了对应元素之后才可以。
<!ATTLIST element_name attr_name attr_type attr_description>
其中,attr_name域是一个文本串,如color或alignment;attr_type指定属性的格式:

类型

意义

示例

CDATA

字符数据

一般文本

NMTOKEN

名字令牌

字符串(不包含空白字符)

NMTOKENS

若干名字令牌

由空白字符分开的字符串

ID

唯一标识符

文本或者数字,对每个元素而言都是唯一的

还有一种的属性取值是枚举列表:
<!ATTLIST element_name attr_name (value1|value2) "value1">
代码中声明元素有属性attr_name,有两个可能取值value1或者value2,value1是默认值。
还可以为属性的功能进行进一步定义,描述包括#REQUIRED、#IMPLIED、#FIXED,分别表示每个元素必须使用该属性、该属性可选、属性的值一成不变。示例:
<!ATTLIST picture filename NMTOKEN #REQUIRED>
⑷编写DTD文档:示例collection.dtd
<!--Script 13.4 - collection.dtd-->
<!ELEMENT collection (book+)>
<!ELEMENT book (title,author+,year,pages?,chapter*,cover?)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT year (#PCDATA)>
<!ELEMENT pages (#PCDATA)>
<!ELEMENT chapter (#PCDATA)>
<!ELEMENT cover EMPTY>
<!ATTLIST title edition NMTOKEN #IMPLIED>
<!ATTLIST chapter number NMTOKEN #IMPLIED pangs NMTOKEN #IMPLIED>
<!ATTLIST cover filename NMTOKEN #REQUIRED>
代码中,声明第一个元素collection是根元素,只包含一个或多个book元素;而book元素包含最多6个其他标记,其中title、author、year是必需的,chapter是可选的且可以出现任意多次,pages和cover都是可选的且最多可以出现一次,autror允许出现多次。cover元素总是空的,元素信息存储在必需的filename属性中。title属性有一个可选元素,chapter元素有number和pages两个可选的属性。
⑸XML文件中引用DTD文件:
XML允许用户编写DTD文档模型,或者使用网上免费获取的他人设计的文档模型。在XML中引用DTD文档的示例为:
<?xml version="1.0" encoding="utf-8" ?>
<!--Script 13.5 - books3.xml-->
<!DOCTYPE collection SYSTEM "collection.dtd">
<collection>
......
</collection>

2)使用XML架构:
XML架构XML Schema是一种用于定义建立XML数据的工具,称为XML Scheme Document,缩写为XSD。XSD是用XML编写的,文件扩展名为.xsd。
⑴定义元素:
XSD中定义元素的格式为:
<xs:element name="some_name" type="some_type"/>
每个元素必须有一个名字,这样就创建了对应的XML使用的元素,xs标识了定义元素的命名空间。而type为对应的数据类型,包括以下预定义类型:

xs:string

xs:integer

xs:boolean

xs:decimal

xs:date

可能的类型有19个标准类型,还有许多定义好的派生类型。示例:
<xs:element name="name" type="xs:string"/>
还可以使用element标记的属性来定制元素,其中default属性声明默认值,fixed表明元素仅能有一个值。示例:
<xs:element name="edition" type="xs:integer" default="1"/>
可以通过使用minOccurs与maxOccurs属性来限制元素在上下文中出现的次数。示例:
<xs:element name="size" type="xs:string" minOccurs="1" maxOccurs="10"/>
上述代码表明size元素至少要出现一次,但最多出现10次,并判定任何不包含size元素的XML非法。minOccurs与maxOccurs属性的默认值都为1,这时对应的元素必须出现且只能出现一次。如果允许任意次出现,则0作为minOccurs值,unbounded作为maxOccurs值:
<xs:element name="picture" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
⑵简单类型与复杂类型:
可以使用xs:simpleType或者xs:complexType来创建用户定义类型,是简单类型及其他默认类型的变体得到。定义复杂类型时,必须表明该类型是如何组成的。
⑶创建属性:
使用xs:attribute来声明元素属性,并提供名字与类型。示例:
<xs:attribute name="price" type="xs:decimal"/>
⑷编写XSD的示例:
<?xml version="1.0" encoding="utf-8" ?>
<!--Script 13.5 - collection.xsd-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="collection">
<xs:complexType>
<xs:sequence>
<xs:element name="book" type="bookType" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="bookType">
<xs:sequence>
<xs:element name="title" type="titleType" />
<xs:element name="author" type="xs:string" minOccurs="1"
maxOccurs="unbounded"/>
<xs:element name="year" type="xs:int" />
<xs:element name="pages" type="xs:int" minOccurs="0" maxOccurs="1"/>
<xs:element name="chapter" type="chapterType" minOccurs="0"
maxOccurs="unbounded"/>
<xs:element name="cover" type="coverTyle" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:complexTyle>
<xs:complexType name="coverType">
<xs:attribute name="filename" type="xs:string"/>
</xs:complexTyle>
<xs:complexType name="chapterType">
<xs:simpleContent>
<xs:extension base="xs:string" />
<xs:attribute name="number" type="xs:int"/>
<xs:attribute name="pages" type="xs:int"/>
</xs:extension>
</xs:sequence>
</xs:complexTyle>
<xs:complexType name="titleType">
<xs:simpleContent>
<xs:extension base="xs:string" />
<xs:attribute name="edition" type="xs:int"/>
</xs:extension>
</xs:sequence>
</xs:complexTyle>
</xs:schema>
⑸XML引用XSD文件:
XML可以使用外部的XSD文件,这需要在XML文件的根标记上引用XSD。示例:
<?xml version="1.0" encoding="utf-8" ?>
<collection xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="collection.xsd">
......
</collection>
属性xmlns指明了该XML架构实例的命名空间,然后给出了XSD文件的路径。
XML也可以使用内联式XSD。

6. 使用PHP解析XML文件:

一旦XML数据存在后,应用程序就能解析这些数据。XML解析程序为解析器parse,解析器获取XML文件,然后将其分散成各种片段。有两种解析器,一种是基于事件的,一种是基于树形结构的。

1)使用Expat解析XML:
Expat是基于事件的解析器,在事件发生时调用其回调函数,解析XML时发生的基本事件包括发现开始标记、发现标记间的内容、发现闭合标记。使用Expat解析XML有4个步骤。
⑴创建一个新解析器:
$p=xml_parser_create();
⑵确定处理事件要使用的函数:
处理开始和闭合标记使用xml_set_element_handler()函数:
xml_set_element_handler($p,'open_element_fx','close_element_fx');
对于元素内容,使用xml_set_character_data_handler()函数:
xml_set_character_data_handler($p,'data_fx");
⑶解析文件:
解析文件使用xml_parse()函数:
xml_parse($p,$data,[$stop]);
⑷释放解析器占用资源:
xml_parser_free($p);
示例:expat.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>XML Expat Parser</title>
</head>
</body>
<?php #Script 14.7 -expat.php
function handler_open_element($p,$element,$attributes){
$attributes=array('NUMBER'=>1,'PAGES'=>'34');
switch($element){
case 'BOOK':echo '<div>';break;
case 'CHAPTER':echo '<p>Chapter {$attributes['NUMBER']}: ';break;
case 'COVER':
$iamge=@getimagesize($attribute['FILENAME']);
echo '<img src=\"{$attributes['FILENAME']}\" $image[3] border=\"0\"><br/>";
break;
case 'TITLE':echo '<h2>";break;
case 'YEAR':
case 'AUTROR':
case 'PAGES':
echo '<span class="label">'.$element.'</span>: ';
break;
}
}
function handler_close_element($p,$element){
switch($element){
case 'BOOK':echo '</div>';break;
case 'CHAPTER':echo '</p> ';break;
case 'TITLE':echo '</h2>";break;
case 'YEAR':
case 'AUTROR':
case 'PAGES':
echo '<br/>';
break;
}
}
function handle_character_data($p,$cdata){
echo $cdata;
}
$p=xml_parser_create();
xml_set_element_handler($p,'handle_open_element','handle_close_element');
xml_set_character_data_handler($p,'handle_character_data');
$file='bools.xml';
$fp=@fopen($file,'r') or die("<p>Could not open a file called '$file'.</p></body></html>");
while($data=fread($fp,4096)){
xml_parse($p,$data,feof($fp));
}
xml_parser_free($fp);
?>
</body>
</html>
上述代码要使用fopen()函数打开文件,然后循环读取整个文件,并将收到的数据传送给解析器。一旦读完整个文件,则主循环停止,注销解析器。上述程序把XML文件解析成网页HTML文件并把相关信息显示出来。

2)使用SimpleXML:
SimpleXML是基于DOM的解析器,也就是基于树形结构的。SimpleXML解析器首先要使用simplexml_load_file()函数加载XML到一个对象中:
$xml=simplexml_load_file('filename.xml");
如果在一个字符串中存有XML数据,可以使用simplexml_load_string()来提取。然后有多种访问XML数据的方法。要引用特定元素,使用$xml->elementname格式,如果有相同的多个元素可以像数组样对待。对于嵌套元素,可以继续使用这种方法。
使用foreach循环,可以访问树中的每一个元素:
foreach ($xml->product as $product){}
而访问属性,使用$xml->elementname['attribute'];
SimpleXML可以使用addChild()与addAttribute()方法添加新元素和新属性,也可以使用赋值方法改变元素的值:
$xml->product->name="Heavy T-Shirt";
SimpleXML还支持XPath。使用DOM解析器会比使用SAX解析器需要更多服务器内存,因为需要将整个XML数据都加载到一个变量中。
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>SimpleXML Parser</title>
</head>
</body>
<?php #Script 14.8 -simplexml.php
$xml=simplexml_load_file(books.xml);
foreach($xml->book as $book){
echo "<div><h2>$book->title";
if(isset($book->title['edition'])){
echo " (Edition {$book->title['edition']})";
}
echo '</h2>';
foreach($book->author as $author){
echo "<span class=\"label\">Author</span>:$author<br/>;
}
echo "<span class=\"label\">Published:</span>$book->year<br/>;
if(isset($book->pages)){
echo "<span class=\"label\">Pages:</span>$book->pages<br/>;
}
if(isset($book->chapter)){
echo 'Table of Contents<ul>';
foreach($book->chapter as $chapter){
echo '<li>';
if(isset($chapter['number'])){
echo "Chapter {$chapter['number']}: ";
}
echo $chapter;
if(isset($chapter['pages'])){
echo "({$chapter['pages']} Pages) ";
}
echo '</li>';
}
echo '</ul>';
}
if(isset($book->cover)){
$image=@getimagesize($book->cover['filename']);
echo "<img src=\"{$book->cover['filename']}\" $image[3] border=\"0\"/><br/>
}
echo '</div>';
}
?>
</body>
</html>
上述代码同样是解析XML文件并把内容显示在网页中,不同的是采用了SimpleXML解析器。

3)创建RSS源:
RSS是网站提供本站内容列表的方式,通常该列表至少包含文章标题及其描述。用户使用RSS客户端访问这些RSS源,如果想进一步阅读该文章,要点击文章的链接,这样会将其带到完全的网页显示中。
RSS源是一些已经建立的标记的XML文件,以rss为根元素,rss根元素有一个必需的version属性,应使用最新的RSS版本来设置此值。所有的RSS文档开始部分为:
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
此后,所有的RSS文件都会包含一个单独的channel元素,其他的元素都嵌套在里面,如title、description和link,以上元素都是用来描述RSS源的。示例;
<channel>
<title>Name of the RSS Feed</title>
<description>Description of the RSS Feed</description>
<link>Link to the Web site</link>
这三个元素是channel元素中必需有的。还有一些可选的元素,如language、copyright、managingEdition(Email)、webMaster(email)等。
channel元素也包含多个item元素,每个item元素都是一条内容。item元素也有title、description、link以及其他嵌套元素。
<item>
<title>Article Title</title>
<description>Article Description</description>
<link>Link to the Article</link>
</item>
item的子元素中没有一个是必需的,除了title与description两者必须有一个,也可以使用author与pubDate。pubDate必须按照RFC822规定的格式,如Web,01 Nov 2012 16:45:23 GMT。

7. 可缩放矢量图形SVG:

SVG广泛用于定义图片和动画,使用XML来表示。SVG图形可以缩放而不会使图形失真,尺寸更小,可压缩性更强,可在任何分辨率下被高质量地打印,并可被很多工具读取和修改。SVG图形中的文本是可以搜索的,可以与JavaScript一起运行。
SVG通过定义必要的线和形状来创建一个图形,也可以修改已有的位图,或者将这两种方式结合起来。图形和其组成部分可以变形,可以合并,也可以通过滤镜改变外观,支持渐变和旋转。一个简单的SVG只包含svg根元素,以及基本的形状元素,另外还有一个g元素,用来把若干个基本形状标记成一个组。示例:
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" fill="gray" />
<circle cx="150" cy="100" r="80" fill="black" />
<text x="150" y="125" font-size="60" text-anchor="middle" fill="white">SVG</text>
</svg>
SVG的元素和属性必须按标准格式书写,是区分大小写的,其中的属性必须用引号括起来,即使是数值也不例外。为了明确SVG版本,svg根元素中的version和baseProfile两个属性必须要写,SVG必须始终绑定正确的命名空间。
SVG规范提供了gzip压缩的SVG文件格式,这类文件的后缀是.sgvz,但一些服务器和浏览器不支持这种压缩文件格式。

1)SVG的引用:
一般情况下,不会直接在浏览器中加载.svg文件,更多是在一个HTML页面中嵌入SVG。有几种方法可以用于SVG在HTML页面中显示,将SVG作为图像导入、将SVG放入iframe中导入、将SVG作为object对象导入、将SVG作为一个data URI导入,以及使用内联SVG。
⑴将SVG作为图像导入:
这是将SVG导入HTML文档最简单的方法。用矢量编辑工具创建一个图形,将图形导出为.svg格式的文件,然后把它加到一个普通<img>标记内。示例:
<img src="example.svg" alt="My SVG example">
也可以把.svg文件作为一个background-image用CSS导入:
#my-image{
background:url("example.png");
background-image:url("example.svg");
}
注意要加一个备用的.png图像,以防浏览器无法显示svg。但这种方法无法使用CSS对SVG图形进行更多控制。
⑵使用object或iframe导入SVG图形:
<object type="image/svg+xml" data="example.svg" class="example">My SVG</object>
代码中通过data属性链接了要导入的.svg文件,还为<object>元素加入一个class属性,用来定义CSS样式,样式定义为:
.example{display:block;margin:5em auto;border-radius:10px;}
还可以把.svg文件嵌入到一个<iframe>框架内:
<iframe src="example.svg" class="example"></iframe>
在<iframe>框架内也可以使用CSS来控制SVG的样式。
⑶将SVG作为data URI导入:
可以把SVG转成一个data URI,再把它作为data导入。可以通过在线或离线工具来进行转换,然后把转换得到的data URI加入到一个<img>或<object>标记内,或是放到CSS中:
<img src="data:image/svg+xml;base64,[data]">
background:url(data:image/svg+xml;base64,[data]);
<object type="image/svg+xml" data="data:image/svg+xml;base64,[data]">My SVG</object>
上述代码中的[data],可以导入由转换工具返回的data内容,此时变为如下形式:
<object type="image/svg+xml" data="data:image/svg+xml;base64,PCEtLQo8...mc+Cg=="> My SVG </object>
⑷使用内联SVG:
SVG可以直接在HTML中嵌入:
<body>
<svg version="1.1" baseProfile="full" width="300" height="200"
xmlns="http://www.w3.org/2000/svg" class="example">
<rect width="100%" height="100%" fill="green" />
</svg>
</body>
对于简单的图形,使用内联SVG比较方便。但多数情况下,HTML代码本身就很复杂,需要更好地模块化这些内容,把SVG移到单独的文件中存放更稳妥。

2)SVG的坐标系统:
SVG使用的坐标系统以页面左上角为坐标原点(0,0),坐标以像素为单位,x正方向向右,y轴正方向向下。
基本上,SVG文档里的1px等同于设备上的1像素,但这种情况可以改变。CSS可以定义字体的绝对大小和相对大小,SVG也可以定义绝对大小(如pt或cm),也能使用相对大小(只需给出数字,采用用户的单位)。默认情况下,用户单位等同于屏幕单位,如果要改变这种设定,有多种方法。如下述代码定义了100px X 100px的SVG画布:
<svg width="100" height="100">
这里的用户单位等同于屏幕单位。但使用下述代码:
<svg width="200" height="200" viewBox="0 0 100 100">
这里定义的画布为200px X 200px,但是viewBox属性定义了画布上显示的区域为100px X 100px,因此形成放大两倍的效果。除了缩放,坐标系统还可以旋转、倾斜、翻转。

3)SVG内置基本图形:
SVG有一些预定义的图形元素,矩形、圆形、椭圆、线、折线、多边形和路径。
⑴矩形Rectangle:
利用<rect>标记可绘制矩形,以及矩形的变种。示例:
<rect width=250" height="100" x="10" y="10" rx="10" ry="20"
style="fill:#2F9AFE;stroke:#DF3D82;stroke-width:4px;fille-opacity:0.5;stroke-opacity:0.9;"/>
其中,属性x为x坐标;属性y 为y坐标;属性rx为x轴方向的圆角;属性ry为y轴方向的圆角;fill为填充颜色;stroke为边框颜色;stroke-width为边框宽度;fill-opacity为填充透明度;stroke-opacity为边框透明度。
颜色可以使用#开头的十六进制字符串,也可以使用rgb(r,g,b)函数,其中参数为10进制数值,一些颜色可以使用颜色名称,如red。其他可用属性还有transform="rotate(45)",定义变换而旋转45度;stroke-dasharray="5 3",定义边框使用的dash线型。
⑵圆形Circle:
利用<circle>标记可绘制圆形,示例代码:
<circle cx="70" cy="70" r="60" style="fill:#2E9AFE;stroke:#DF3D82;stroke-width:2px;"/>
其中,属性cx为圆心x坐标;属性cy为圆心y坐标;属性r为圆形的半径。其中也可以使用变形属性,如transform="scale(0.3,1)",进行了横向压缩。
⑶椭圆形Ellipse:
利用<ellipse>标记可绘制SVG椭圆形,椭圆形的高和宽不相等,示例:
<ellipse cx="110" cy="60" rx="100" ry="50"
style="fill:#2E9AFE;stroke:#DF3D82;stroke-width:2;" />
其中,属性cx为圆心x坐标;属性cy为圆心y坐标;属性rx为椭圆的水平半径;ry为椭圆的垂直半径。也可以使用变形属性transform和边框使用的dash线型stroke-dasharray。
⑷直线Line:
利用<line>标记可绘制直线。示例:
<line x1="0" y1="0" x2="130" y2="150" style="stroke:#2E9AFE;stroke-width:3;" />
⑸折线Polyline:
利用<polyline>标记可以绘制折线,折线其实是多个点连接起来的直线。示例:
<polyline points="10,10 150,120 100,180 200,170"
style="fill:none;stroke:#2E9AFE;stroke-width:3;" />
⑹多边形Polygon:
利用<polygon>标记可绘制多边形,要求不少于3个边。示例:
<polygon points="50,20 100,40 100,80 60,100 20,80 20,40"
style="fill:#2E9AFE;stoke:#DF3D82;stroke-width:1;" />
⑺路径Path:
利用<path>标记可以绘制曲线、直线、弧度组成的复杂路径或图形。路径的命令有:

字母

助记符

描述

示例

M

moveto

移动画笔至给定的坐标

M 23,117

L

lineto

从当前点画一条线到给定的位置

L 300,312

H

horizontal lineto

画一条水平线到给定的x坐标

H 312

V

vertical lineto

画一条垂直线到给定的y坐标

Y 23

Z

closepath

关闭路径

Z

C

curveto

曲线至

C 20,-17 30,-8 40,40

S

Smooth curveto

平滑曲线至

S 30,-8 40,40

Q

quadratic Bezier curve

二维贝塞尔曲线

Q 20,-17 40,40

T

smooth quadratic Bezier curve

平滑二维贝塞尔曲线

T 30,45

A

elliptical arc

椭圆弧

A 150,150 0 1 1 40 40

以上路径命令,大写字母表示定位方式使用绝对位置,小写则表示使用相对位置。示例:
<path d="M 10,10 C 10,27 48,60 58,60 68,60 70,44 45.5,27 45,10 87,10 87,10"
style="fill:none;stroke:#000000;stroke-width:1pt" />
<path d="m 129.5,9.2 c -3.4,0.1 -5.1,0.9 -6.2,6.1 -1.3,5.8 3.9,17 3.9,17 0,0 -6.2,0.6 -9.5,0
C 114.3,31.8 114.3,31.5 114.3,31.5 l 1.9,5.2 -2.2,3.2 c 0,0 5.9,-0.6 6.8,-0.6 0.9,0 3.5,0 6.3,0.1 0,5.4 -1.7,22.1 -1.7,22.1 0,0 2.8,-2.4 5.5,-2.4 2.7,0 5.5,2.4 5.5,2.4 0,0 -1.7,-16.7 -1.7,-22.1 2.7,-0.1 5.3,-0.1 6.3,-0.1 0.9,0 6.8,0.6 6.8,0.6 l -2.2,-3.2 1.9,-5.2 c 0,0 -0.0,0.3 -3.2,0.9 -3.2,0.6 -9.5,0 -9.5,0 0,0 5.2,-11.1 3.9,-17.0 -1.3,-5.8 -3.2,-6.1 -7.8,-6.1 -0.5,0 -1.0,-0.0 -1.5,0 z m 1.5,2.8 c 1.4,0.0 2.4,0.3 3.8,1.3 2.1,4.7 0.5,9.4 -1.9,13.5 -0.5,0.9 -1.2,1.8 -1.9,2.7 -0.6,-0.9 -1.3,-1.8 -1.9.-2.7 -2.4,-4.0 -4.0,-8.7 -1.9,-13.5 0.6,-0.7 2.8,-1.3 3.8,-1.3 z" fill="#b5b5b5" stroke="#000000" stroke-width="1" />
绘制路径的代码可能会很复杂,建议使用SVG编辑器来创建复杂的图形。
⑻文字Text:
利用<text>标记来绘制文字。示例:
<text x="20" y="30" fill="#DF3D82" font-size="20">HELLO</text>
其中,属性x定义文字的起始x坐标;属性y定义文字的起始y坐标。属性中可以使用transform变形。

4)SVG滤镜:
滤镜允许在图形上添加特效,这样很容易在客户端生成和修改图形,滤镜不会破坏原有文档的结构。使用<filter>标记定义滤镜,需要时在图形或容器上添加filter属性引用相关滤镜。
滤镜元素包含很多滤镜原子操作,并产生图形输出。大多数原子操作生成的结果都是一个RGBA图片。每个原子操作的输入既可以是原图形,也可以是其他原子操作的结果。
<filter>元素标记使用必需的id属性来定义向图形应用哪个滤镜,<filter>元素标记必须嵌套在<defs>元素标记内。示例:
<?xml version="1.0" encoding="UTF-8" ?>
<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="Gaussian_Blur">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" />
</filter>
</defs>
<ellipse cx="200" cy="150" rx="70" ry="40"
 style="fill:#ff0000;stroke:#000000;stroke-width:2;filter:url(#Gaussian_Blur)" />
</svg>
代码中,<filter>元素标记的id属性定义了滤镜的名称,filter:url属性用来把元素链接到滤镜,而滤镜效果通过<feGaussionBlur>标记来定义,fe后缀可用于所有的滤镜,其中的stdDeviation属性定义模糊的程度,而in="SourceGraphic"定义了由整个图形创建效果。
<filter>元素具有的属性有:
⑴filterUnits="userSpaceOnUse|objectBoundingBox":
这个属性定义了x、y、width和height使用的坐标空间,该属性有两个值,userSpaceOnUse表示使用引用该<filter>元素的元素的用户坐标系统;而objectBoundingBox表示使用引用该<filter>元素的元素的包围盒的百分比作为取值范围,这是默认值。
⑵x、y、width、height:
这些属性定义了滤镜起作用的矩形范围,滤镜效果不会应用在超过区域的点上。x、y的默认值是-10%,width和height的默认值是120%。
⑶filterRes:
该属性定义了中间缓存区域的大小,也即定义了缓存图片的质量。一般情况下不需要提供这个值,浏览器会选择合适的值。通常,滤镜效果区应定义与背景正好点和点一一对应。
⑷primitiveUnits="userSpaceOnUse|objectBoundingBox":
这个属性定义每个原子操作中坐标和长度使用的坐标空间,属性值有两个,默认为userSpaceOnUse。
⑸xlink:href="<iri>":
该属性用于当前<filter>元素中引用其他的<filter>元素。
⑹result:
该属性用于存放该步操作的结果。指定了result以后,同一个<filter>元素的其他后续操作都可以使用in属性来指定其为输入。如果省略了这个值,则只能作为紧挨着的下一步操作的隐式输入。如果紧挨着的下一步操作已经用in属性指定了输入,则以in指定的为准。
⑺in:
表示该步操作的输入。省略in属性将会默认使用前一步的结果作为本步的输入,如果省略的是第一步的in,则会使用SourceGraphic作为值。
in属性可以引用result属性存放的值,也可以指定下列6个特殊的值:
·SourceGraphic:代表使用当前图形元素作为操作的输入。
·SourceAlpha:代表使用当前图形元素的Alpha值作为操作的输入。
·BackgroundImage:代表使用当前背景截图作为操作的输入。
·BackgroundAlpha:代表使用当前背景截图的Alpha值作为操作的输入。
·FillPaint:使用当前图形元素fill属性的值作为操作的输入。
·StrokePaint:使用当前图形元素stroke属性的值作为操作的输入。
<filter>元素只会继承自己父节点的属性,并不会继承引用该<filter>元素的属性。
示例:
<?xml version="1.0" encoding="UTF-8" ?>
<svg width="7.5cm" height="5cm" viewBox="0 0 200 120"
version="1.1" xmlns="http://www.w3.org/2000/svg">
<title>SVG filter</title>
<desc>3D effect</desc>
<defs>
<filter id="myFilter" filterUnits="userSpaceOnUse"
x="0" y="0" width="200" height="120">
<feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blur" />
<feOffset in="blur" dx="4" dy="4" result="offsetBlue" />
<feSpecularLighting in="blur" surfaceScale="5" specularConstant="0.75"
specularExponent="20" lighting-color="#bbbbbb" result="specOut">
<fePointLight x="-5000" y="-10000" z="20000" />
</feSpecularLighting>
<feComposite in="specOut" in2="SourceAlpha" operator="in" result="specOut" />
<feComposite in="SourceGraghic" in2="specOut" operator="arithmetic"
k1="0" k2="1" k3="1" k4="0" result="litPaint" />
<feMerge>
<feMergeNode in="offsetBlue" />
<feMergeNode in="litPaint" />
</feMerge>
</filter>
</defs>
<rect x="1" y="1" width="198" height="118" fill="#888888" stroke="blue" />
<g filter="url(#myFilter)">
<g>
<path fill="none" stroke="#D90000" stroke-width="10"
d="M 50,90 C 0,90 0,30 50,30 L 150,30 C 200,30 200,90 150,90 z" />
<path fill="#D90000"
d="M 60,80 C 30,80 30,40 60,40 L 140,40 C 170,40 170,80 140,80 z" />
<g fill="#FFFFFF" stroke="black" font-size="45" font-family="Verdana">
<text x="52" y="76">SVG</text>
</g></g></g>
</svg>
代码中共使用了5次滤镜特效,feGaussianBlur为高斯模糊处理,feOffset是平移,feSpecularLighting是图片表面进行光线处理,feComposite是对不同的缓存层进行组合,使用了两次,feMerge是合并不同的层,这通常是最后一步,融合各个缓存的层生成最终的图片并渲染呈现。

5)SVG渐变:
渐变是指从一种颜色到另一种颜色的平滑过渡。可以把多个颜色的过渡应用到同一个元素上。SVG主要有线性渐变和放射渐变。
⑴线性渐变:
<linearGradient>标记可用来定义SVG的线性渐变。<linearGradient>标记必须嵌套在<defs>标记内。线性渐变可被定义为水平、垂直或角形的渐变:
·当y1和y2相等时,而x1和x2不同时,可创建水平渐变。
·当x1和x2相等时,而y1和y2不同时,可创建垂直渐变。
·当x1和x2不同,且y1和y2也不同时,可创建角形渐变。
水平渐变示例:
<?xml version="1.0" encoding="UTF-8" ?>
<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="orange_red" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1"/>
<stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1"/>
<linearGradient>
</defs>
<ellipse cx="200" cy="190" rx="85" ry="55" style="fill:url(#orange_red)" />
</svg>
代码中,<linearGradient>标记的id属性为渐变定义了一个名称,使用fill:url(#orange_red)属性把ellipse元素链接到此渐变。<linearGradient>标记的x1、x2、y1、y2属性定义渐变开始和结束的位置。渐变的颜色范围可由两种或多种颜色组成,每种颜色通过一个<stop>标记来规定,offset属性用来定义渐变的开始和结束位置。
垂直渐变示例:
<?xml version="1.0" encoding="UTF-8" ?>
<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="orange_red" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1"/>
<stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1"/>
<linearGradient>
</defs>
<ellipse cx="200" cy="190" rx="85" ry="55" style="fill:url(#orange_red)" />
</svg>
⑵放射渐变:
<radialGradient>标记用来定义放射渐变,<radialGradient>标记必须嵌套在<defs>标记中。
<?xml version="1.0" encoding="UTF-8" ?>
<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient id="grey_blue" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:rgb(200,200,200);stop-opacity:0"/>
<stop offset="100%" style="stop-color:rgb(0,0,255);stop-opacity:1"/>
<radialGradient>
</defs>
<ellipse cx="230" cy="200" rx="110" ry="100" style="fill:url(#grey_blue)" />
</svg>
代码中,<radialGradient>标记的id属性为渐变定义了一个唯一的名称,fill:url(#grey_blue)属性把<ellipse>元素链接到此渐变。cx、cy和r属性定义外圈,而fx和fy定义内圈。渐变的颜色可由两种或多种颜色组成,每种颜色通过一个<stop>标记来规定,其offset属性用来定义渐变开始和结束位置。

6)SVG与HTML:
SVG可以嵌套在HTML文件中,尤其在HTML5中,SVG好像是其一部分。示例:
<!DOCTYPE html>
<html>
<head>
<title>HTML5 and SVG</title>
</head>
<body>
<h1>Radial Gradient</h1>
<svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient id="grey_blue" cx="20%" cy="40%" r="50%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:rgb(200,200,200);stop-opacity:0"/>
<stop offset="100%" style="stop-color:rgb(0,0,255);stop-opacity:1"/>
<radialGradient>
</defs>
<ellipse cx="230" cy="200" rx="110" ry="100" style="fill:url(#grey_blue)" />
</svg>
</body>
</html>

Copyright@dwenzhao.cn All Rights Reserved   备案号:粤ICP备15026949号
联系邮箱:dwenzhao@163.com  QQ:1608288659