JAXP 全面讲解.docx
- 文档编号:5727049
- 上传时间:2022-12-31
- 格式:DOCX
- 页数:13
- 大小:25.56KB
JAXP 全面讲解.docx
《JAXP 全面讲解.docx》由会员分享,可在线阅读,更多相关《JAXP 全面讲解.docx(13页珍藏版)》请在冰豆网上搜索。
JAXP全面讲解
Java技术和XML无疑是最近五年来最重要的编程开发工具。
因此,用于在Java语言中处理XML的API就发展起来了。
两个最流行的——文档对象模型(DOM)和SimpleAPIforXML(SAX)——已经产生巨大的影响,JDOM和数据绑定API也随之产生了(参阅参考资料)。
彻底理解其中一个或两个API是非常必要的;正确使用全部API会让您成为权威。
但是,越来越多的Java开发人员发现他们不再需要广泛了解SAX和DOM——这主要是由于SunMicrosystems的JAXP工具包。
JavaAPIforXMLProcessing(JAXP)使得XML甚至对于Java初级开发人员也变得易于掌握,并大大提高了高级开发人员的能力。
也就是说,即使使用JAXP的高级开发人员对于他们十分依赖的API也有误解。
本文假设您已基本了解SAX和DOM。
如果您完全不懂XML解析,那么可能需要首先阅读在线参考资料中有关SAX和DOM的信息,或者浏览我的书(参阅参考资料)。
您不需要精通回调或DOMNode,但必须至少了解是SAX和DOM在解析API。
本文还有助于基本了解它们之间的差别。
如果您掌握了这些基本知识,本文将对您更有帮助。
JAXP:
是API还是抽象?
严格说来,JAXP是API,但更准确地说是抽象层。
它没有提供解析XML的新方法,没有添加到SAX或DOM,也没有为Java和XML处理提供新功能。
(如果您还不相信这一点,那么阅读这篇文章算对了。
)但是,JAXP使得使用DOM和SAX来处理一些困难任务变得更容易。
它还允许以开发商中立的方式处理一些在使用DOM和SAXAPI时可能遇到的特定于开发商的任务。
逐渐晋级
在Java平台的早期版本中,JAXP是核心平台中单独的下载。
在Java5.0中,JAXP已经是Java语言的主要产品。
如果已经有最新版本的JDK(参阅参考资料),您就已经获得了JAXP。
没有SAX、DOM或另一个XML解析API,则无法解析XML。
我曾经看到过许多关于将SAX、DOM、JDOM和dom4j与JAXP进行比较的请求,但作这样的比较是不可能的,因为前面四个API与JAXP具有完全不同的用途。
SAX、DOM、JDOM和dom4j都解析XML。
JAXP提供了一种到达这些解析器及其所涉及的数据的方法,但并未提供一种解析XML文档的新方法。
如果您要正确使用JAXP,则理解此差别是非常必要的。
这还很有可能使您远远领先于您的XML开发同行。
如果仍有疑问,请确保您具有JAXP发行版(参阅逐渐晋级)。
启动Web浏览器并加载JAXPAPI文档。
导航至位于javax.xml.parsers软件包中的API的解析部分。
令人奇怪的是,您将只找到六个类。
这个API到底怎么回事?
所有这些类都位于现有解析器的顶部。
其中两个类仅用于错误处理。
JAXP比人们想像的要简单得多。
那么为何会有混淆呢?
位于顶部
甚至JDOM和dom4j(参阅参考资料)与JAXP一样都位于其他解析API的顶部。
但这两个API都提供了从SAX或DOM中访问数据的不同模型,它们在内部使用SAX(带有一些技巧和修改)来到达它们提供给用户的数据。
Sun的JAXP和Sun的解析器
许多解析器/API混淆来自于Sun软件包JAXP和该JAXP默认使用的解析器。
在JAXP的早期版本中,Sun包括JAXPAPI(带有刚才提到的六个类和一些常用于转换的类)和一个叫做Crimson的解析器。
Crimson是com.sun.xml软件包的一部分。
在JAXP的新版本中——包括在JDK中——Sun已经重新包装了ApacheXerces解析器(参阅参考资料)。
在这两种情况下,虽然解析器是JAXP发行版的一部分,但不是JAXPAPI的一部分。
可以认为是JDOM附带了ApacheXerces解析器。
该解析器不是JDOM的一部分,但由JDOM使用,所以包括它是为了确保JDOM可以即装即用。
同一原则适用于JAXP,但并未明确公布:
JAXP附带解析器是为了可以立即使用。
但是,许多人将Sun的解析器中包括的类作为JAXPAPI本身的一部分。
例如,新闻组上的常见问题通常是“我如何使用JAXP附带的XMLDocument类?
它的作用是什么?
”答案有些复杂。
软件包名称中是什么?
当我第一次在Java1.5中贸然打开源代码时,我惊奇于我所看到的——或者更应该说是我没有看到的。
没有在正常中的软件包org.apache.xerces中找到Xerces,因为Sun将Xerces类重新分配给了com.sun.org.apache.xerces.internal。
(我发现这有点不正常,但没有人问我。
)在任何情况下,如果您在JDK中查找Xerces,就能找到它。
首先,com.sun.xml.tree.XMLDocument类不是JAXP的一部分。
它是Sun的Crimson解析器的一部分,包装在JAXP的早期版本中。
所以这个问题从一开始就令人误解。
其次,JAXP的主要用途是在处理解析器时提供开发商独立性。
有了JAXP,您可以用Sun的XML解析器、Apache的XercesXML解析器和Oracle的XML解析器来处理相同的代码。
因而使用特定于Sun的类会违反使用JAXP的要点。
是否弄清楚了本主题是如何变得复杂起来的?
JAXP发行版中的API和解析器已经组合在一起,一些开发人员误将解析器中的类和特性作为API的一部分,反之亦然。
既然弄清楚了所有的混淆,那么您就可以深入了解一些代码和概念了。
回页首
SAX入门
SAX是事件驱动的XML处理方法。
它由许多回调组成。
例如,startElement()回调在每次SAX解析器遇到元素的起始标记时被调用。
characters()回调为字符数据所调用,然后endElement()为元素的结束标记所调用。
许多回调用于文档处理、错误和其他词汇结构。
您明白了。
SAX程序员实现一个SAX接口来定义这些回调。
SAX还提供一个叫做DefaultHandler的类(在org.xml.sax.helpers软件包中)来实现所有这些回调,并提供所有回调方法默认的空实现。
(您将看到,这对于下一节处理DOM中讨论DOM是重点。
)SAX开发人员只需要继承该类,然后实现需要插入特定逻辑的方法。
所以SAX中的关键是提供这些各种回调的代码,然后让解析器在适当的时候触发其中的一个。
下面是典型的SAX例程:
1.使用特定开发商的解析器实现来创建SAXParser实例。
2.注册回调实现(例如,通过使用继承DefaultHandler的类)。
3.开始解析并在回调实现启动时停止。
JAXP的SAX组件提供了完成所有这些操作的简单方法。
没有JAXP,SAX解析器实例要么必须从开发商类(比如org.apache.xerces.parsers.SAXParser)中直接实例化,要么必须使用一个叫做XMLReaderFactory的SAX帮助类(也在org.xml.sax.helpers软件包中)。
第一种方法的问题很显然:
它不是开发商中立的。
第二种方法的问题在于,工厂需要使用解析器类的String名称作为参数(又是Apache类org.apache.xerces.parsers.SAXParser)。
可以通过传递不同的解析器类作为String而更改解析器。
使用该方法,如果更改解析器名称,则不需要更改任何导入语句,但仍需要重新编译类。
这显然不是最好的解决方案。
如果能够不重新编译类而更改解析器就方便多了。
JAXP提供了更好的备选方法:
它允许将解析器作为Java系统特性。
当然,从Sun中下载发行版时,您能得到使用Sun的Xerces版本的JAXP实现。
更改解析器(比如更改为Oracle的解析器)需要更改类路径设置,从一个解析器实现移动到另一个解析器实现。
但不需要重新编译代码。
这就是JAXP的全部魔力——抽象。
诡异的SAX开发人员
稍叉开一下话题。
使用巧妙一点的编码,可以使得SAX应用程序从系统特性或特性文件中选择要使用的解析器类。
但是,JAXP提供了相同的行为,且无需任何工作,所以大多数人更愿意走JAXP路线。
SAX解析器工厂一览
JAXPSAXParserFactory类是能够轻易更改解析器实现的关键。
必须创建该类的新实例(一会将用到它)。
新实例创建之后,工厂提供一种方法用于获得具有SAX功能的解析器。
实际上,JAXP实现保护着开发商相关的代码,从而使您的代码完全不受污染。
工厂还具有一些其他的有用特性。
除了创建SAX解析器实例的基本工作之外,工厂还允许设置配置选项。
这些选项影响通过工厂获得的所有解析器实例。
JAXP1.3中两个常用的选项是,用于设置名称空间意识的setNamespaceAware(booleanawareness)和用于打开DTD验证的setValidating(booleanvalidating)。
记住,一旦设置了这些选项,它们将影响在方法调用后从工厂获得的所有实例。
设置了工厂之后,调用newSAXParser()会返回JAXPSAXParser类立即可用的实例。
该类包装底层的SAX解析器(SAX类org.xml.sax.XMLReader的实例)。
它还防止您使用解析器类的任何特定于开发商的附加项。
(是否记得上文中有关XmlDocument类的讨论?
)该类允许启动实际的解析行为。
清单1显示如何创建、配置和使用SAX工厂:
清单1.使用SAXParserFactory
importjava.io.OutputStreamWriter;
importjava.io.Writer;
//JAXP
importjavax.xml.parsers.FactoryConfigurationError;
importjavax.xml.parsers.ParserConfigurationException;
importjavax.xml.parsers.SAXParserFactory;
importjavax.xml.parsers.SAXParser;
//SAX
importorg.xml.sax.Attributes;
importorg.xml.sax.SAXException;
importorg.xml.sax.helpers.DefaultHandler;
publicclassTestSAXParsing{
publicstaticvoidmain(String[]args){
try{
if(args.length!
=1){
System.err.println("Usage:
javaTestSAXParsing[filename]");
System.exit
(1);
}
//GetSAXParserFactory
SAXParserFactoryfactory=SAXParserFactory.newInstance();
//Turnonvalidation,andturnoffnamespaces
factory.setValidating(true);
factory.setNamespaceAware(false);
SAXParserparser=factory.newSAXParser();
parser.parse(newFile(args[0]),newMyHandler());
}catch(ParserConfigurationExceptione){
System.out.println("Theunderlyingparserdoesnotsupport"+
"therequestedfeatures.");
}catch(FactoryConfigurationErrore){
System.out.println("ErroroccurredobtainingSAXParserFactory.");
}catch(Exceptione){
e.printStackTrace();
}
}
}
classMyHandlerextendsDefaultHandler{
//SAXcallbackimplementationsfromContentHandler,ErrorHandler,etc.
}
在清单1中,可以看到在使用工厂时出现两个特定于JAXP的问题:
无法获得或配置SAX工厂,及无法配置SAX解析器。
第一个问题由FactoryConfigurationError表示,通常发生在无法获得JAXP实现或系统特性中指定的解析器时。
第二个问题由ParserConfigurationException表示,发生在请求的特性在所使用的解析器中不可用时。
两个问题都易于处理,且不应在使用JAXP时造成任何困难。
事实上,您可能想要编写代码,来尝试设置几个特征并巧妙处理某个特性不可用时的情况。
SAXParser实例是在获得工厂、关闭名称空间支持并打开验证时获得的;然后解析开始。
SAX解析器的parse()方法采用前面提到的SAXHandlerBase帮助类的一个实例,自定义处理器类继承自该类。
请参阅代码发行版来查看该类的实现的完整Java清单(参阅下载)。
还传递File以进行解析。
但是,SAXParser类不只包含这一个方法。
使用SAX解析器
一旦具有SAXParser类的实例后,您可以做的远远不止于给它传递File来解析。
由于大型应用程序中组件的通信方式,所以假设对象实例的创建者就是它的用户并不总是安全的。
一个组件可能创建SAXParser实例,而另一个组件(可能由另一个开发人员编码)可能需要使用相同的实例。
因此,JAXP提供了确定解析器的设置的方法。
例如,可以使用isValidating()来确定解析器是否将执行验证,使用isNamespaceAware()来查看解析器是否可以处理XML文档中的名称空间。
这些方法可以为您提供关于解析器可以做什么的信息,但只带有SAXParser实例而非SAXParserFactory本身的用户无法更改这些特性。
您必须在解析器工厂级别完成这一操作。
还有许多方法来请求文档的解析。
并非只能接受File和SAXDefaultHandler实例,SAXParser的parse()方法还可以接受字符串格式的SAXInputSource、JavaInputStream或URL,它们全部具有DefaultHandler实例。
所以仍可以解析包装在各种格式中的文档。
最后,可以获得底层SAX解析器(org.xml.sax.XMLReader的实例),并直接通过SAXParser的getXMLReader()方法来使用它。
一旦获得该底层实例,一般的SAX方法都可用。
清单2显示JAXP中的核心类SAXParser类在SAX解析中的各种用法的例子:
清单2.使用JAXPSAXParser类
//GetaSAXParserinstance
SAXParsersaxParser=saxFactory.newSAXParser();
//Findoutifvalidationissupported
booleanisValidating=saxParser.isValidating();
//Findoutifnamespacesaresupported
booleanisNamespaceAware=saxParser.isNamespaceAware();
//Parse,inavarietyofways
//UseafileandaSAXDefaultHandlerinstance
saxParser.parse(newFile(args[0]),myDefaultHandlerInstance);
//UseaSAXInputSourceandaSAXDefaultHandlerinstance
saxParser.parse(mySaxInputSource,myDefaultHandlerInstance);
//UseanInputStreamandaSAXDefaultHandlerinstance
saxParser.parse(myInputStream,myDefaultHandlerInstance);
//UseaURIandaSAXDefaultHandlerinstance
saxParser.parse("http:
//www.newI
myDefaultHandlerInstance);
//Gettheunderlying(wrapped)SAXparser
org.xml.sax.XMLReaderparser=saxParser.getXMLReader();
//Usetheunderlyingparser
parser.setContentHandler(myContentHandlerInstance);
parser.setErrorHandler(myErrorHandlerInstance);
parser.parse(neworg.xml.sax.InputSource(args[0]));
到此为止,已经针对SAX谈了许多,但还没有显示任何显著的或惊人的内容。
JAXP的附加功能相当小,尤其是涉及到SAX的地方。
这个最小功能使得代码更易移植,让其他开发人员用任何SAX兼容的XML解析器来自由或商业地使用它。
好了。
使用SAX与JAXP再无其他内容。
如果已经了解了SAX,您已经成功了大约98%。
您只需要学习两个新类和一对Java异常,然后就可以开始行动了。
如果从未用过SAX,从现在开始也足够了。
回页首
处理DOM
如果您认为需要休息一下来对付DOM的挑战,那么就休息一下吧。
使用DOM与JAXP和使用JAXP与SAX几乎完全相同,惟一要做的就是更改类名和返回类型,这就足够了。
如果理解SAX如何工作和DOM是什么,那就根本没有问题。
DOM和SAX的主要差别是API本身的结构。
SAX由基于事件的回调集组成,而DOM具有内存树结构。
在SAX中,决不会有需要处理的数据结构(除非开发人员手动创建一个)。
因此,SAX没有提供修改XML文档的能力。
DOM提供了此功能。
org.w3c.dom.Document类表示XML文档,由表示元素、属性和其他XML构造的DOM节点组成。
所以JAXP不需要启动SAX回调;它只负责从解析中返回DOMDocument对象。
DOM解析器工厂一览
基本了解了DOM以及DOM和SAX之间的差别之后,就不需要了解其他内容了。
清单3看起来与清单1中的SAX代码十分相似。
首先,获得DocumentBuilderFactory(与清单1中获得SAXParserFactory的方法一样)。
然后,配置工厂来处理验证和名称空间(与SAX中的方法一样)。
其次,从工厂中检索与SAXParser类似的DocumentBuilder实例(与SAX中的方法一样)。
然后进行解析,得到的DOMDocument对象传递给输出DOM树的方法:
清单3.使用DocumentBuilderFactory
importjava.io.File;
importjava.io.IOException;
importjava.io.OutputStreamWriter;
importjava.io.Writer;
//JAXP
importjavax.xml.parsers.FactoryConfigurationError;
importjavax.xml.parsers.ParserConfigurationException;
importjavax.xml.parsers.DocumentBuilderFactory;
importjavax.xml.parsers.DocumentBuilder;
//DOM
importorg.w3c.dom.Document;
importorg.w3c.dom.DocumentType;
importorg.w3c.dom.NamedNodeMap;
importorg.w3c.dom.Node;
importorg.w3c.dom.NodeList;
publicclassTestDOMParsing{
publicstaticvoidmain(String[]args){
try{
if(args.length!
=1){
System.err.println("Usage:
javaTestDOMParsing"+
"[filename]");
System.exit
(1);
}
//GetDocumentBuilderFactory
DocumentBuilderFactoryfactory=
DocumentBuilderFactory.newInstance();
//Turnonvalidation,andturnoffnamespaces
factory.setValidating(true);
factory.setNamespaceAware(false);
DocumentBuilderbuilder=factory.newDocumentBuilder();
Documentdoc=builder.parse(newFile(args[0]));
//PrintthedocumentfromtheDOMtreeand
//feeditaninitialindentationofnothing
printNode(doc,"");
}catch(ParserConfigurat
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- JAXP 全面讲解 全面 讲解