Java XML解析技术

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/xingweiyang/article/details/83381900
                                        **Java XML解析技术**

                    **XML概述**
随着软件程序从独立的单机应用程序演化为分布式的企业系统,开发人员开始要面对一系列新的挑战。应用程序不再仅仅运行于一台机器上,而是会运行于多台机器上,并且这些机器的硬件架构、操作系统还可能不一样。这样,开发人员的挑战就是要定义一种通用的机制,使得采用不同编程语言编写的、运行于不同操作系统平台上的应用程序之间可以相互通讯。
假如所有的应用程序都是用Java编写的,我们的工作就会变得很简单。我们知道,Java是被设计用在统一的虚拟机上的,而该虚拟机的职责就是把Java表示的数据转换成操作系统认识的数据。Java用4个字节表示整数,而有些编程语言却是用2个字节表示整数,那么我们如何解释丢失的2个字节呢?Windows和Unix操作系统对数据字节表示的底层解释是不同的:对于4个字节的整数的各个位数,这两种操作系统的解释互不相同,因此所产生的结果值是不同的。
在现实中,应用程序可能是用Java编写的,还有可能是用C#、VB、Delphi、C、C++等编程语言编写的。考虑直接与硬件对话的那一类应用程序:这类应用程序需要直接与底层操作系统交互,需要理解硬件所处的计算机架构。这只是一类无法使用Java的情况,另外一类情况是软件所运行的操作系统还没有开发Java虚拟机。
我们已经了解了一些我们所面临的挑战,现在我们继续想想,怎样在两个应用程序之间无二义性地传递数据呢?假设要传递带有值65的变量speed,那么我们就要尝试传输两个数据:值65,该值代表速度。前面已经提到过,不能把整型值当成一系列二进制位传递。那么,能不能把数据当作字符串(字符6后面跟着字符5)发送呢?不管操作系统及编程语言是什么,字符5总是一样的。
XML(可扩展标记语言,eXtended Markup Language)是当今出现的最重要的十大软件开发技术之一。它是一种允许Web应用程序开发人员创建自定义标记,以便更有效组织和传递内容的语言。在XML文档中,用户可以定义自己需要的标记,创造自己的标记语言,只要在定义标记时遵循XML规范即可。XML定义了一套元句法,这些符合规范的XML文档能够很容易地被应用程序统一解析。这样,数据的存储和传输就有章可循。
XML由于简洁高效,能够用纯文本的形式表现各种复杂的有层次的数据及其之间的相互关系,易于在各个平台上构造和解析,因此在数据交换、结构化数据存储与显示、内容呈现与显示格式分离等方面得到了广泛的应用。

                     **XML语法规则**
一个XML文档由两个部分组成:一个部分是序言,包括XML文档声明、注释、空白;另一个部分是文档元素,这两个部分是必须的。此外,我们还可以选择性地包含注释、处理指令和空白。

                 XML声明
XML文档声明由“<?xml”开始,以“?>”结束。这个声明的作用在于告诉XML处理程序:该文档是按照XML文档规范对数据进行组织的。
XML声明有版本号(version)、独立文档声明(standalone)和编码声明(encoding)三个属性。属性是由等号分开的名称-数值对,位于等号左边的是属性名,而其值位于等号的右边,并用双引号括起来。
版本声明指明文档所采用的XML版本号,必须排在第一位。目前1.0是唯一可用的版本。这个属性是XML文档声明必需的。
编码声明则指明该文档所使用的编码方式,是可选属性。XML默认的字符集是Unicode。Unicode是一种双字节字符,可以标识当今使用的大多数字符,包括汉字。UTF-8是Unicode的压缩版本,而UTF-16则是Unicode的双字节编码实现。如果文档不使用默认的Unicode编码方式,则必须为encoding属性指定一个编码方式。简体中文采用GB2312编码,繁体中文则采用BIG5编码。对于某些XML处理程序而言,GB2312有时候会出现中文乱码的情况,所以我们应该根据实际情况选择合适的编码方式:UTF-8、UTF-16、GB2312、BIG5或者ISO8859-1。
独立文档声明指明文档是否有外部的标记声明文件相配套使用,属性取值为“yes”或“no”。如果standalone的值为yes,代表所有的文档都在一个文件里完成。这个属性也是可选属性。
XML声明是大小写敏感的,不可以用“<? XML”或者其它形式。而且,XML声明必须在文档的最前面,之前不能出现任何的空白或者注释。

                 XML文档注释
XML文档注释以“<!--”开始,以“-->”结束。在XML文档被XML处理程序解析时,这些注释内容会全部被忽略不显示。当我们希望XML文档中的某些内容被解析器忽略时,可以使用注释的方式。
注释内容不能出现在XML声明之前,也不能放在任何标记当中。但是,可以包围和隐藏标记。
值得注意的是,在注释的内容中不要出现“--”或者“-”,因为容易混淆;不要把注释放在原有标记中间,如:<NAME <! --The name --> >TOM CRUISE</NAME>。

                 处理指令(PI)
处理指令(Processing Instruction)被用来为XML处理程序提供信息,以“<?处理指令名称 处理指令信息?>”的格式呈现,通常它用来传递信息给解析器的下游程序。例如:
<?xml:stylesheet type="text/xsl" href="example.xsl"?> 
上面的指令指明了与其所属文档配套使用的样式表的类型为XSL(eXtensible Style sheet Language),文件名称为example.xsl,并且与该XML文档同在一个目录下。在显示XML文档内容的时候,为XML指定相应的XSL是一种比较快捷的方法。如果没有指定样式表,则浏览器按照自己默认的样式显示文档内容。

                  XML空白
XML空白是指由一个或者更多的空格符、制表符、回车符、换行符等组成的字符或者字符串。通常,为了使XML文档显示起来更直观,在开始标记、结束标记、注释、处理指令等地方添加空白是必要的。

                  XML元素
1. 开始和结束标记
为自定义标记取名称时,可以采用中文或者英文,但是名称必须以一个字母或者下划线开始。开始标记的名称必须与结束标记的名称一致,包括所有字母的大小写。
按照XML规范的要求,每个格式良好的XML文档必须有一个根元素,所有其它的元素都必须嵌套在它里面。根元素的起始标记要放在所有其他元素的起始标记之前,而根元素的结束标记要放在所有其他元素的结束标记之后。对于我们的根元素book,其起始标记是<book>,而结束标记是</book>,其文档现在看起来像下面的样子:
<?xml version="1.0" encoding="GB2312" ?>
<book>
客户端网页编程
</book>
每个XML文档至少有一个XML元素;大小写不同的标记含义不同,如<TITLE>不同于<title>;结束标记必须带反斜杠,如</TITLE>,当只有一个标记时可以写为<HR/>;嵌套必须完整
除以上规则外,XML元素标记还必须遵循下面的命名规则:
名字中可以包含字母、数字以及其它字母;
	名字不能以数字或下划线开头;
	名字不能以字母xml(或XML或Xml..)开头;
	名字中不能包含空格和冒号。
2. 元素内容
XML元素内容可以是字符数据、嵌套的元素、实体引用、CDATA。
	字符数据
元素内容可以是字符数据。但是内容中不能包含小于号(<)、连字符(&)、或者字符串(]]>)。
	嵌套元素
元素内容可以是嵌套的元素,单层或者多层的嵌套都可以。
	实体
实体在XML中是存储单元,一个实体可以包含字符串、文件、数据库记录,以及一些其他数据。应用实体主要是为了避免在文档中进行重复输入,我们可以为一个文档安排一个实体名,然后在XML文件中用这个名字代替引入文档,当XML文件解析时,实体名被替换为文档。
有些符号如:“<”、“””、“>”等在XML中是预定义的,如果在我们的XML文档中出现了这样的数据则容易混淆,为此XML给我们预定义了五个实体来代替它们

在这里插入图片描述

	CDATA
大多数情况下,出现在一对尖括号(<>)中的是标记,不在尖括号中的是字符数据。但是有一种情况例外,在CDATA段中所有文本都是纯字符数据。看起来与标记或者实体相似的仅仅是它们各自相应的文本。XML处理器无论如何是不会解析它们的。
CDATA段用于需要把整段文本解释为纯字符数据而并不是标记的情况。当有一个包含许多“<”、“>”、“&”或“"”字符而非标记的庞大文本时,这是非常有用的。对于大部分C和Java源代码,正是这种情况。
3. 元素的属性
XML元素也可以拥有自己的属性。这是让文档包含有关信息的一个简单的方式。属性说明及其取值成对出现,中间以等号(=)分隔开,两者均为字符串。每个元素可以包含零到多个属性。属性通常被用来表现那些与元素内容无关的简单数据,或者不希望呈现给用户的非结构化数据。属性命名必须符合如下的规则:
	属性名以一个字母或者下划线开始,名称中不能包含有空格。
	同一个元素不能有两个同名的属性,即同一个属性在一个元素中只能出现一次。
	属性名是区分大小写的。
	不能使用任何形式的以“xml”为前缀的属性。
属性的取值则是由引号界定的一系列字符,也应该遵守如下的规则:
	属性取值由引号界定,可以使用单引号或者双引号,但是必须成对出现。
	属性取值字符串不能包含用于界定它的同种引号,不能包含<字符。
	属性取值不能包含&字符,除非以一个字符或者实体引用开始。

                     **XML技术体系概述**
我们已经初步认识了XML文档,掌握了XML的基础语法规则。下面我们列出学习XML所要掌握的XML技术体系。
	 文档描述与校验技术:DTD和Schema都是用于定义XML结构,并且用于校验我们书写的XML文档是否符合要求的技术。
	文档转换技术(XSL /XSLT):XML的一大特点就是内容与格式分离,也就是说,XML文档中并不包含如何显示/表示文档的信息。XSL(XML Style Language)解决了XML文档的显示问题。 利用XSL中的XSLT,可以把XML文件转成其它格式的语言。可转换的格式包括:文本文件、PDF文件、HTML、以逗号为分隔符的文件,或其它XML文件。
	文档查询技术(XPath/XQuery):XPath和XQuery是用于从XML文件中抽取单个项目或一组项目的查询语言。XPATH、XQuery与XML的关系正像SQL与关系数据库的关系。
	 文档解析技术(XML DOM/SAX):XML DOM和SAX实现XML编程接口,使我们可以解析XML文档,即对XML文档进行编程。
	文档链接和定位技术(XLink/XPointer):作为一种Web语言,XML的链接能力是非常重要的。XML的链接和定址机制包括XLink、XPath和XPointer。XLink提供功能强大的链接方法,可以在文档之间建立单向或多向的复杂联结关系,还有注释链接、概要链接、扩展链接集等多种链接功能。XPath在XSLT和XPointer中使用,支持在XML文档中相对于节点和节点集的定位。XPointer在XPath的基础上提供对XML文档的内容的内部结构(如一个字符串或者选择的一个段落)的定位。

                        **XML解析技术**
编程语言怎么样才能识别XML文件中的数据把它变成自己有用的信息呢?这里就要用到了XML处理器概念,支持XML的编程语言都提供了相对应的XML处理器。XML处理器更常用的名称是解析器,通俗地说,在Java里,XML解析器就是一系列用来识别XML文档的API的集合。
XML解析器有两种形式,即:
	进行验证的处理器――检查XML文档的有效性和格式规范。
	不进行验证的处理器――检查XML文档的格式规范。
为了能够处理XML文档,几乎所有的应用程序都需要一个XML解析器。解析器从文档中提取实际的数据,然后创建一系列的事件或者是新的数据结构。解析器也能够检查文档否严格的遵守了XML规范,而这是处理XML文档之前就必须进行的工作。另外,解析器还应该能够判断一个文档是否遵守DTD/Schema标准,如果该文档有一个DTD/Schema的话。
XML解析器使用的两种基本API是:
	文档对象模型(DOM),一种基于树结构的API。
	XML简单API(SAX),一种事件驱动的API。
大部分常用的编程语言和环境都实现了SAX和DOM API,包括C、C++、Perl、Python和Java,本章稍后将详细讨论这些API。

             	DOM
DOM(Document Object Model)表示文档对象模型。它定义了一组Java接口,用于创建、访问和操纵XML文档的内部结构。它是基于对象的,与语言和平台无关。整个XML文档被作为对象的体系结构排列进行解析和存储,因此客户端应用程序就可以随机访问这些对象。DOM的一个显著特点就是整个文档必须在内存中解析和存储,对于那些需要对文档不同部分进行重复、随机访问的应用程序。DOM非常有用,但对于大型文档则会造成内存紧张。
在DOM中,XML文档表示为树,其节点为元素或文本。XML处理器生成树,然后将其传递给应用程序。

在这里插入图片描述

树上的每个项目称为节点,每个最终节点通常称为叶。树上的节点将自身与其他节点相关联。父节点指直接上级节点,祖先节点指任何上级节点,兄弟节点是共享同一父节点的节点。通过遍历树可以从文档的任一部分到达文档的任何其他部分。
所有DOM的树成分(如元素、文本和属性)均定义为从节点派生的接口。本章将在稍后讨论这些接口。
DOM最适用于下列情形:
	在结构上修改XML文档时。例如,以特定的顺序对元素进行排序或将某些元素从树中的一个位置移至另一个位置。
	在内存中与其他应用程序共享文档时。

                 	SAX
SAX是XML的简单应用程序编程接口。SAX提供一种用于解析XML文档的事件驱动模型,在识别不同的XML语法结构时,SAX解析器使用回调机制来通知客户端应用程序,而不是将整个文档都存储在内存中。即使是处理大型文档也不会占用大量内存。
具有SAX的XML处理器并不创建数据结构,而是扫描输入XML文档,并生成元素开始、元素结束等事件,在发生事件时,解析器会通知应用程序。
由于SAX不创建显式数据结构,因此它比DOM的效率更高。SAX适用于下列情形:
	在解析大型文档时,不必将整个文件加载到内存中,因此占用的内存比DOM少。
	在只需一个信息子集时,SAX忽略不需要的数据,而DOM无法做到这一点。
SAX应用程序一般包含的三个组件,即:
	应用程序。
	文档处理程序是编写用于处理文档内容的代码。
	解析器是符合SAX标准的XML解析器。
此应用程序创建了解析器和文档处理程序。通过调用解析器的parse()方法,它告诉解析器应使用哪个文档处理程序开始处理输入文档。解析器会将它在文档中发现的所有感兴趣的东西通知文档处理程序,如元素起始标记和结束标记。文档处理程序会处理这些通知,获得应用程序需要的任何内容。
注意:Sax并不把全部XML内容保存在自己的内存里,而是由Sax框架不断调用处理程序实现。由框架推送内容,处理程序通过回调函数处理所有内容。所以称为推模式。
以下列出了SAX的一些缺点:
	必须按到达顺序处理数据,不能对文档进行随机访问。
	SAX是只读的,它是设计用来读取XML文档而不是写入它们。
	文档只能遍历一次。

                    DOM和SAX解析技术的实现
实现DOM和SAX解析技术的方法有多种,下面列出了常用的几种方法:
	JAXP(Java API for XML):JAXP是对应用程序隐藏了特定解析器的接口,它提供了访问DOM和SAX实现的抽象层机制。
	JDOM:JDOM 是一种使用 XML 的独特 Java 工具包,用于快速开发 XML 应用程序。它基于树型结构,利用纯JAVA的技术对XML文档实现解析、生成、序列化以及多种操作。JDOM 直接为JAVA编程服务。它利用更为强有力的JAVA语言的诸多特性(方法重载、集合概念以及映射),把SAX和DOM的功能有效地结合起来。同时JDOM也是用Java语言读、写、操作XML的新API函数,在简单和高效的前提下,这些API函数被最大限度的优化,以弥补DOM及SAX在实际应用当中的不足之处。在 JDOM 中,XML 元素就是 Element 的实例,XML 属性就是 Attribute 的实例,XML 文档本身就是 Document 的实例。因此创建一个新 JDOM 对象就如在 Java 语言中使用 new 操作符一样容易。
	DOM4J:Dom4j是一个易用的、开源的库,用于XML、XPath和XSLT。它应用于Java平台,采用了Java集合框架并完全支持DOM、SAX和JAXP。在Java开发社区里,DOM4J的使用最为广泛。JDOM的操作非常简单,但是在处理大XML文件时性能表现不佳,解析10M文档时就会内存溢出。而DOM4J是一个非常优秀的Java XML API,具有性能优异、功能强大和易于使用的特点,同时它也是一个开放源代码的软件,DOM4J使用大量的接口,这也是它被认为比JDOM灵活的原因。如今我们可以看到越来越多的Java软件都在使用DOM4J来读写XML。DOM4J的官方地址是“http://www.dom4j.org/”。
由于在实际项目开发中,采用DOM4J的占主流,所以本书主要讲解DOM4J的使用。

在这里插入图片描述

1)利用DOM4J创建XML
本节将使用dom4j API创建 XML 文档。使用 DocumentHelper 类创建一个文档实例。 DocumentHelper类是生成 XML文档节点的dom4j API工厂类。
Document document = DocumentHelper.createDocument();
使用 addElement() 方法创建根元素 catalog 。addElement() 用于向 XML 文档中增加元素,并添加注释“An XML catalog”。
Element catalogElement = document.addElement("catalog");
catalogElement.addComment("An XML catalog");
在catalog元素中使用 addProcessingInstruction() 方法增加一个XML处理指令。
catalogElement.addProcessingInstruction("target","text");
在catalog元素中使用addElement()方法增加book元素。使用addAttribute()方法向 book元素添加title和publisher属性。
Element bookElement =  catalogElement.addElement("book");
bookElement.addAttribute("title", "XML Zone");
bookElement.addAttribute("publisher", "Java developer");
向book元素里添加article子元素,为 article 元素增加 level 和 date 属性
Element articleElement=bookElement.addElement("article");
articleElement.addAttribute("level", "Intermediate");
articleElement.addAttribute("date", "8-2008");
向article元素中增加 title 元素,使用setText()方法设置article元素的文本。
Element titleElement=articleElement.addElement("title");
titleElement.setText("Java configuration with XML Schema");
在article元素中增加author元素在author元素中增加firstname元素和lastname元素并设置元素的文本。
Element authorElement=articleElement.addElement("author");
Element  firstNameElement=authorElement.addElement("firstname");
firstNameElement.setText("tiger");
Element lastNameElement=authorElement.addElement("lastname");
lastNameElement.setText("MM");
可以使用 addDocType() 方法添加文档类型说明。 
document.addDocType("catalog", null,"file://d:/xmldtds/catalog.dtd"); 
这样就向 XML 文档中增加了文档类型说明:
<!DOCTYPE catalog SYSTEM "file://d:/xmldtds/catalog.dtd">
输出文档方式与JDOM很相似。
OutputFormat format = OutputFormat.createPrettyPrint()
XMLWriter output = new XMLWriter(System.out, format);
output.write( document);
output.close();
也可以输出到文件。
XMLWriter output = new XMLWriter(new FileWriter(new File("book.xml")), format);
输出格式类OutputFormat可以使用createPrettyPrint()方法设置缩减格式和createCompactFormat()设置紧凑格式。

2)利用DOM4J修改XML
DOM4J的xPath表达式功能可以非常方便地查找并修改XML文件中元素的内容。首先使用下面的代码创建SAXReader解析对象
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(inputFile);
“inputFile”就是需要读取的XML文件,可以是File对象、String对象或者InputStream对象。使用 XPath 表达式从 article元素中获得 level 节点列表,如果 level 属性值是“Intermediate”则改为“Introductory”。代码片段如下:
List list = document.selectNodes("//article/@level" );
Iterator iter=list.iterator();
while(iter.hasNext()){
 Attribute attribute=(Attribute)iter.next();
 if(attribute.getValue().equals("Intermediate")){
   attribute.setValue("Introductory");
 }

}

提示:表达式“//article/@level”指示找到article元素下的level属性。“//article/author”指示找到article元素下的author子元素。
还可以获取article元素列表,从article元素中的 title 子元素得到一个迭代器,并修改title元素的文本。
List list = document.selectNodes("//article" );
Iterator iter=list.iterator();
while(iter.hasNext()){
   Element element=(Element)iter.next();
   Iterator iterator=element.elementIterator("title");
   while(iterator.hasNext()){
       Element titleElement=(Element)iterator.next();
        if(titleElement.getText().equals("Java configuration with XML ")){
      	titleElement.setText("Create flexible and extensible XML schema");
        }
 }

}

从上述代码可以看到DOM4J使用集合框架完成XML元素的遍历查找,使得开发变得非常方便,性能也显著提高。
展开阅读全文

没有更多推荐了,返回首页