xml

XML---可扩展标记语言

第一部分:XML语言介绍

什么是 XML?

·  XML 指可扩展标记语言(EXtensible Markup Language

·  XML 是一种标记语言,很类似 HTML

·  XML 的设计宗旨是传输数据,而非显示数据

·  XML 标签没有被预定义。您需要自行定义标签

·  XML 被设计为具有自我描述性

·  XML W3C 的推荐标准

XML 与 HTML 的主要差异

·        XML 不是 HTML 的替代。

·        XML 和 HTML 为不同的目的而设计:

·        XML 被设计为传输和存储数据,其焦点是数据的内容。

·        HTML 被设计用来显示数据,其焦点是数据的外观。

·        HTML 旨在显示信息,而 XML 旨在传输信息

没有任何行为的 XML

·        XML 不会做任何事情。XML 被设计用来结构化、存储以及传输信息。

·        下面是 John 写给 George 的便签,存储为 XML:

·        <note>

·        <to>George</to>

·        <from>John</from>

·        <heading>Reminder</heading>

·        <body>Don't forgetthe meeting!</body>

·        </note>

·        上面的这条便签具有自我描述性。它拥有标题以及留言,同时包含了发送者和接受者的信息。

·        但是,这个 XML 文档仍然没有做任何事情。它仅仅是包装在 XML 标签中的纯粹的信息。我们需要编写软件或者程序,才能传送、接收和显示出这个文档。

·        XML 没什么特别的。它仅仅是纯文本而已。有能力处理纯文本的软件都可以处理XML

通过 XML 您可以发明自己的标签

·        上例中的标签没有在任何 XML 标准中定义过(比如 <to> 和 <from>)。这些标签是由文档的创作者发明的。

·        这是因为 XML 没有预定义的标签。

·        在 HTML 中使用的标签(以及 HTML 的结构)是预定义的。HTML 文档只使用在 HTML 标准中定义过的标签(比如 <p> 、<h1> 等等)。

·        XML 允许创作者定义自己的标签和自己的文档结构。

XML 不是对 HTML 的替代

·        XML 是对 HTML 的补充

·        XML 不会替代 HTML,理解这一点很重要。在大多数 web 应用程序中,XML 用于传输数据,而 HTML 用于格式化并显示数据。

·        对 XML 最好的描述是:XML 是独立于软件和硬件的信息传输工具。

XML定义:

XMLextensible markup language用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。

XML是标准通用标记语言 (SGML) 的子集,非常适合 Web 传输。XML 提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。

格式特性:

XMLAccess,OracleSQL Server等数据库不同,数据库提供了更强有力的数据存储和分析能力,例如:数据索引、排序、查找、相关一致性等,XML仅仅是展示数据。事实上XML与其他数据表现形式最大的不同是:他极其简单。这是一个看上去有点琐细的优点,但正是这点使XML与众不同。

XMLHTML的设计区别是XML是用来存储数据的,重在数据本身。而HTML是用来定义数据的,重在数据的显示模式。

XML的简单使其易于在任何应用程序中读写数据,这使XML很快成为数据交换的唯一公共语言,虽然不同的应用软件也支持其它的数据交换格式,但不久之后他们都将支持XML,那就意味着程序可以更容易的与Windows,MacOS,Linux以及其他平台下产生的信息结合,然后可以很容易加载XML数据到程序中并分析他,并以XML格式输出结果。

为了使得SGML显得用户友好,XML重新定义了SGML的一些内部值和参数,去掉了大量的很少用到的功能,这些繁杂的功能使得SGML在设计网站时显得复杂化。XML保留了SGML的结构化功能,这样就使得网站设计者可以定义自己的文档类型,XML同时也推出一种新型文档类型,使得开发者也可以不必定义文档类型。

简明语法:

SGML常用来定义针对HTML的文档类型定义(DTD),同时它也常用于编写XMLDTDSGML的问题就在于,它允许出现一些奇怪的语法,这让创建HTML的解析器成为一个大难题:

1 .某些起始标签不允许出现结束标签,例如HTML<img>标签。包含了结束标签就会出现错误。

2 .某些起始标签可以选择性出现结束标签或者隐含了结束标签

3 .某些起始标签要求必须出现结束标签,例如HTML<script>标签。

4. 标签可以以任何顺序嵌套。即使结束标签不按照起始标签的逆序出现也是允许的,例如,This isa sample string是正确的。

5 .某些特性要求必须包含值,例如<imgsrc="picture.jpg">中的src特性。

6 .某些特性不要求一定有值,例如中的nowrap特性。

7 .定义特性的两边有没有加上双引号都是可以的,所以<imgsrc="picture.jpg"><img src=picture.jpg>都是允许的。

这些问题使建立一个SGML语言的解析器变成了一项艰巨的任务。判断何时应用以上规则的困难导致了SGML语言的定义一直停滞不前。以这些问题作为出发点,XML逐渐步入我们的视野。

XML去掉了之前令许多开发人员头疼的SGML的随意语法。在XML中,采用了如下的语法:

1 任何的起始标签都必须有一个结束标签。

2 可以采用另一种简化语法,可以在一个标签中同时表示起始和结束标签。这种语法是在大于符号之前紧跟一个斜线(/),例如<tag/ >XML解析器会将其翻译成<tag></tag>

3 标签必须按合适的顺序进行嵌套,所以结束标签必须按镜像顺序匹配起始标签,例如this is a samplestring。这好比是将起始和结束标签看作是数学中的左右括号:在没有关闭所有的内部括号之前,是不能关闭外面的括号的。

4 所有的特性都必须有值。

5 所有的特性都必须在值的周围加上双引号。

这些规则使得开发一个XML解析器要简便得多,而且也除去了解析SGML中花在判断何时何地应用那些奇怪语法规则上的工作。仅仅在XML出现后的前六年就衍生出多种不同的语言,包括MathMLSVGRDFRSSSOAPXSLTXSL-FO,而同时也将HTML改进为XHTML

扩展阅读:

因为XMLW3C制定的,XML的标准化工作由W3CXML工作组负责,该小组成员由来自各个地方和行业的专家组成,他们通过email交流对XML标准的意见,并提出自己的看法 (www.w3.org/TR/WD-xml)。因为XML 是个公共格式,(它不专属于任何一家公司),你不必担心XML技术会成为少数公司的盈利工具,XML不是一个依附于特定浏览器的语言。

 

第二部分:XML文件介绍及读写操作

XML文件介绍:

XML文件结构:

XML 文档形成了一种树结构,它从根部开始,然后扩展到枝叶

一个 XML 文档实例

XML 使用简单的具有自我描述性的语法:

<?xml version="1.0"encoding="ISO-8859-1"?>

<note>

<to>George</to>

<from>John</from>

<heading>Reminder</heading>

<body>Don't forget themeeting!</body>

</note>

第一行是 XML 声明。它定义 XML 的版本 (1.0) 和所使用的编码 (ISO-8859-1 = Latin-1/西欧字符集)。

下一行描述文档的根元素(像在说:“本文档是一个便签”):

<note>

接下来 4 行描述根的 4 个子元素(to, from, heading 以及 body):

<to>George</to>

<from>John</from>

<heading>Reminder</heading>

<body>Don't forget themeeting!</body>

最后一行定义根元素的结尾:

</note>

 

 

从本例可以设想,该 XML 文档包含了 John 给 George 的一张便签。

XML 具有出色的自我描述性,你同意吗?

XML文档形成一种树结构

XML 文档必须包含根元素。该元素是所有其他元素的父元素。

XML 文档中的元素形成了一棵文档树。这棵树从根部开始,并扩展到树的最底端。

所有元素均可拥有子元素:

<root>

 <child>

   <subchild>.....</subchild>

 </child>

</root>

父、子以及同胞等术语用于描述元素之间的关系。父元素拥有子元素。相同层级上的子元素成为同胞(兄弟或姐妹)。

所有元素均可拥有文本内容和属性(类似 HTML 中)。

实例

上图表示下面的 XML 中的一本书:

<bookstore>

<bookcategory="COOKING">

 <title lang="en">Everyday Italian</title>

 <author>Giada De Laurentiis</author>

 <year>2005</year>

 <price>30.00</price>

</book>

<bookcategory="CHILDREN">

 <title lang="en">Harry Potter</title>

 <author>J K. Rowling</author>

 <year>2005</year>

 <price>29.99</price>

</book>

<book category="WEB">

 <title lang="en">Learning XML</title>

 <author>Erik T. Ray</author>

 <year>2003</year>

 <price>39.95</price>

</book>

</bookstore>

例子中的根元素是 <bookstore>。文档中的所有 <book> 元素都被包含在 <bookstore> 中。

<book> 元素有 4 个子元素:<title>、< author>、<year>、<price>。

XML 语法规则

XML 的语法规则很简单,且很有逻辑。这些规则很容易学习,也很容易使用。

所有 XML 元素都须有关闭标签

在 HTML,经常会看到没有关闭标签的元素:

<p>This is a paragraph

<p>This is another paragraph

XML 中,省略关闭标签是非法的。所有元素都必须有关闭标签:

<p>This is aparagraph</p>

<p>This is anotherparagraph</p> 

注释:您也许已经注意到 XML 声明没有关闭标签。这不是错误。声明不属于XML本身的组成部分。它不是 XML 元素,也不需要关闭标签。

XML 标签对大小写敏感

XML 元素使用 XML 标签进行定义。

XML 标签对大小写敏感。在 XML 中,标签 <Letter> 与标签 <letter> 是不同的。

必须使用相同的大小写来编写打开标签和关闭标签:

<Message>这是错误的。</message>

 

<message>这是正确的。</message>

注释:打开标签和关闭标签通常被称为开始标签和结束标签。不论您喜欢哪种术语,它们的概念都是相同的。

XML 必须正确地嵌套

在 HTML 中,常会看到没有正确嵌套的元素:

<b><i>This text is boldand italic</b></i>

在 XML 中,所有元素都必须彼此正确地嵌套:

<b><i>This text is boldand italic</i></b>

在上例中,正确嵌套的意思是:由于 <i> 元素是在 <b> 元素内打开的,那么它必须在 <b> 元素内关闭。

XML 文档必须有根元素

XML 文档必须有一个元素是所有其他元素的父元素。该元素称为根元素

<root>

 <child>

   <subchild>.....</subchild>

 </child>

</root>

XML 的属性值须加引号

与 HTML 类似,XML 也可拥有属性(名称/值的对)。

在 XML 中,XML 的属性值须加引号。请研究下面的两个 XML 文档。第一个是错误的,第二个是正确的:

<note date=08/08/2008>

<to>George</to>

<from>John</from>

</note>

<note date="08/08/2008">

<to>George</to>

<from>John</from>

</note>

在第一个文档中的错误是,note 元素中的 date 属性没有加引号。

实体引用

在 XML 中,一些字符拥有特殊的意义。

如果你把字符 "<" 放在 XML 元素中,会发生错误,这是因为解析器会把它当作新元素的开始。

这样会产生 XML 错误:

<message>if salary < 1000then</message>

为了避免这个错误,请用实体引用来代替 "<" 字符:

<message>if salary &lt; 1000then</message>

XML 中,有 5 个预定义的实体引用:

&lt;

< 

小于

&gt;

> 

大于

&amp;

&

和号

&apos;

'

单引号

&quot;

"

引号

注释:在 XML 中,只有字符 "<" 和 "&" 确实是非法的。大于号是合法的,但是用实体引用来代替它是一个好习惯。

XML 中的注释

在 XML 中编写注释的语法与 HTML 的语法很相似:

<!-- This is a comment -->

XML 中,空格会被保留

HTML 会把多个连续的空格字符裁减(合并)为一个:

HTML:    Hello           my name is David.

输出:    Hello my name is David.

在 XML 中,文档中的空格不会被删节。

XML LF 存储换行

在 Windows 应用程序中,换行通常以一对字符来存储:回车符 (CR) 和换行符 (LF)。这对字符与打字机设置新行的动作有相似之处。在 Unix 应用程序中,新行以 LF 字符存储。而 Macintosh 应用程序使用 CR 来存储新行。

XML 元素

XML 文档包含 XML 元素。

什么是 XML 元素?

XML 元素指的是从(且包括)开始标签直到(且包括)结束标签的部分。

元素可包含其他元素、文本或者两者的混合物。元素也可以拥有属性。

<bookstore>

<bookcategory="CHILDREN">

 <title>Harry Potter</title>

 <author>J K. Rowling</author>

 <year>2005</year>

 <price>29.99</price>

</book>

<book category="WEB">

 <title>Learning XML</title>

 <author>Erik T. Ray</author>

 <year>2003</year>

 <price>39.95</price>

</book>

</bookstore>

在上例中,<bookstore> 和 <book> 都拥有元素内容,因为它们包含了其他元素。<author> 只有文本内容,因为它仅包含文本。

在上例中,只有 <book> 元素拥有属性(category="CHILDREN")。

XML 命名规则

XML 元素必须遵循以下命名规则:

· 名称可以含字母、数字以及其他的字符

· 名称不能以数字或者标点符号开始

· 名称不能以字符 “xml”(或者 XMLXml)开始

· 名称不能包含空格

可使用任何名称,没有保留的字词。

最佳命名习惯

使名称具有描述性。使用下划线的名称也很不错。

名称应当比较简短,比如:<book_title>,而不是:<the_title_of_the_book>。

避免 "-" 字符。如果您按照这样的方式进行命名:"first-name",一些软件会认为你需要提取第一个单词。

避免 "." 字符。如果您按照这样的方式进行命名:"first.name",一些软件会认为 "name" 是对象 "first" 的属性。

避免 ":" 字符。冒号会被转换为命名空间来使用(稍后介绍)。

XML 文档经常有一个对应的数据库,其中的字段会对应 XML 文档中的元素。有一个实用的经验,即使用数据库的名称规则来命名 XML 文档中的元素。

非英语的字母比如 éòá 也是合法的 XML 元素名,不过需要留意当软件开发商不支持这些字符时可能出现的问题。

XML 元素是可扩展的

XML 元素是可扩展,以携带更多的信息。

请看下面这个 XML 例子:

<note>

<to>George</to>

<from>John</from>

<body>Don't forget themeeting!</body>

</note>

让我们设想一下,我们创建了一个应用程序,可将 <to>、<from> 以及 <body> 元素提取出来,并产生以下的输出:

MESSAGE

To: George

From: John

 

Don't forget the meeting!

想象一下,之后这个 XML 文档作者又向这个文档添加了一些额外的信息:

<note>

<date>2008-08-08</date>

<to>George</to>

<from>John</from>

<heading>Reminder</heading>

<body>Don't forget themeeting!</body>

</note>

那么这个应用程序会中断或崩溃吗?

不会。这个应用程序仍然可以找到 XML 文档中的 <to>、<from> 以及 <body> 元素,并产生同样的输出。

XML 的优势之一,就是可以经常在不中断应用程序的情况进行扩展。

XML 属性

XML 元素可以在开始标签中包含属性,类似 HTML

属性 (Attribute) 提供关于元素的额外(附加)信息。

XML 属性

从 HTML,你会回忆起这个:<imgsrc="computer.gif">。"src" 属性提供有关 <img> 元素的额外信息。

在 HTML 中(以及在 XML 中),属性提供有关元素的额外信息:

<imgsrc="computer.gif">

<a href="demo.asp">

属性通常提供不属于数据组成部分的信息。在下面的例子中,文件类型与数据无关,但是对需要处理这个元素的软件来说却很重要:

<filetype="gif">computer.gif</file>

XML 属性必须加引号

属性值必须被引号包围,不过单引号和双引号均可使用。比如一个人的性别,person 标签可以这样写:

<person sex="female">

或者这样也可以:

<person sex='female'>

注释:如果属性值本身包含双引号,那么有必要使用单引号包围它,就像这个例子:

<gangster name='George"Shotgun" Ziegler'>

或者可以使用实体引用:

<gangster name="George&quot;Shotgun&quot; Ziegler">

XML 元素 vs. 属性

请看这些例子:

<person sex="female">

 <firstname>Anna</firstname>

 <lastname>Smith</lastname>

</person>

 

<person>

 <sex>female</sex>

 <firstname>Anna</firstname>

 <lastname>Smith</lastname>

</person>

在第一个例子中,sex 是一个属性。在第二个例子中,sex 则是一个子元素。两个例子均可提供相同的信息。

没有什么规矩可以告诉我们什么时候该使用属性,而什么时候该使用子元素。我的经验是在 HTML 中,属性用起来很便利,但是在 XML 中,您应该尽量避免使用属性。如果信息感觉起来很像数据,那么请使用子元素吧。

我最喜欢的方式

下面的三个 XML 文档包含完全相同的信息:

第一个例子中使用了 date 属性:

<note date="08/08/2008">

<to>George</to>

<from>John</from>

<heading>Reminder</heading>

<body>Don't forget themeeting!</body>

</note>

第二个例子中使用了 date 元素:

<note>

<date>08/08/2008</date>

<to>George</to>

<from>John</from>

<heading>Reminder</heading>

<body>Don't forget themeeting!</body>

</note>

第三个例子中使用了扩展的 date 元素(这是我的最爱):

<note>

<date>

  <day>08</day>

  <month>08</month>

  <year>2008</year>

</date>

<to>George</to>

<from>John</from>

<heading>Reminder</heading>

<body>Don't forget the meeting!</body>

</note>

避免 XML 属性?

因使用属性而引起的一些问题:

· 属性无法包含多重的值(元素可以)

· 属性无法描述树结构(元素可以)

· 属性不易扩展(为未来的变化)

· 属性难以阅读和维护

请尽量使用元素来描述数据。而仅仅使用属性来提供与数据无关的信息。

不要做这样的蠢事(这不是 XML 应该被使用的方式):

<note day="08"month="08" year="2008"

to="George"from="John" heading="Reminder"

body="Don't forget themeeting!">

</note>

针对元数据的 XML 属性

有时候会向元素分配 ID 引用。这些 ID 索引可用于标识 XML 元素,它起作用的方式与 HTML 中 ID 属性是一样的。这个例子向我们演示了这种情况:

<messages>

 <note id="501">

   <to>George</to>

   <from>John</from>

   <heading>Reminder</heading>

   <body>Don't forget the meeting!</body>

 </note>

 <note id="502">

   <to>John</to>

   <from>George</from>

   <heading>Re: Reminder</heading>

   <body>I will not</body>

 </note>

</messages>

上面的 ID 仅仅是一个标识符,用于标识不同的便签。它并不是便签数据的组成部分。

在此我们极力向您传递的理念是:元数据(有关数据的数据)应当存储为属性,而数据本身应当存储为元素。

XML 验证

拥有正确语法的 XML 被称为形式良好 XML

通过 DTD 验证的 XML 合法 XML

形式良好的 XML 文档

形式良好结构良好 XML 文档拥有正确的语法。

形式良好Well Formed)的 XML 文档会遵守前几章介绍过的XML 语法规则:

  • XML 文档必须有根元素
  • XML 文档必须有关闭标签
  • XML 标签对大小写敏感
  • XML 元素必须被正确的嵌套
  • XML 属性必须加引号
<?xml version="1.0" encoding="ISO-8859-1"?>
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
验证 XML 文档

合法的 XML 文档是形式良好 XML 文档,同样遵守文档类型定义(DTD) 的语法规则:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE note SYSTEM "Note.dtd">
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>  

在上例中,DOCTYPE 声明是对外部 DTD 文件的引用。下面的段落展示了这个文件的内容。

XML DTD

DTD的作用是定义XML 文档的结构。它使用一系列合法的元素来定义文档结构:

<!DOCTYPE note [
  <!ELEMENT note (to,from,heading,body)>
  <!ELEMENT to      (#PCDATA)>
  <!ELEMENT from    (#PCDATA)>
  <!ELEMENT heading (#PCDATA)>
  <!ELEMENT body    (#PCDATA)>
]> 

如果您希望学习 DTD,请访问我们的 DTD 教程

XML Schema

W3C支持一种基于XML DTD 代替者,它名为XML Schema[ˈski:mə]

<xs:element name="note">
 
<xs:complexType>
  <xs:sequence>
    <xs:element name="to"      type="xs:string"/>
    <xs:element name="from"    type="xs:string"/>
    <xs:element name="heading" type="xs:string"/>
    <xs:element name="body"    type="xs:string"/>
  </xs:sequence>
</xs:complexType>
 
</xs:element> 

如果您需要学习 XML Schema,请访问我们的 XML Schema 教程

一个通用的验证器

为了帮助您检查 XML 文件的语法,我们创建了这个工具,以便您对任何XML 文件进行语法检查。

请看下一节。

XML 验证器

XML 错误会终止您的程序

XML 文档中的错误会终止你的 XML 程序。

W3C 的 XML 规范声明:如果 XML 文档存在错误,那么程序就不应当继续处理这个文档。理由是,XML 软件应当轻巧,快速,具有良好的兼容性。

如果使用 HTML,创建包含大量错误的文档是有可能的(比如你忘记了结束标签)。其中一个主要的原因是 HTML 浏览器相当臃肿,兼容性也很差,并且它们有自己的方式来确定当发现错误时文档应该显示为什么样子。

使用 XML 时,这种情况不应当存在。

对您的 XML 进行语法检查

为了帮助您对 XML 进行语法检查,我们创建了一个 XML 验证器。

把您的 XML 粘贴到下面的文本框中,然后点击"验证"按钮来进行语法检查。

窗体顶端

窗体底端

对您的 XML 文件进行语法检查

您可以通过把 XML 文件的 URL 键入下面的输入框中,然后点击"验证"按钮,来对某个在线的 XML 文件进行语法检查:

窗体顶端

文件名:

窗体底端

注释:如果返回的的错误是"拒绝访问",说明您的浏览器安全设置不允许跨域的文件访问。

文件 "note_error.xml" 的作用是演示浏览器的错误处理,如果需要返回无错的消息,可以将该文件替换为其他文件,比如 "books.xml"。

根据 DTD 来验证 XML

只要把 DOCTYPE 声明添加到您的 XML 中,然后点击验证按钮即可:

窗体顶端

窗体底端

注释:只有在 Internet Explorer 中,可以根据 DTD 来验证 XML。Firefox, Mozilla, Netscape 以及 Opera 做不到这一点。

XML 命名空间(XML Namespaces

XML 命名空间提供避免元素命名冲突的方法。

命名冲突

XML 中,元素名称是由开发者定义的,当两个不同的文档使用相同的元素名时,就会发生命名冲突。

这个 XML 文档携带着某个表格中的信息:

<table>
   <tr>
   <td>Apples</td>
   <td>Bananas</td>
   </tr>
</table>

这个 XML 文档携带有关桌子的信息(一件家具):

<table>
   <name>African Coffee Table</name>
   <width>80</width>
   <length>120</length>
</table>

假如这两个 XML 文档被一起使用,由于两个文档都包含带有不同内容和定义的<table> 元素,就会发生命名冲突。

XML解析器无法确定如何处理这类冲突。

使用前缀来避免命名冲突

此文档带有某个表格中的信息:

<h:table>
   <h:tr>
   <h:td>Apples</h:td>
   <h:td>Bananas</h:td>
   </h:tr>
</h:table>

XML 文档携带着有关一件家具的信息:

<f:table>
   <f:name>African Coffee Table</f:name>
   <f:width>80</f:width>
   <f:length>120</f:length>
</f:table>

现在,命名冲突不存在了,这是由于两个文档都使用了不同的名称来命名它们的<table> 元素(<h:table> <f:table>)

通过使用前缀,我们创建了两种不同类型的<table> 元素。

使用命名空间(Namespaces

这个 XML 文档携带着某个表格中的信息:

<h:table xmlns:h="http://www.w3.org/TR/html4/">
   <h:tr>
   <h:td>Apples</h:td>
   <h:td>Bananas</h:td>
   </h:tr>
</h:table>

XML 文档携带着有关一件家具的信息:

<f:table xmlns:f="http://www.w3school.com.cn/furniture">
   <f:name>African Coffee Table</f:name>
   <f:width>80</f:width>
   <f:length>120</f:length>
</f:table>

与仅仅使用前缀不同,我们为<table> 标签添加了一个xmlns 属性,这样就为前缀赋予了一个与某个命名空间相关联的限定名称。

XML Namespace (xmlns) 属性

XML命名空间属性被放置于元素的开始标签之中,并使用以下的语法:

xmlns:namespace-prefix="namespaceURI"

当命名空间被定义在元素的开始标签中时,所有带有相同前缀的子元素都会与同一个命名空间相关联。

注释:用于标示命名空间的地址不会被解析器用于查找信息。其惟一的作用是赋予命名空间一个惟一的名称。不过,很多公司常常会作为指针来使用命名空间指向实际存在的网页,这个网页包含关于命名空间的信息。

请访问 http://www.w3.org/TR/html4/

统一资源标识符(Uniform Resource Identifier (URI)

统一资源标识符是一串可以标识因特网资源的字符。最常用的 URI 是用来标示因特网域名地址的统一资源定位器(URL)。另一个不那么常用的 URI 统一资源命名(URN)在我们的例子中,我们仅使用URL

默认的命名空间(Default Namespaces

为元素定义默认的命名空间可以让我们省去在所有的子元素中使用前缀的工作。

请使用下面的语法:

xmlns="namespaceURI"

这个 XML 文档携带着某个表格中的信息:

<table xmlns="http://www.w3.org/TR/html4/">
   <tr>
   <td>Apples</td>
   <td>Bananas</td>
   </tr>
</table>

XML 文档携带着有关一件家具的信息:

<table xmlns="http://www.w3school.com.cn/furniture">
   <name>African Coffee Table</name>
   <width>80</width>
   <length>120</length>
</table>
命名空间的实际应用

当开始使用 XSL 时,您不久就会看到实际使用中的命名空间。XSL样式表用于将XML 文档转换为其他格式,比如HTML

如果您仔细观察下面的这个XSL 文档,就会看到大多数的标签是HTML标签。非 HTML 的标签都有前缀 xsl,并由此命名空间标示:"http://www.w3.org/1999/XSL/Transform"

<?xml version="1.0" encoding="ISO-8859-1"?>
 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 
<xsl:template match="/">
<html>
<body>
  <h2>My CD Collection</h2>
  <table border="1">
    <tr>
      <th align="left">Title</th>
      <th align="left">Artist</th>
    </tr>
    <xsl:for-each select="catalog/cd">
    <tr>
      <td><xsl:value-of select="title"/></td>
      <td><xsl:value-of select="artist"/></td>
    </tr>
    </xsl:for-each>
  </table>
</body>
</html>
</xsl:template>
 
</xsl:stylesheet>

XML 的相关技术

下面是一个与XML 相关的技术的列表。

XHTML

更严格更纯净的基于 XML HTML 版本。

XML DOM

访问和操作 XML 的标准文档模型。

XSLT

XSL 包含三个部分:

·        XSLT- 把XML 转换为其他格式,比如HTML

·        XSL-FO- 用于格式化XML 文档的语言

·        XPath- 用于在XML 文档中导航的语言

XQuery

基于XML 的用于查询XML 数据的语言。

DTD

用于定义 XML 文档中的合法元素的标准

XSD

XMLSchema。基于XML 的DTD 替代物。

XLink

在XML 文档中创建超级链接的语言。

XPointer

允许XLink 超级链接指向XML 文档中更多具体的部分。

XForms

使用XML 定义表单数据。

SOAP

允许应用程序在HTTP 之上交换信息的基于XML 的协议。

WSDL

用于描述网络服务的基于XML 的语言。

RDF

用于描述网络资源的基于XML 的语言。

RSS

聚合新闻以及类新闻站点内容的格式。

WAP

用于在无线设备上(比如移动电话)显示内容的一种基于XML 的语言。

SMIL

描述视听呈现的语言。

SVG

使用XML 格式定义图形。

 

XML文件的读写操作

盛行的四种对XML的解析方式

Java生活中我们经常需要对XML进行解析以方便我们对数据进行操作,下面介绍在民间盛行的四种使用Java解析XML的方法,其中重点介绍DOM方式和DOM4J方式。

DOMJAXP Crimson 解析器):W3CHTMLXML分析器制定的标准接口规范,基于树,可随机动态访问和更新文档的内容、结构、样式。一次性将xml加载内存,比较消耗内存。

SAXsimple API for XML不是W3C的标准,而是由XML-DEV邮件列表成员于1998年为Java语言开发的一种基于事件的简单API。基于事件,逐行解析,顺序访问XML文档,速度快,处理功能简单。Sax不能随机处理xml文档

JDOM:鉴于DOM的低效率,而SAX又不能随机处理XML文档,Jason Hunter与BrettMcLaughlin于2000年春天,开始创建一种能充分体现两者优势的API——JDOM(Java-based DOM,基于Java的DOM),它是一个基于Java的对象模型,树状结构,能使读取、操作和写入XML文档,比DOM更高效,比SAX更强大,但由于使用了大量的类而不使用接口导致灵活性降低。

DOM4J:DOM4J是一个易用的,开源的库,用于XML,XPath,XSLT。它应用于Java平台,采用了Java集合框架并完全支持DOM,SAX,JAXP。它提供了大量的接口,因此JDOM更具有灵活性。

有关文档对象模型(DOM

DOM(文档对象模型),W3C实现了DOM操作的规范化,并为多种语言提供了操作DOM的接口,如C,java,Javascript等等。

对象模型的构建是以面向对象的思想为基础,通过对问题进行抽象,构造出一组相关的模型,从而能够全面地捕捉问题空间的信息。而我们这里要介绍的文档对象模型通常是以树的形式对相关文档进行抽象,构建出由节点构成的文档树模型,从而实现更方便的对文档的各种操作。

节点:XML文档中的所有节点组成了一个文档树(或节点树)。XML文档中的每个元素、属性、文本等都代表着树中的一个节点。树起始于文档节点,并由此继续伸出枝条,直到处于这棵树最低级别的所有文本节点为止,常用节点类型如表2-1所示:

节点类型

附加说明

实例

元素节点(Element)

XML标记元素

<company>…</company>

属性节点(Attribute)

XML标记元素的属性

name=”ntcsoft”

文本节点(Text)

包括在XML标记中的文本段

工程师A

文档类型节点(DocumentType)

文档类型声明

!DOCTYPE…﹥

注释节点Comment

XmlComment类注释节点。

<!—文档注释à

2-1

节点关系:下面我们从一个XML文档实例中了解一下各个节点之间的关系:

<company name="ntcsoft" >

  <department><employee position="developer">工程师A</employee></department>

  <department name="education"></department>

</company>

通过上面的XML文档,我们构建出如下树状文档对象模型,如图2-1所示:

文档

根元素节点

<company>

元素节点

<department>

元素节点

<     department>

元素节点

<employee>

属性节点

name

文本节点

工程师A

属性节点

position

属性节点

name

根节点

父到子

子到父

下一节点

上一节点

firstChild

lastChild

2-1

DOM操作的各种招式

常用节点属性如表2-2所示:

属性

描述

nodeName

结点名称

nodeValue

结点内部值,通常只应用于文本结点

nodeType

节点类型对应的数字

parentNode

如果存在,指向当前结点的父亲结点

childNodes

子结点列表

firstChild

如果存在,指向当前元素的第一个子结点

lastChild

如果存在,指向当前元素的最后一个子结点

previousSibling

指向当前结点的前一个兄弟结点

nextSibling

指向当前结点的后一个兄弟结点

attributes

元素的属性列表

2-2

常用节点方法如表2-3所示:

操作类型

方法原型

描述

访问节点

getElementById(id)

根据ID属性查找元素节点

getElementsByName(name)

根据name属性查找元素集

getElementsByTagName(tagName)

根据元素标记名称查找元素集

创建节点

createElement(tagName)

创建元素节点

createTestNode(string)

创建文本节点

createAttribute(name)

创建属性节点

插入和添加节点

appendChild(newChild)

添加子节点到目标节点上

insertBefore(newChild,targetChild)

将newChild节点插入到targetChild节点之前

复制节点

CloneNode(bool)

复制该节点,由bool确定是否复制子节点

删除和替换节点

removeChild(childName)

删除由childName指定的节点

replaceChild(newChild,oldChild)

用newChild替换oldChild

属性节点操作

getAttribute(name)

返回目标对象指定属性名称为name的属性值

setAttribute(name,value)

修改目标节点指定属性名称为name的属性值为value

removeAttribute(name)

删除目标节点指定属性名称为name的属性

2-3

使用DOMDOM4J来解析XML

MyEclipse下创建exercise工程,在src目录下创建文件名为Company.xml的XML文档,如图

 

Company.xml源码如下:

<?xml version="1.0" encoding="UTF-8"?>

<company name="ntcsoft" address="河南省郑州市">

  <department deptNo="001" name="development">

<employee id="devHead" position="minister">许刚</employee>

<employee position="developer">工程师A</employee>

  </department>

  <department deptNo="002" name="education">

<employee position="minister" telephone="1234567">申林</employee>

<employee position="trainee">实习生A</employee>

  </department>

</company>

 

在工程下创建domain包,用于存放实体类,在此包下创建如下实体类,如图

 

Company.java主要源码如下:

publicclass  Company {

         private  String name;

         private  String address;

         private  Department[] dept;

         省略Seters and Getters…}                   

}     

 

Department.java主要源码如下:

publicclass  Department {

         private  String number;

         private  String name;

         private  Employee[] emp;

         省略Seters and Getters…}

      

 

Employee.java主要源码如下:

publicclass  Employee {

         private  String name;

         private  String position;

         private  String telephone;

         省略Seters and Getters…}

      

在工程下创建xmpParsers包,用于存放解析器,如图所示:

 

在工程下创建parsersTest包,用于存放解析器测试类,如图所示:

DOM方式解析XML

A.    概述:

DOMDocument Object Model文档对象模型),是W3CHTMLXML分析器制定的标准接口规范。

B.       特点:

独立于语言,跨平台(可以在各种编程和脚本语言中使用),需要将整个文档读入内存,在内存中创建文档树,可随即访问文档中的特定节点,对内存的要求比较高,经过测试,访问速度相对于其他解析方式较慢,适用于简单文档的随即处理。

C.     在解析过程中需要使用的包、接口和类:

//为文档对象模型 (DOM) 提供接口  API(Java API for XML Processing (JAXP))

import  org.w3c.dom.*;

//此类可以包含来自 XML 解析器或应用程序的基本错误和警告信息

import  org.xml.sax.SAXException;

//导入实体类

import  domain.*;

//标准IO,用于输入输出工作

import  java.io.*;

//用于从 XML 文档获取 DOM 文档实例并生成 DOM 对象树的解析器

import  javax.xml.parsers.*;

//用于创建将DOM文档树源对象转换为XML文档结果对象的转换器

import  javax.xml.transform.*;

//构造DOM文档树源对象

import  javax.xml.transform.dom.DOMSource;

//构造XML文档的结果对象

import  javax.xml.transform.stream.StreamResult;

D.    读取本地XML文档解析并转换为对象的步骤:

1.            创建XML文件解析器:我们可以通过javax.xml.parsers包下的工厂类DocumentBuilderFactory创建XML文档的解析器。

//创建DocumentBuilderFactory工厂实例。

DocumentBuilderFactory  dbfactory =  DocumentBuilderFactory.newInstance();

//通过文档创建工厂创建文档创建器

DocumentBuilder  dBuilderdbfactory.newDocumentBuilder();

2.            解析XML文件并把该文件转换为文档对象:通过文档创建器DocumentBuilderparse方法解析参数URL指定的XML文档,并返回一个Document 对象。

Document  doc = dBuilder.parse(url);

3.            操作该对象并获取数据。

E.     将对象转换为XML文件并写入本地的步骤:

1.            创建XML文档对象:

Document  doc = dBuilder.newDocument();       //通过文档创建器创建一个新的文档对象。

2.            把实体对象转换为节点对象添加到创建好的XML文档对象中:

Element  root = doc.createElement(“company”);//建立根节点company

doc.appendChild(root);

3.            使用javax.xml.transform包下TransformerFactory创建文档转换器。

TransformerFactory  tFactory = TransformerFactory.newInstance();//创建转换器工厂实例

Transformer  tFormer= tFactory.newTransformer();//创建转换器

4.            通过文档转换器将XML文档的源对象转换为可写入本地的结果对象,并写入本地。

DOMSource  dSource = new DOMSource(doc);//DOM对象解析为转换器的输入源

//创建一个文件路径为filePath的文件对象,并将文件对象封装到结果集对象中

StreamResult  sResult = new StreamResult(new  File(filePath));

//  使用转换器将内存中的XML文档输入源转换为结果集输出到本地

tFormer.transform(dSource,  sResult);

F.      处理XML文档步骤:

1.            读取本地XML文档。

2.            通过节点的各种操作方法对节点进行增加,修改,删除等操作。

3.            重新将XML文档写入本地。

G.    解析器DOMParser.java的全部源码:

/**

 * Parse XML document with DOM.

 * Copyright 2010.9 NTCsoft(郑州蜂鸟科技有限公司) , Inc. All rights reserved.

 * @author  ZhouYuan

 * @since  2010-9-24

 * @version  1.0

 */

//用于各种IO操作

import java.io.*;

//用于从 XML 文档获取 DOM 文档实例并生成 DOM 对象树的解析器

import  javax.xml.parsers.*;

//用于创建将DOM文档树对象模型转换为XML文档模型的转换器

import  javax.xml.transform.*;

//构造DOM文档树源对象

import  javax.xml.transform.dom.DOMSource;

//构造XML文档的结果对象

import  javax.xml.transform.stream.StreamResult;

//为文档对象模型 (DOM) 提供接口API(Java API for XML Processing (JAXP)的组件)

import  org.w3c.dom.*;

//此类可以包含来自 XML 解析器或应用程序的基本错误和警告信息

import  org.xml.sax.SAXException;

//导入实体类

import  domain.*;

/**

 * Parse XML document with DOM.*/

publicclass  DOMParser {

         DocumentBuilderFactory dbfactory                    //创建DocumentBuilderFactory工厂实例。

                   = DocumentBuilderFactory.newInstance();        

         DocumentBuilder dBuilder;                                           

        

         /**

          * XML文档:

          * 从本地读取XML文件,并将XML文档转换为Java对象。

          * @param  url 将要读取的XML文件的路径

          * @return返回转换成功的Company对象*/

         public  Company readXML(String url){

                   //创建公司对象

                   Company comp = new  Company();

                  

                   try {

                            dBuilderdbfactory.newDocumentBuilder();

                            /*

                           * Document 接口表示整个 HTML XML 文档。

                            *  parse方法:解析 URI 指定的 XML 文档,返回一个新的 DOM Document 对象。*/

                            Document doc = dBuilder.parse(url);

                            //得到文档的根元素company

                            Element root = doc.getDocumentElement();

                            //读取XML文档中的公司信息,并为公司对象设置相关属性。

                            comp.setAddress(root.getAttribute("address"));

                            comp.setName(root.getAttribute("name"));

                            //通过getElementsByTagName读取XML文档中的所有root节点下的department节点。

                            NodeList depts = root.getElementsByTagName("department");

                            //创建Department对象数组

                            Department[]  deptList = new Department[depts.getLength()];

                           

                            /*

                             * 读取部门信息,并将部门对象添加至公司对象中。  */

                            for(int i  = 0;i < depts.getLength();i++){

                                     Department  dept = new  Department();

                                     //使用NodeListitem()方法遍历节点,item(int  index)方法可以返回集合中的第 index个项。

                                     Element  deptEmt = (Element) depts.item(i);

                                     dept.setName(deptEmt.getAttribute("name"));

                                     dept.setNumber(deptEmt.getAttribute("deptNo"));

                                    

                                     //通过getElementsByTagName读取XML文档中的所有deptEmt节点下的employee节点

                                     NodeList  emps = deptEmt.getElementsByTagName("employee");

                                     //创建Employee对象数组

                                     Employee[]  empList = new Employee[emps.getLength()];

                                    

                                     /*

                                      * 读取雇员信息,并将雇员对象添加至部门对象中。*/

                                     for(int j  = 0;j < emps.getLength();j++){

                                               Employee  emp = new  Employee();

                                               //XML中的employee节点转换为Employee对象emp

                                               Element  empEmt = (Element) emps.item(j);

 

                                               emp.setName(empEmt.getTextContent());

                                               emp.setPosition(empEmt.getAttribute("position"));

                                               emp.setTelephone(empEmt.getAttribute("telephone"));

                                               //emp对象添加至Employee对象数组empList

                                               empList[j]=emp;

                                               //将对象数组empList添加至部门对象dept的对象数组属性emp中。

                                               dept.setEmp(empList);

                                     }

                                     //dept对象添加至Department对象数组deptList中。

                                     deptList[i]=dept;

                                     /*  将对象数组deptList添加至公司对象comp的对象数组属性deptList中,

                                      * 并返回该公司对象。*/

                                     comp.setDept(deptList);

                            }

                   } catch  (ParserConfigurationException e) {

                            e.printStackTrace();

                   }catch  (SAXException e) {

                            e.printStackTrace();

                   } catch  (IOException e) {

                            e.printStackTrace();

                   }

                  

                   return  comp;

         }

        

         /**

          * XML文档:

          * java对象转换为XML文档,并将文档写入本地

          * @param  url 将要写入本地的XML文件的路径

          * @param  comp 需要转换的公司对象

          * @return返回文档在本地的绝对路径*/

         public  String writeXML(String url,Company comp){

                   try {

                            dBuilderdbfactory.newDocumentBuilder();   //通过文档创建工厂创建文档创建器,

                            Document doc = dBuilder.newDocument();       //并通过文档创建器创建一个新的文档对象。

                            Element root =  doc.createElement("company");//建立根节点company

                            //将根结点添加到文档中

                            doc.appendChild(root);

 

                            /*

                             * 通过循环将公司对象中的部门对象数组转换成部门节点,

                             * 并根据部门对象的属性设置部门节点的香瓜那属性,

                             * 最后将该部门节点添加至相应的公司节点中  */

                            for(int i  = 0;i < comp.getDept().length;i++){

                                     Department  dept = comp.getDept()[i];                                 

                                     Element  deptEmt = doc.createElement("department");    

                                     deptEmt.setAttribute("deptNo",  dept.getNumber());

                                     deptEmt.setAttribute("name",  dept.getName());                 

                                    

                                     /*

                                      * 通过循环将部门对象中的员工对象数组转换成员工节点,

                                      * 并根据员工对象的属性设置员工节点的相关属性,

                                      * 最后将该员工节点添加至相应的部门节点中  */

                                     for(int j  = 0;j < dept.getEmp().length;j++){

                                               Employee  emp = dept.getEmp()[j];                                        

                                               Element  empEmt = doc.createElement("employee");                 

                                               empEmt.setAttribute("position", emp.getPosition());

                                               empEmt.setAttribute("telphone",  emp.getTelephone());

                                               Text  tNode = doc.createTextNode(emp.getName());

                                               empEmt.appendChild(tNode);

                                               deptEmt.appendChild(empEmt);

                                     }

                                     root.appendChild(deptEmt);

                            }

 

                            docToXML(doc,  url);

                           

                   } catch  (ParserConfigurationException e) {

                            e.printStackTrace();

                   }

                   return  url;

         }

        

         /**

          * DOM树对象转换为可以写入本地的XML文档对象

          * @param  doc 需要转换的DOM对象

          * @param  filePath 转换后的XML文档存放的

          * @return写入成功返回true,转换过程中出现异常返回false

          */

         publicboolean  docToXML(Document doc,String filePath){

                  

                   //XML文档输出到指定的文件

                   try {

                            TransformerFactory  tFactory = TransformerFactory.newInstance();//创建转换器工厂实例

                            Transformer  tFormer= tFactory.newTransformer();//创建转换器

                            DOMSource dSource  = new  DOMSource(doc);//创建DOM输入源

                            StreamResult  sResult = new StreamResult(new  File(filePath));// 创建输出流

                           

                            //设置写入XML文件的编码、空白符和版本

                            tFormer.setOutputProperty(OutputKeys.ENCODING,"UTF-8");

                            tFormer.setOutputProperty(OutputKeys.INDENT, "yes");

                            tFormer.setOutputProperty(OutputKeys.VERSION, "1.0");

                           

                            tFormer.transform(dSource,  sResult); //  将内存中的XML文档转换输出到本地

                           

                   } catch  (TransformerConfigurationException e) {

                            e.printStackTrace();

                            returnfalse;

                   }catch  (TransformerException e) {

                            e.printStackTrace();

                            returnfalse;

                   }

                   returntrue;

         }

        

         /**

          * 处理XML文档:

          *    1.修改company节点的address属性为"郑州市金水区文化路与丰产路交叉口向东50SOHO世纪城"

          *    2.修改工程师A的名字为王工程师

          *    3."许刚"添加telephone属性,并将值设置为7654321

          *    4.删除"申林"telephone属性

          *  5.删除名字为"实习生A"employee节点

          * @param  inUrl 要处理的XML文档的url

          * @param  outUrl 处理后的XML文档存放的的url

          */

         publicvoid  XMLHandle(String inUrl,String outUrl){

                   try {

                            //获得XML文档的树对象

                            dBuilderdbfactory.newDocumentBuilder();

                            dbfactory.setIgnoringElementContentWhitespace(true);

                            Document doc = dBuilder.parse(inUrl);

                            Element company =  doc.getDocumentElement();//获得根节点

                            NodeList emps = company.getElementsByTagName("employee");//获得所有employee节点

                           

                            //1.修改company节点的address属性

                            company.setAttribute("address", "郑州市金水区文产路交叉口向东50SOHO世纪城");

                           

                            //2.修改工程师A的名字为王工程师

                            //Element  emp = (Element) company.getFirstChild().getLastChild();

                            Element emp =  (Element) emps.item(1);

                            emp.replaceChild(doc.createTextNode("王工程师"),emp.getFirstChild());

                           

                            //3."许刚"添加telephone属性,并将值设置为7621

                            emp = (Element)  emps.item(0);

                            emp.setAttribute("telephone", "7654321");

                           

                            //4.删除"申林"telephone属性

                            emp = (Element)  emps.item(2);

                            emp.removeAttribute("telephone");

                           

                            //5.删除名字为"实习生A"employee节点

                            emp.getParentNode().removeChild(emps.item(3));

                           

                            //重新写入修改后的XML文档

                            docToXML(doc,outUrl);

                   } catch  (ParserConfigurationException e) {

                            e.printStackTrace();

                   }catch  (SAXException e) {

                            e.printStackTrace();

                   } catch  (IOException e) {

                            e.printStackTrace();

                   }

         }

}

H.    测试类DOMParserTest.java源码如下:

package  parsersTest;

/**

 * Test parsers.

 * Copyright 2010.9 NTCsoft(郑州蜂鸟科技有限公司) , Inc. All rights reserved.

 * @author  ZhouYuan

 * @since  2010-9-24

 * @version  1.0

 */

//导入解析器

import  xmlParsers.DOMParser;

//导入实体类

import  domain.Company;

import  domain.Department;

import  domain.Employee;

 

/**

 * Test DOMParser. */

publicclass  DOMParserTest {

         publicstaticvoid  main(String args[]){

                   //实例化解析器

                   DOMParser dp = new  DOMParser();

        

                   //XML测试方法

                   Company comp = dp.readXML("src/Company.xml");

                   System.out.println("公司名称:"+comp.getName());

                   System.out.println("公司地址:"+comp.getAddress());

                   for(int i  =0; i < comp.getDept().length; i++){

                            Department  department = comp.getDept()[i];

                            System.out.println("\t部门编号:"+department.getNumber()

                                                                 +"\t部门名称:"+department.getName());

                            for(int j  = 0; j < department.getEmp().length;  j++){

                                     Employee  employee = department.getEmp()[j];

                                     System.out.println("\t\t部门成员:\n\t\t\t姓名:"+employee.getName()

                                                                 +"\t职位:"+employee.getPosition()

                                                                 +"\t联系方式:"+employee.getTelephone());

                            }

                   }

                  

                   //XML测试方法

                   dp.writeXML("d:\\company.xml",  comp);

                  

                   //处理XML测试方法

                   dp.XMLHandle("src/Company.xml", "e:\\company.xml");

         }

}

      

DOM4J方式解析XML

A.      概述:

DOM4J是一个易用的,开源的库,用于XML,XPath,XSLT。它应用于Java平台,采用了Java集合框架并完全支持DOM,SAX,JAXP

B.       特点:

它合并了许多超出基本 XML 文档表示的功能,包括集成的 XPath 支持、XML Schema 支持以及用于大文档或流化文档的基于事件的处理。

它具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件。

C.       XMLPath简介:

XPath 是一门在 XML 文档中查找信息的语言,可用来在 XML 文档中对元素和属性进行遍历。XPath 使用路径表达式来选取 XML 文档中的节点或者节点集。这些路径表达式和我们在常规的电脑文件系统中看到的表达式非常相似。

1.      常用的路径表达式和实例,如表3-1所示:

表达式

附加说明

实例

nodename

选取此节点的所有子节点

company:选择company元素的所有子节点

/

从根节点选取

/company:选择根元素company

//

从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置

//employee:选择所有employee子元素,不论它们在文档中什么位置

.

选取当前节点

当前节点为company时: .//employee表示选取company节点下节点名称为employee的所有子节点

..

选取当前节点的父节点

当前节点为employee时: ..表示employee的父节点department

@

选取属性

//@lang:选择所有属性名为lang的属性节点,不论它们在文档中什么位置

3-1

2.      常用谓语选择器,如表3-2所示:

实例

说明

/department/employee[1]

选取department 元素的第一个 employee子元素。

/department/employee  [last()]

选择department元素下的最后一个employee子元素

/department/employee  [last()-1]

选择department元素下的倒数第二个employee子元素

/department/employee  [position()<3]

选取最前面的两个属于 department元素的子元素的 employee元素。

//employee[@telephone]

选取所有拥有名为 telephone的属性的 employee元素。

//department[employee='实习生A']

选取所有 department元素,且其中子元素 employee的文本内容为实习生A。

3-2

D.      在解析过程中需要使用的包、接口和类:

1.      需要导入的3个外部JAR包,如图3-5所示。dom4j-1.6.1.jar可从sourceforge网站上获得;jaxen.jar可从java2s上获得,saxpath.jar也可从java2s上获得,以上jar包同时也可从服务器上获得。

3-5

2.      在解析过程中需要使用的包、接口和类:

//使用dom4j解析xml文档的辅助类

import  org.dom4j.*;

//需要使用util包下的list接口和Iterator接口

import  java.util.*;

//java标准输入输出控制

import  java.io.*;

//用于创建使用各种方式读取XML源和以各种方式输出XML源的解析器

import  org.dom4j.io.*;

 

//导入实体类

import  domain.Company;

import  domain.Department;

import  domain.Employee;

E.       读取本地XML文档解析并转换为对象的步骤:

该步骤与DOM方式解析XML类似,只不过使用的API和操作方式不同。剑理一致,招式不同。

1.      创建负责把XML文档源文件解析为文档对象树的解析器。

//使用org.dom4j.io.包下DOM4J已经配置好的SAXReader读取XML文档。

SAXReader  reader = new  SAXReader();

//设置读取文件的编码为UTF-8

reader.setEncoding("utf-8");

//读取url指定的xml文件并返回一个新的DOM4Jdocument对象

Document  doc = reader.read(url);

2.      使用list方式和iterator方式遍历节点:

List方式:

//通过Elementelements("nodeName")方法获得子节点并返回一个java标准列表List<Element>  emps = deptEmt.elements("employee");

//根据得到的列表大小创建Employee对象数组

Employee[]  empList = new Employee[emps.size()];

 

Iterator方式:

//生成遍历department节点下名称为employee的所有元素节点的迭代器

Iterator  empIte = root.elementIterator("department");

Element  empEmt = (Element) empIte.next();

3.      遍历节点后将节点信息存储在java对象的实体类中,并返回该对象

F.        java实体类对象转换为DOM4J文档对象并写入本地的步骤:

1.      创建XML文档对象

//使用DOM4JDocumentHelper类的静态方法createDocument()创建一个XML文档对象。

Document  doc = DocumentHelper.createDocument();

2.      使用DOM4J提供的节点操作方法创建节点对象并将java实体类对象中的信息存放至节点对象中。

3.      XML对象转换和格式化后写入本地

//使用org.dom4j.io包下的XMLWriter类将DOM4J的文档树对象转换为XML流文件并格式化输出。

XmlWriter  xmlWriter;

//创建有格式和缩进的格式化输出对象

OutputFormat  format = OutputFormat.createPrettyPrint();

//创建紧凑的无空白符和缩进的格式化输出对象

//OutputFormat  format = OutputFormat.createCompactFormat();

format.setEncoding("UTF-8");

//将新的文件输出流对象和格式化对象封装进实例化的XMLWriter对象中

xmlWriter  = new  XMLWriter(new FileOutputStream(filePath),format);

//使用xmlWriter将文档对象写入本地并关闭

xmlWriter.write(doc);

xmlWriter.close();

G.      使用XpathDOM4J的节点处理方法处理文档:

1.      读取本地XML文档并转换为Document对象

2.      使用XPath获得需要处理的节点,并修改文档对象模型。

3.      将处理好的文档写入本地。

I.       解析器DOM4JParser.java的全部源码:

/**

 * Parse XML document with DOM4J.

 * Copyright 2010.9 NTCsoft(郑州蜂鸟科技有限公司) , Inc. All rights reserved.

 * @author  ZhouYuan

 * @since  2010-9-24

 * @version  1.0

 */

package  xmlParsers;

//使用dom4j解析xml文档的辅助类

import  org.dom4j.*;

//需要使用util包下的list接口和Iterator接口

import  java.util.*;

//java标准输入输出控制

import  java.io.*;

//用于创建使用各种方式读取XML源和以各种方式输出XML源的解析器

import  org.dom4j.io.*;

 

//导入实体类

import  domain.Company;

import  domain.Department;

import  domain.Employee;

 

 

/**

 * Parse XML document with DOM4J.*/

publicclass  DOM4JParser{

        

         /**

          * 使用List方式遍历XML文档

          * @param  url XML文件路径

          * @return返回Company对象

          * @throws  DocumentException 使用SAXReader读取XML文档时需要处理该异常

          */

         @SuppressWarnings("unchecked")

         public  Company readXMLInList(String url) throws  DocumentException{

                   //创建公司对象

                   Company comp = new  Company();

                   //使用org.dom4j.io.包下DOM4J已经配置好的SAXReader读取XML文档。

                   SAXReader reader = new  SAXReader();

                   reader.setEncoding("utf-8");//设置读取文件的编码为UTF-8

                   Document doc =  reader.read(url); //读取url指定的xml文件

                   //得到文档的根元素company

                   Element root =  doc.getRootElement();

                   //使用ElementattributeValue(String arg)方法读取XML文档中的公司信息,并为公司对象设置相关属性。

                   comp.setAddress(root.attributeValue("address"));

                   comp.setName(root.attributeValue("name"));

                  

                   //通过elements(String arg)方法读取XML文档中的所有root节点下的department节点并返回一个List

                   List<Element> depts =  root.elements("department");

                   //创建Department对象数组

                   Department[] deptList = new  Department[depts.size()];

                  

                   //读取部门信息,并将部门对象添加至公司对象中。

                   for(int i  = 0;i < depts.size();i++){

                            Department dept = new  Department();

                            //使用Listget(int index)方法遍历List,返回列表中的第每一项。

                            Element deptEmt =  depts.get(i);

                            dept.setName(deptEmt.attributeValue("name"));

                            dept.setNumber(deptEmt.attributeValue("deptNo"));

                           

                            //通过Elementelements("nodeName")方法获得子节点并返回一个java标准列表对象

                            List<Element>  emps = deptEmt.elements("employee");

                            //根据得到的列表大小创建Employee对象数组

                            Employee[] empList  = new  Employee[emps.size()];

                            /*

                             * 读取雇员信息,并将雇员对象添加至部门对象中。*/

                            for(int j  = 0;j < emps.size();j++){

                                     Employee  emp = new  Employee();

                                     //XML中的employee节点转换为Employee对象emp,并设置对象属性。

                                     Element  empEmt = emps.get(j);

                                     emp.setName(empEmt.getText());

                                     emp.setPosition(empEmt.attributeValue("position"));

                                     emp.setTelephone(empEmt.attributeValue("telephone"));

                                     //emp对象添加至Employee对象数组empList

                                     empList[j]=emp;

                                     //将对象数组empList添加至部门对象dept的对象数组属性emp中。

                                     dept.setEmp(empList);

                            }

                            //dept对象添加至Department对象数组deptList中。

                            deptList[i]=dept;

                            /*  将对象数组deptList添加至公司对象comp的对象数组属性deptList中,

                             * 并返回该公司对象。*/

                            comp.setDept(deptList);

                   }

                   return  comp;

         }

        

         /**

          * 使用Iterator方式遍历XML文档

          * @param  url XML文件路径

          * @return返回Company对象

          * @throws  DocumentException 使用SAXReader读取XML文档时需要处理该异常

          */

         @SuppressWarnings("unchecked")

         public  Company readXMLInIterator(String url) throws  DocumentException{

                   //创建公司对象

                   Company comp = new  Company();

                   //使用org.dom4j.io.包下DOM4J已经配置好的SAXReader读取XML文档。

                   SAXReader reader = new  SAXReader();

                   reader.setEncoding("utf-8");//设置读取文件的编码为UTF-8

                   Document doc =  reader.read(url); //读取url指定的xml文件

                   //得到文档的根元素company

                   Element root =  doc.getRootElement();

                   //使用ElementattributeValue(String arg)方法读取XML文档中的公司信息,并为公司对象设置相关属性。

                   comp.setAddress(root.attributeValue("address"));

                   comp.setName(root.attributeValue("name"));

                  

                   //创建Department对象数组

                   Department[] deptList = new  Department[(root.elements("department")).size()];

                   /*

                    * 本段代码解释:读取部门信息,并将部门对象添加至公司对象中。

                    * for循环语句解释:生成遍历root节点下名称为department的所有元素节点的迭代器  */

                   for(Iterator  deptIte = root.elementIterator("department");deptIte.hasNext();){

                            int  i=0 ,j=0;//数组下标标志值

                            Department dept = new  Department();

                            //使用Listget(int index)方法遍历List,返回集合中的第每一项。

                            Element deptEmt =  (Element) deptIte.next();

                            dept.setName(deptEmt.attributeValue("name"));

                            dept.setNumber(deptEmt.attributeValue("deptNo"));

                            //创建Employee对象数组

                            Employee[] empList  = new  Employee[deptEmt.elements("employee").size()];

                           

                            /*

                             * 本段代码:读取雇员信息,并将雇员对象添加至部门对象中。

                             * for循环语句:生成遍历deptEmt节点下名称为employee的所有元素节点的迭代器  */

                            for(Iterator  empIte = root.elementIterator("department");deptIte.hasNext();){

                                     Employee  emp = new  Employee();

                                     //XML中的employee节点转换为Employee对象emp

                                     Element  empEmt = (Element) empIte.next();

                                     emp.setName(empEmt.getText());

                                     emp.setPosition(empEmt.attributeValue("position"));

                                     emp.setTelephone(empEmt.attributeValue("telephone"));

                                     //emp对象添加至Employee对象数组empList

                                     empList[j]=emp;j++;

                                     //将对象数组empList添加至部门对象dept的对象数组属性emp中。

                                     dept.setEmp(empList);

                            }

                            //dept对象添加至Department对象数组deptList中。

                            deptList[i]=dept;i++;

                            /*  将对象数组deptList添加至公司对象comp的对象数组属性deptList中,

                             * 并返回该公司对象。*/

                            comp.setDept(deptList);

                   }

                   return  comp;

         }

 

         /**

          * java实体类对象转换为DOM4J文档对象并写入本地

          * @param  url 文档写入路径

          * @param  comp 需要转换的java实体类对象

          * @return成功时返回写入文件的url,失败时返回字符串Some  Exception Occurred

          */

         public  String writeXML(String url,Company comp){

                            Document doc =  DocumentHelper.createDocument();                 //通过文档帮助工具创建一个新的文档对象。

                            Element root =  doc.addElement("company")

                                               .addAttribute("name",  comp.getName())

                                               .addAttribute("address",  comp.getAddress());//建立根节点company并添加至文档中

 

                            /*

                             * 通过循环将公司对象中的部门对象数组转换成部门节点,

                             * 并根据部门对象的属性设置部门节点的相关属性,

                             * 最后将该部门节点添加至相应的公司节点中  */

                            for(int i  = 0;i < comp.getDept().length;i++){

                                     Department  dept = comp.getDept()[i];                                 

                                     Element  deptEmt = root.addElement("department")

                                                        .addAttribute("deptNo",  dept.getNumber())

                                                        .addAttribute("name",  dept.getName());  

                                     /*

                                      * 通过循环将部门对象中的员工对象数组转换成员工节点,

                                      * 并根据员工对象的属性设置员工节点的相关属性,

                                      * 最后将该员工节点添加至相应的部门节点中  */

                                     for(int j  = 0;j < dept.getEmp().length;j++){

                                               Employee  emp = dept.getEmp()[j];                                        

                                               deptEmt.addElement("employee")

                                                                 .addAttribute("position",  emp.getPosition())

                                                                 .addAttribute("telephone",  emp.getTelephone())

                                                                 .addText(emp.getName());                 

                                     }

                            }

                            //将文档对象写入本地

                            if(docToXML(doc,url)){

                                     System.out.println("文件写入成功");return  url;

                            }else{

                                     System.out.println("文件写入失败");return"Some  Exception Occurred";}

         }

        

         /**

          * DOM树对象转换为可以写入本地的XML文档对象

          * @param  doc 需要转换的DOM对象

          * @param  filePath 转换后的XML文档存放的

          * @return写入成功返回true,转换过程中出现异常返回false

          */

         publicboolean  docToXML(Document doc,String filePath){

                   try {

                            //  使用org.dom4j.io包下的XMLWriter类将DOM4J的文档树对象转换为XML流文件并格式化输出。

                            XMLWriter  xmlWriter;

                            //创建有格式和缩进的格式化输出对象

                            OutputFormat  format = OutputFormat.createPrettyPrint();

                            //创建紧凑的无空白符和缩进的格式化输出对象

                            //OutputFormat  format = OutputFormat.createCompactFormat();

                            //设置XML文档的输出编码

                            format.setEncoding("UTF-8");

//                         format.setIndent(true);

//                         format.setNewlines(true);

                            //将新的文件输出流对象和格式化对象封装进实例化的XMLWriter对象中

                            xmlWriter = new  XMLWriter(new FileOutputStream(filePath),format);

                            //使用xmlWriter将文档对象写入本地

                            xmlWriter.write(doc);

                            xmlWriter.close();

                            returntrue;

                   } catch  (IOException e) {

                            e.printStackTrace();

                            returnfalse;

                   }

         }

        

         /**

          * 处理XML文档:

          *    1.修改属性:修改company节点的address属性为"郑州市金水区文化路与丰产路交叉口向东50SOHO世纪城"

          *    2.修改文本节点:工程师A的名字为王工程师

          *    3.添加属性:为"许刚"添加telephone属性,并将值设置为7654321

          *    4.删除属性:删除"申林"telephone属性

          *  5.删除节点:删除名字为"实习生A"employee节点

          * @param  inUrl 要处理的XML文档的url

          * @param  outUrl 处理后的XML文档存放的的url

          */

         @SuppressWarnings("unchecked")

         publicvoid  XMLHandle(String inUrl,String outUrl){

 

                   //获得XML文档的树对象

                   SAXReader reader = new  SAXReader();

                   reader.setEncoding("utf-8");

                   Document doc;

                   try {

                            doc =  reader.read(inUrl);

 

                   Element company =  doc.getRootElement();//获得根节点

                   List empList =  company.selectNodes("//employee");//获得所有的employee节点

                   //1.修改company节点的address属性

                   company.attributeValue("address", "郑州市金水区文产路交叉口向东50SOHO世纪城");

                  

                   //2.修改工程师A的名字为王工程师

                   Node developer = (Node)  empList.get(1);

                   developer.setText("王工程师");

 

                   //3."许刚"添加telephone属性,并将值设置为7654321

                   Element xugang = (Element)  empList.get(0);

                   xugang.addAttribute("telephone", "7654321");

 

                   //4.删除"申林"telephone属性

                   Element shenlin = (Element)  doc.selectSingleNode("//department[2]//employee[1]");

                   shenlin.remove(shenlin.attribute("telephone"));

                  

                   //5.删除名字为"实习生A"employee节点

                   Element shiXiSheng =  (Element) doc.selectSingleNode("//department[2]//employee[2]");

                   Element par = (Element)  shiXiSheng.getParent();

                   par.remove(shiXiSheng);

 

                   //重新写入修改后的XML文档

                   docToXML(doc,outUrl);

                   System.out.println("----------------Success----------------");

                   } catch  (DocumentException e) {

                            System.out.println("----------------fail----------------");

                            e.printStackTrace();

                   }

         }

}

J.         测试类DOM4JParserTest.java源码如下:

package  parsersTest;

/**

 * Test DOM4JParser.

 * Copyright 2010.9 NTCsoft(郑州蜂鸟科技有限公司) , Inc. All rights reserved.

 * @author  ZhouYuan

 * @since  2010-9-24

 * @version  1.0

 */

//解析过程中可能抛出此异常

import  org.dom4j.DocumentException;

//导入解析器

import  xmlParsers.DOM4JParser;

//导入实体类

import  domain.Company;

import  domain.Department;

import  domain.Employee;

 

publicclass  DOM4JParserTest {

 

         publicstaticvoid  main(String args[]) throws DocumentException{

                   //实例化解析器

                   DOM4JParser d4jp = new  DOM4JParser();

        

                   //使用ListXML测试方法

                   Company comp =  d4jp.readXMLInList("D:\\Company.xml");

                   System.out.println("公司名称:"+comp.getName());

                   System.out.println("公司地址:"+comp.getAddress());

                   for(int i  =0; i < comp.getDept().length; i++){

                            Department  department = comp.getDept()[i];

                            System.out.println("\t部门编号:"+department.getNumber()

                                                                 +"\t部门名称:"+department.getName());

                            for(int j  = 0; j < department.getEmp().length;  j++){

                                     Employee  employee = department.getEmp()[j];

                                     System.out.println("\t\t部门成员:\n\t\t\t姓名:"+employee.getName()

                                                                 +"\t职位:"+employee.getPosition()

                                                                 +"\t联系方式:"+employee.getTelephone());

                            }

                   }

                  

                   //使用IteratorXML测试方法

                   comp = d4jp.readXMLInList("src/Company.xml");

                   System.out.println("公司名称:"+comp.getName());

                   System.out.println("公司地址:"+comp.getAddress());

                   for(int i  =0; i < comp.getDept().length; i++){

                            Department  department = comp.getDept()[i];

                            System.out.println("\t部门编号:"+department.getNumber()

                                                                 +"\t部门名称:"+department.getName());

                            for(int j  = 0; j < department.getEmp().length;  j++){

                                     Employee  employee = department.getEmp()[j];

                                     System.out.println("\t\t部门成员:\n\t\t\t姓名:"+employee.getName()

                                                                 +"\t职位:"+employee.getPosition()

                                                                 +"\t联系方式:"+employee.getTelephone());

                            }

                   }

                  

                   //XML测试方法

                   d4jp.writeXML("D:\\company.xml",  comp);

                  

                   //处理XML测试方法

                   d4jp.XMLHandle("src/Company.xml", "F:\\company.xml");

         }

}

实战

A.      创建一个新的工程,并创建如下所示的XML实例和对应的实体类对象。

Company.xml源码如下:

<?xml version="1.0" encoding="utf-8"?>

<bookstore>

<book category="database">

  <title lang="中文">数据库系统概论</title>

  <author sex="">萨师煊</author>

  <author>王珊</author>

  <year>2000</year>

</book>

 

<book category="datastructer">

  <title lang="CH">数据结构</title>

  <author email="yanweimin@qq.com">严蔚敏</author>

  <year>2004</year>

  <price>16.00</price>

</book>

 

<book category="java">

  <title lang="英文">JAVA2核心技术卷1</title>

  <author>Cay  S. Horstmann</author>

  <author>Cary  Cornell</author>

  <year>2006</year>

  <price>88.00</price>

</book>

</bookstore>

B.       XML文件读取:使用DOM方式和DOM4J方式读取该XML文件并转换为JAVA实体类对象输出。

C.       XML文件写入:使用DOM方式和DOM4J方y式将JAVA实体类对象转换为XML文件写入本地。

D.      XML文件操作:

1.      增加bookstore节点的address属性,并设置属性值为"河南新华书店"。

2.      为数据库系统概论这本书增加price节点,节点值为25.1。

3.      修改数据库系统概论的lang属性值为"CH"。

4.      修改严蔚敏的名字为"YanWeiMin"。

5.      删除类别为java的节点,及其子节点。

6.      删除数据结构这本书作者的email属性

 

 

SAXJDOM下节课继续讲解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值