Java XML解析技术

本文链接: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处理器生成树,然后将其传递给应用程序。

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");
        }
 }
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
开源项目TinyXml项目所涉及的字符编码说明如下: 1. TinyXml函数调用接口的字符型参数,仅支持`窄字符`格式(char*),不兼容`宽字符`格式(wchar_t*)。 2. TinyXml函数提供的Xml内容解析功能,仅支持以ANSI编码和UTF8编码的Xml字符串,也即`多字节编码`。 3. TinyXml函数提供的Xml内容解析功能,不支持内容以UTF16编码和UTF32编码的Xml字符串,也即`Unicode编码`。 4. UTF8编码是Unicode编码的一种实现方式,以不定个数的字节来存储一个Unicode码值,支持多国语言文字。 也即,UTF8编码在编码实现上属于`多字节编码`,在编码标准上属于`Unicode编码`。 5. 人类语言中同一个的字符,如果在各种不同的标准如ANSI编码、UTF8编码、UTF16编码和UTF32编码中都存在码值, 就可以相互转换。因为各个标准下的可编码字符容量不同,部分语言字符会在一个编码标准库下存在, 而在另外一个编码标准库下不存在,这时精确的相互转换就无法执行,但是仍然有默认字符转换。 -- 6. VC语言,当定义了宏 _UNICODE 后,_T系列宏或函数,以`宽字符`承载UTF16编码。 TinyXml如何提供`宽字符`函数接口,支持解析UTF16编码、UTF32编码标准下的Xml字符串呢? 本项目: - 新增适用于`宽字符`参数的函数接口,调用字符集转换功能,转换为`窄字符`参数,再回调TinyXml原版接口。 - 对于以UTF16编码、或UTF32编码的Xml字符串,转换为UTF8编 --
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值