Java XML教程Java XML教程
第一章入门介绍
关于本教程
在本教程中,我们将讨论如何使用一个XML解析器来:
处理一个XML文档
创建一个XML文档
操作一个XML文档
我们也将讨论一些有用而不为众人所知的XML解析器特性。最重要的,我们所讨论的每个工具都可从IBM的alphaWorks站点(www.alphaworks.ibm)和其它网站免费获得。
未讨论的:
有些重要的编程概念并未在此介绍:
1使用可视工具来构建XML应用
2将一个XML文档从一种形式转换到另一种
3为最终用户或其他进程创建接口,及对后端存储数据的接口
当您构建一个XML应用时,所有这些概念都是重要的。我们正在编制新的教程来讨论它们,因此请常光顾我们的网址!
XML应用架构
一个XML应用通常是基于一个XML解析器而构建的。它为其用户提供了一个接口,以及对后端存储数据的一个接口。
本教程关注于编写使用XML解析器来操作XML文档的Java代码。如下边图片所示,本教程关注于中间那块。
第二章解析器基础
基础
一个XML解析器是一段可以读入一个文档并分析其结构的代码。在本章节,我们将讨论如何使用一个XML解析器来读入一个XML文档。我们也将讨论不同类型的解析器以及您在何时使用它们。
本教程后面的章节将讨论您从解析器可以获得什么以及如何使用这些结果。
如何使用一个解析器
我们将在稍后的章节详细讨论它,但通常而言,您如下使用它:
1创建一个解析器对象
2将您的XML文档传递给解析器
3处理结果
构建一个XML应用显然远远超出这些,但通常一个XML的应用将包含这些流程。
解析器种类
有不同的方法来划分解析器种类:
验证或非验证解析器
支持DocumentObjectModel(DOM)的解析器
支持SimpleAPIforXML(SAX)的解析器
用特定语言编写的解析器(Java,C++,Perl等)
验证或非验证解析器
如我们在第一个教程中所提及的,XML文档如果使用一个DTD并符合DTD中的规则将被称为有效文档(validdocument)。符合基本标记规则的XML文档被称为格式正确文档(well-formeddocument)。
XML规范要求所有的解析器当其发现一个文档不是格式正确时要报错。验证(Validation)则是另一个问题了。验证解析器(Validatingparser)在解析XML文档同时进行验证。非验证解析器(Non-validatingparser)忽略所有的验证错误。换而言之,如果一个XML文档是格式正确的时,一个非验证解析器并不关注文档是否符合其对应DTD所指定的规则(如果有的话)。
为何使用非验证解析器?
速度和效率。要一个XML解析器处理DTD并确保每个XML的元素符合在DTD中的规则需要相当大的开销。如果您
确定一个XML文档是有效的(可能来自一个数据源),那就没有必要在次验证它了。
同样,有时您所需要的只是从一个文档中出XML的标记。一旦您有了这些标记,您可以将数据从中提取出然后加以处理。如果这就是您所需要的,一个非验证解析器就是正确的选择。
DocumentObjectModel(DOM)
文档对象模型(DocumentObjectModel)是WorldWideWebConsortium(W3C)的正式推荐。它定义了一个接口使得程序可以存取和更新XML文档的风格、结构和内容。支持DOM的XML解析器实现该接口。
该规范的第一版,DOMLevel1,可从/TR/REC-DOM-Level-1获得,如果您愿意阅读规范的话。
DOM解析器可提供什么
当您用一个DOM解析器来解析一个XML文档时,您将获得一个包含文档中所有元素的树结构。DOM提供了不同的功能来检查文档的内容和结构。
关于标准
现在我们即将讨论开发XML应用了,我们也要关注XML的标准。正式而言,XML是MIT(麻省理工)的商标和WorldWideWebConsortium(W3C)组织的产品。
XML规范,W3C的正式推荐,可从/TR/REC-xml下载。W3C站点包含了XML、DOM以及一大堆XML相关标准的规范。
SimpleAPIforXML(SAX)
SAXAPI是另一种处理XML文档内容的方法。一个既成事实的标准,它由DavidMegginson和XML-Dev邮件列表其它成员所开发。
要查看完整的SAX标准,参见inson/SAX/。要参加XML-Dev邮件列表,发送邮件到majordomo@ic.ac.uk其中包含:subscribexml-dev。
SAX解析器可提供什么
当您使用SAX解析器来解析XML文档时,解析器在文档的不同处将产生事件。由您来决定对每个事件如何处理。
SAX解析器会在以下情况下产生事件:在文档开始和结束时,在一个元素开始和结束时,或者它在一个元素中到字符时,以及其它若干点。您可编写Java代码来处理每个事件,以及如何处理从解析器获得的信息。
何时使用SAX?何时使用DOM?
我们将在稍后的章节详细讨论这个问题,但通常而言,您在下列时候应该使用一个DOM解析器:
您需要十分了解文档的结构
您需要操作文档中的某些部分(例如,您可能想对某些元素排序)
您需要不止一次使用文档中的信息
当您只需要从一个XML文档中提取若干元素时,可使用SAX解析器。SAX解析器在您没有大多数内存时、或者如果您只需要使用文档中的信息一次(而不是解析文档一次,而后要反复使用它)。
不同语言的XML解析器
在Web上使用的大多数语言都有其对应的XML解析器和库,包括Java、C++、Perl和Python。下一页介绍了IBM或其它公司提供的解析器的链接。
本教程中绝大多数的示例是使用IBM的XML4J解析器。我们所讨论的所有代码使用标
准的接口。在本教程的最后章节,我们将向您展现编写可使用不同解析器的代码是如何简单。
Java
IBM的解析器,XML4J,可从www.alphaWorks.ibm/tech/xml4j获得。
JamesClark的解析器,XP,可从www.jclark/xml/xp获得。
Sun的XML解析器可从developer.java.sun/developer/products/xml/(您必需成为JavaDeveloperConnection的会员)下载。
DataChannel的XJParser可从xdev.datachannel/downloads/xjparser/获得。
C++
IBM的XML4C解析器可从www.alphaWorks.ibm/tech/xml4c获得。
JamesClark的C++解析器,expat,可从www.jclark/xml/expat.html获得。
Perl
有多种Perl语言的XML解析器。要获得更多信息,参见www.perlxml/faq/perl-xml-faq.html。
Python
要获得更多Python语言的XML解析器,参见/topics/xml/。
总结
任何XML应用的核心是一个XML解析器。要处理一个XML文档,您的应用将创建一个parser对象,将一个XMLdocument传递给它,然后处理从parser对象返回的结果。
我们讨论了不同类型的XML解析器,以及您为何选取其一。我们用不同方式来对解析器分类:
验证或非验证解析器
支持DocumentObjectModel(DOM)的解析器
支持SimpleAPIforXML(SAX)的解析器
用特定语言编写的解析器(Java,C++,Perl等)
在我们的下一章节,我们将探讨DOM解析器和如何使用它们。
第三章DOM(DocumentObjectModel)
Dom,dom,dom,dom,dom,
Doobie,doobie,
Dom,dom,dom,
DOM是一个操作文档结构的通用接口。它设计的一个目标是为一个DOM兼容解析器所编写的Java代码应该可以使用其它任意DOM兼容的解析器而不需要修改代码。(我们稍后将展示这个。)
正如我们前面所提的,一个DOM解析器将以树形式返回您整个文档的结构。
示例代码
在我们继续以前,请您下载我们的示例XML应用程序。解开此文件xmljava.zip,就可以了!(blueski:***或者查看本教程附录)
DOM接口
DOM定义了多个Java接口。下列是常用的:
Node:DOM基本的数据类型。
Element:您将最主要处理的对象是Element。
Attr:代表一个元素的属性。
Text:一个Element或Attr的实际内容。
Document:代表整个XML文档。一个Document对象通常也被称为一棵DOM树。
常用的DOM方法
当您使用DOM时,下列是您将常会使用的方法:
返回文档的根(root)元素。
返回给定Node的第一个子女。
它将删除DOM树中一切内容,格式化您的硬盘,然后给您地址簿中每个人发送一个谩骂的邮件。(不是真的啦。这些方法返回下一个或前一个给定Node的同胞。)
对给定的Node,返回给定
名称的属性。例如,如果您要获得名为id属性的对象,可调用getAttribute("id")。
我们的第一个DOM应用!
介绍了很多概念,让我们继续吧。我们的第一个应用简单地读入一个XML文档并将其内容输出到标准输出。
在一个命令行窗口,运行下面的命令:
这个命令将载入我们的应用然后让它解析l文件。如果一切运行正常,您将看到XML文档的内容被输出到标准输出。
<?xml version="1.0"?>
<sonnet type="Shakespearean">
<author>
<last-name>Shakespeare</last-name>
<first-name>William</first-name>
<nationality>British</nationality>
<year-of-birth>1564</year-of-birth>
<year-of-death>1616</year-of-death>
</author>
<title>Sonnet130</title>
<lines>
<line>
domOne剖析
domOne的源码是非常直了的。我们创建一个新的类domOne;它有两个方法,parseAndPrint以及printDOMTree。
在main方法中,我们处理命令行,创建一个domOne对象,然后将文件名传递给domOne对象。domOne对象创建一个parser对象,解析文档,然后通过printDOMTree方法处理DOM树(即Document对象)。
我们将详细研究每个步骤。
publicclassdomOne
{
publicvoidparseAndPrint(Stringuri)
...
publicvoidprintDOMTree(Nodenode)
...
publicstaticvoidmain(Stringargv[])
...
处理命令行
处理命令行的代码在左面显示。我们将检查用户是否在命令行上输入参数。如果没有,我们打印使用方法并推出;否则,我们假定命令行上第一个参数(Java语言中的argv[0])是文档名。我们忽略用户可能输入的其它参数。
我们使用命令行参数来简化我们的示例。在大多数情况下,一个XML应用可能使用servlet、JavaBean和其它类型的组件一起使用;而用命令行参数并不是一个问题。
publicstaticvoidmain(Stringargv[])
{
if(argv.length==0)
{
System.out.println("Usage:...");
...
}
domOned1=newdomOne();
d1.parseAndPrint(argv[0]);
}
创建一个domOne对象
在我们的示例代码中,我们创建一个单独的类domOne。要解析文件和打印结果,我们创建一个domOne类的实例,然后让我们刚创建的domOne对象来解析和打印XML文档。
我们为何这样处理?由于我们想要使用一个递归方法来遍历DOM树并打印出结果。我们无法用一个如main的静态方法来处理,因此我们创建一个单独的类来处理它。
publicstaticvoidmain(Stringargv[])
{
if(argv.length==0)
{
python转java代码System.out.println("Usage:...");
...
}
domOned1=newdomOne();
d1.parseAndPrint(argv[0]);
}
创建一个Parser对象
现在我们已经让domOne的实例来解析和处理我们的XML文
档,它的第一个处理是创建一个新的Parser对象。在此例中,我们将使用一个DOMParser对象,一个实现DOM接口的Java类。在XML4J包中还有其它parser对象,例如SAXParser、ValidatingSAXParser和NonValidatingDOMParser。
注意我们将这段代码放在一个try模块中。parser在某些情况下将抛出异常(exception),包括一个无效的URI、不到一个DTD或者一个XML文档不是有效的或格式错误。要很好地处理它,我们要捕获异常(exception)。
try
{
DOMParserparser=newDOMParser();
parser.parse(uri);
Document();
}
解析XML文档
解析文档只是简单的一行代码。当解析结束时,我们获得解析器生成的Document对象。
如果Document对象不是null(如果解析过程出错它将是null),我们将其传递给printDOMTree方法。
try
{
DOMParserparser=newDOMParser();
parser.parse(uri);
Document();
...
if(doc!=null)
printDOMTree(doc);
}
处理DOM树
现在解析已经完成,我们将遍历DOM树。注意这段代码是递归的。对每个节点,我们处理其本身,然后我们对每个节点的子女递归地调用printDOMTree方法。递归调用如左所示。
要记住当有些XML文档非常大时,它们反而不会有太多层标记。以一个上海市的电话簿为例,可能有几百万条记录,但其标记可能不会超过几层。考虑到这个原因,递归算法的栈溢出不是一个问题。
publicvoidprintDOMTree(Nodenode)
{
NodeType();
switch(nodeType)
{
caseDOCUMENT_NODE:
printDOMTree(((Document)node).
GetDocumentElement());
...
caseELEMENT_NODE:
...
NodeListchildren=
if(children!=null)
{
for(inti=0;
i< Length();
i++)
printDOMTree(children.item(i));
}
很多 Node
如果您查看 l,有二十四个节点。您可能认为这意味着二十四个节点。然而,这不正确。在 l 中一共有 69 个节点;一个文档节点(document node), 23 个元素节点(element node)以及 45 个文本节点(text node)。我们运行 java l 就获得了下边所示的结果。
domCounter.java
这段代码解析一个 XML 文档,然后遍历 DOM 树来采集有关该文档的数据。当数据采集后将其输出到标准输出。
统计 l 的数据:
====================================
Document Nodes: 1
Element Nodes: 23
Entity Reference Nodes: 0
CDATA Sections: 0
Text Nodes: 45
Processing Instructions: 0
----------
Total: 69 Nodes
节点列表示例
对于下边的片断,
<sonnet type="Shakespearean">
<author>
<last-name>Shakespeare</last-name>
下列是从解析器返回的节点:
Document节点
Element节点对应于<sonnet>;标记
一个Text节点对应于<sonnet>;节点后的
回车符以及<author>;标记前的两个空格符
Element节点对应于<author>;标记
一个Text节点对应于<author>;节点后的回车符以及<last-name>;标记前的四个空格符
Element节点对应于<last-name>;标记
所有那些文本节点
如果您查看由解析器返回的所有节点列表,您将发现它们大多数是没用的。在每行开始的空格符组成其中包含可忽略的Text节点。
注意如果您将所有的节点放在一行上我们就不会得到这些无用的节点了。我们通过添加分行符和空格符来提高文档的可读性。
当您构建一个XML文档时不需要考虑可读性,就可省略分行符和空格符。这可使得您的文档更小,处理您的文档时也不需要构建那些无用的节点。
所有那些文本节点
如果您查看由解析器返回的所有节点列表,您将发现它们大多数是没用的。在每行开始的空格符组成其中包含可忽略的Text节点。
注意如果您将所有的节点放在一行上我们就不会得到这些无用的节点了。我们通过添加分行符和空格符来提高文档的可读性。
当您构建一个XML文档时不需要考虑可读性,就可省略分行符和空格符。这可使得您的文档更小,处理您的文档时也不需要构建那些无用的节点。
<sonnet type="Shakespearean">
<author>
<last-name>Shakespeare</last-name>
<first-name>William</first-name>
<nationality>British</nationality>
<year-of-birth>1564</year-of-birth>
<year-of-death>1616</year-of-death>
</author>
<title>Sonnet130</title>
<lines>
<line>Mymistress'eyesarenothinglikethesun,</line>
一个Text节点对应于"Shakespeare"字符
如果您看到标记间所有的空格符,您可发现为何我们有那么多超出您想像的节点。
了解您的Node
我们最后对处理在DOM树的Node要指出的是,我们在处理其之前要检查每个Node的类型。一些方法,例如getAttributes,对一些特定的节点类型返回null值。如果您不检查节点类型,您将得到不正确的结果(最佳情况)和异常(最差情况)。
在此所介绍的switch语句常出现在使用DOM解析器的代码。
switch(nodeType)
{
caseNode.DOCUMENT_NODE:
...
caseNode.ELEMENT_NODE:
...
caseNode.TEXT_NODE:
...
}
总结
不管您信不信,这就是我们使用DOM对象所要了解的所有内容。我们的domOne代码完成了下列工作:
创建一个Parser对象
将一个XML文档传递给Parser来解析
获得来自于Parser的Document对象然后加以检查。
在本教程最后一章,我们将讨论如何不需要XML原文件来构建一棵DOM树,并展示如何对一个XML文档中的元素排序。而那些都是基于我们这里所讨论的概念之

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。