??xml version="1.0" encoding="utf-8" standalone="yes"?>
Identify the aspects of your application that vary and separate them from what stays the same.
Here's another way to think about this principle: take the parts that vary and encapsulate them, so that later you can alter or extends the parts that vary without affecting those that don't.
As simple as this concept is, it forms the basis for almost every design pattern. All patterns provide a way to let some part of a system vary independently of all other parts.
Each set of class will hold all the implementations of their respective behavior. For instance, we might have one clss that implements quarking, another implements squaking, and another that implements silence.
To separate thest behaviors from the Duck class, we'll pull both methods out of the duck class and create a new set of class to represent each behavior.
This is in contrast to the way we were doing things before, where a behavior either came from a concrete implementation in the suprerclass Duck, or by providing a specialized implementation in the sub class itself. In both cases we were relying on an implementation. We were locked into using that specific implemetation and there was no room for changing out the behavior.
And the same is true for the duck's flying behavior.
Okay, now that we've done the deep dive on the duck simulator design, it's time to come back up for air and take a look at the big picture.
Below is the entire reworked class structure. We have everything you'd expect: ducks extending Duck. fly behavior implementing FlyBehavior and quack behavior implementing QuackBehavior.
Notice also that we've started to describe things a little differntly. Instead of thinking of the duck behaviors as a set of behaviors, we'll start thinking of them ad a family of algorithms. Think about it: in the SimUDuck design, the algorithms represent things a duck would do , but we could just as easily use the same techniques for a set of classes that implement the ways to compute state sales tax by different states.
Q一Q前aQ?br />
JFreeChart是开放源代码站点SourceForge.net上的一个JAVA目。它的功能十分强大,能创建饼图、柱状图(普通柱状图以及堆栈q?、线图、区域图、分布图、合图、甘特图以及一些A表盘{等Qƈ可生成PNG或JPG囄格式文g?br /> 本h在学习过E中发现Q网上很多文章都是讲一些JFreeChart的基本应用,而对JFreeChart生成热点图表q样常用的功能虽有所提及却没有一个完整的例子Q所以我写一个简单示例供大家参考,希望对大家的学习有所帮助。?br /> Q二Q示例说明: 假设有一个关于程序员北京Q上Pq洲三地E序员学历,开发语aQ薪金情늚调查。首先要以饼图显C程序员学历的分布情?index.jsp)。点击饼囄每一部分会以q图显C层次E序员所用开发语a和薪金的情况(barview.jsp)。重ҎC怎样在饼图上d链接。?br /> Q三Q准备工作: 1.下蝲最新版本的JFreeChart,当前为jfreechart-1.0.0-rc1 下蝲地址Qhttp://www.jfree.org/jfreechart/index.html 2.解压文gQ将jfreechart-1.0.0-rc1/lib下的jcommon-1.0.0-rc1.jarQjfreechart-1.0.0-rc1.jar复制到WEB应用的lib目录下?br /> 3.在web.xml文g中增加以下内容:
Q四Q饼N面代码(index.jspQ?br />
生成的图片如?br />
在浏览器中点右键Q>查看源文件会发现有以下一DHTML代码Q?br />
q就是MAP信息Q我们在IMG标签中加入usemap="#map0"可以ؓ饼图的每一部分加入链接?br /> Q五Q柱状图面代码Q?barview.jsp)
生成囄如下Q?br />
|
escape() & encodeURI() & encodeURIComponent()q三个函数都可以用来对URIq行encode或过滤特D字W(#/$&+=?/{)。我的经验是最好用encodeURIComponent()Q需要IE 5.5以上QFireFox当然没问题)Q因为对UTF-8支持比较好,不会遇到中文q问题Q否则还需要进行编码{换,很麻烦的。用其它两个函数都会发生丢qD字W的问题,例如I格?h者空?引号,&=?{丢q问题, 臛_使用 JSP 作ؓ服务器端的话会发生这U情? 有兴的朋友可以本文最后的例子代码中的~码部分修改后做个测?
下面是MSDN上对q三个函数的解释Q?/p>
escape(charString)
The escape method returns a string value (in Unicode format) that contains the contents of charstring. All spaces, punctuation, accented characters, and any other non-ASCII characters are replaced with %xx encoding, where xx is equivalent to the hexadecimal number representing the character. For example, a space is returned as "%20."
Characters with a value greater than 255 are stored using the %uxxxx format.
Note The escape method should not be used to encode Uniform Resource Identifiers (URI). Use encodeURI and encodeURIComponent methods instead.
http://msdn.microsoft.com/library/en-us/script56/html/js56jsmthescape.asp
encodeURI(URIString)
The encodeURI method returns an encoded URI. If you pass the result to decodeURI, the original string is returned. The encodeURI method does not encode the following characters: ":", "/", ";", and "?". Use encodeURIComponent to encode these characters.
http://msdn.microsoft.com/library/en-us/script56/html/js56jsmthfencodeuri.asp
encodeURIComponent(encodedURIString)
3. 使用一个简便的客户端数据解析方?br />The encodeURIComponent method returns an encoded URI. If you pass the result to decodeURIComponent, the original string is returned. Because the encodeURIComponent method encodes all characters, be careful if the string represents a path such as /folder1/folder2/default.html. The slash characters will be encoded and will not be valid if sent as a request to a web server. Use the encodeURI method if the string contains more than a single URI component.
http://msdn.microsoft.com/library/en-us/script56/html/js56jsmthencodeuricomponent.asp
源码解压羃到JSP服务器的L目录下即? 例如 $TOMCAT_HOME\webapps\ROOT ? 然后在浏览器里键?
http://localhost:8080/ajax_form_submit.htm
作? beansoft@126.com 2006.12.25
需要注意的地方是form的action属性的写法了;
2、在xwork.xml中增加相应的处理action的节?/font>
q里需要注意的是action节点中name的D与index.jsp中定义的action的名字要严格匚wQ对于大?/font> 写是敏感的。在action节点中还包含?result>节点Q以说明处理action之后会可能出现的不同l果(name)和相应的处理方式(type)。譬如说Q如果Login的这个action处理success了,则用dispatcher结果分(dispatch)到相应的面。而在WAF框架中ƈ没有q样的定义,因ؓ在默认情况下如果不成功则会返回当前页面,不过可以定义FlowHandlerQƈ拥有cM的功能且更加灉|Q?br /> 3、实现类Login的代码:
在代码中Q你会发现有两个l承变量ERROR与SUCCESS。这两个变量是定义在Actionq个接口的,而ActionSupport则实CAction接口。在接口Action的代码中Q我们可以看到ERROR = "error"、SUCCESS = "success"。我们可以发现这两个变量的gxwork.xml中result子节点中的name的值是相匹配。除此之外,在代码中Q我也找不到了原来在开发中l常要用到的一个APIQgetParameter。事实上Q将表单中数据析取出来的工作是由webworkq个唯一定义的servletd成的Q而这个类会调用LogincMset的方法将用户输入的数据赋lLogincȝ属性:loginId和loginPassword。在q里Q我们也要跟前面index.jsp中的包含的标{联pv来。当数据被dispatch回index.jsp的时候,在index.jsp面render的过E中是调用了get的方法去获取相应的数据的?br /> 最后,我们可以ȝ一下,整个Web应用E序的处理流E了Q?br /> 首先Q当用户提交了表?form)至Login.action后,由web.xml中定义的唯一的一个servletQwebworkd理这个请求。webwork会以action的nameQLogin到xwork.xml中寻扄应的处理action的类Q于是就扑ֈ了fantasysoft.webwork包中的Loginc,由LogincM的executeҎ来处理提交的form的数据了Q?br /> 然后Q根据executeҎ的返回|再到xwork.xml中对应的action节点中去扑配的result子节点;
最后,Ҏresult子节点的定义Q将处理l果分发(dispatch)或者重定向(redirect)至下一个页?sup>[3]?/font>
[1] 准备工作可以参?
WebWork Getting Started
Q?br /> [2] web.xml文g的具体内容,可以参?
WebWork Tutorial Lesson 2
Q?br /> [3] 对于result的Type的更多介l,可以参?
WebWork Tutorial Lesson 3
重蝲overloading和覆写overriding哪个更早执行-- visitor帮助?
一Q问题提?br />虽然我们l常写程序用到重载和覆写Q但是很会考虑他们的执行顺序。下边的内容是关于Q他们同时出现时
哪个先v作用Q?br />二:问题分析
Java?动态单分派静态多分派语言"Q这个定义已l多ơ提P如果你不了解q些概念Q看q里"visitor模式准备"
所以就注定了重?静态多分派)要早于覆?动态单分派)Q因为静态分z是~绎期实现的Q动态分z是执行期实现的?br />三:验证
单验证一下,变提高记忆
q行l果是什么?
in Child +param:Object
inChild是确认的Q但是ؓ什么是objectQ而不是StringQ我们放入的是String啊?br />首先来分析执行过E?br />定义韦类型Parent p在执行run(Str)的时候,
1Q如果是先执行重载,然後是执行覆写的q程
重蝲时因为找不到对应的String参数的函敎ͼ所以定位到接受父类的run(Object o)函数Q?br />覆写时因Z入时父类告诉子类的对象类型是ObjectQ所以执行run(Object o);
正是我们看到的结果,所以在Java中执行的序是这L?/p>
2Qؓ了对比,说一下先覆写后重载的q程
如果是先覆写Q再重蝲
覆写时因为确定对象实际是子类Q所以直接覆写到ChildQ然後重载,发现有对应的String为参数的函数
执行Qrun(String str);
应该输出的结?in Child +param:String
但我们看到结果显然是1Q所以验证了Java是先重蝲后覆写的?/p>
最后的部分Q?/p>
看完本文Q如果你对visitor模式有更多的兴趣Q想了解更多L如下几篇文章?br />1,静态分z,动态分z,多分z,单分z?-------------- visitor模式准备
2,讉K差异cd的集合类 ------------------------ visitor模式入门
3,visitor模式理论及学术概?------------Q?---- visitor模式深入
4,visitor模式和其它模式的比较和关p?------------ visitor模式ȝ
5Q重载overloading和覆写overriding哪个更早执行-- visitor帮助?Q本文)
虽然排列序?,2,3,4,5 但是我个人徏议的学习方式?,1,3,4,5因ؓq个序更方便一般h理解
Sun ?Java API for XML 语法分析
![]() |
|
U别: 初
Brett McLaughlin
, Enhydra {略N, Lutris Technologies
2000 q?11 ?01 ?/p>
q是细?JAXPQSun ?Java API for XML 的文章,帮助解除了有?JAXP 本质和服务目的的疑惑。本文讲解了 JAXP 的基本概念,演示 XML 语法分析Z么需?JAXPQƈ昄如何L更改 JAXP 使用的语法分析器。本文还q一步讲qC SAX ?DOM q两个流行的?JAXP 相关?Java ?XML API?/blockquote>Java ?XML 在每一个技术领域都刉了新闻Qƈ且对于Y件开发h员来_g?1999 q和 2000 q最重要的发展。结果,Java ?XML API 的数量激增。其中两个最行?DOM ?SAX q引h大兴,?JDOM 和数据绑?API 也接t而来。只透彻理解q些技术中的一个或两个是一艰巨Q务,而正用所有这些技术就会您成Z家。但在去q_另一?API lh留下了深d象,它就?Sun ?Java API for XMLQ通常UCؓ JAXP。如果考虑?Sun 在其q_上还没有M特定?XML 的品,那么q个q展׃ؓ奇。而o人惊奇的是h们对 JAXP 了解的缺乏。多C用它的开发h员在他们所用的q个 API 的概느解上都有错误?/p>
本文假设您有 SAX ?DOM 的基本知识。这里实在没有够篇q来解释 SAX、DOM ?JAXP。如果您?XML 语法分析的新手,那么可能要通过联机资源阅读 SAX ?DOMQ或者浏览我的书。( 参考资?/font> 一节中有至 API 和我的书的链接。)获得基本知识后再看本文会比较好?
![]()
![]()
![]()
![]()
回页?/font>
在讲解代码之前,介绍一些基本概念很重要。严格地_JAXP ?APIQ但是将其称为抽象层更准。它不提供处?XML 的新方式Q不补充 SAX ?DOMQ也不向 Java ?XML 处理提供新功能。(如果在这点上理解有误Q则本文正好适合您!Q它只是佉K过 DOM ?SAX 处理一些困难Q务更Ҏ。如果在使用 DOM ?SAX API 旉到特定于供应商的dQ它q通过独立于供应商的方式处理这些Q务成为可能?/p>
虽然要分别讲q所有这些特性,但是真正需要掌握的是:JAXP 不提供语法分析功?/i> Q没?SAX、DOM 或另一?XML 语法分析 APIQ就 无法分析 XML 语法 。有很多人曾让我?DOM、SAX ?JDOM ?JAXP q行Ҏ。但q行q些Ҏ是不可能的,因ؓ前三?API ?JAXP 的目的完全不同。SAX、DOM ?JDOM 都分?XML 语法。?JAXP 却提供到达这些语法分析器和结果的方式。它自n不提供分析文档语法的新方法。如果要正确使用 JAXPQ则一定要弄清q点。这您比其它 XML 开发h员领先一大截?
如果仍然怀疑(或认为我故弄玄虚Q,请从 Sun ?Web 站点下蝲 JAXP 分发Q请参阅 参考资?/font> 一节)Q然后就会知道基?JAXP 是什么。在包括?jar (
jaxp.jar
) ?只有六个c?/i> Q这?API 会有多难哪?所有这些类Q?javax.xml.parsers
包的一部分Q都位于现有语法分析器之上。这些类中的两个q用于错误处理。JAXP 比h们想象的要简单得多。那么,Z么还感到困惑哪?
![]()
![]()
![]()
![]()
回页?/font>
JAXP 下蝲时包?Sun 的语法分析器。所?parser 器类作ؓ
com.sun.xml.parser
包和相关子包的一部分位于parser.jar
档案中。应该知道,该语法分析器Q代码名?CrimsonQ??/i> ?JAXP 自n的一部分。它?JAXP 版本的一部分Q但不是 JAXP API 的一部分。o人困惑吗Q有一炏V换q种方式xQJDOM ?Apache Xerces 语法分析器一h供。该语法分析器不?JDOM 的一部分Q但?JDOM 使用Q所以包括它Q以保 JDOM 可以单独使用。JAXP 也是如此Q但不象 JDOM 那样好表达:JAXP ?Sun 的语法分析器一h供,以便可以立即使用。但是,很多人将 Sun 的语法分析器中包括的cd?JAXP API 的一部分。例如,新闻l中一个常见的问题是:“怎样使用 JAXP 中的XMLDocument
c?其目的是什么?”这个答案可有些复杂?首先Q?
com.sun.xml.tree.XMLDocument
cM?JAXP 的一部分。它?Sun 语法分析器的一部分。所以,q个问题从一开始就lh以误对{其ơ,JAXP 的整个意义在于在处理语法分析器时提供供应商独立性。?JAXP 的同一代码可以?Sun ?XML 语法分析器、Apache ?Xerces XML 语法分析器和 Oracle ?XML 语法分析器一起用。而用特定于 Sun 的类是个坏主意。这?JAXP 的整个意义相背离。现在看出来q个问题怎样h概念了吗Q语法分析器?JAXP 发行版本Q至是 Sun 的版本)中的 API 被Z谈,开发h员将其中一个的cdҎ当成是另一个的了,反之亦然?
![]()
![]()
![]()
![]()
回页?/font>
关于 JAXPQ最后需要指出的是:使用 JAXP 有一些缺陗例如,JAXP 只支?SAX 1.0 ?DOM W一层规范。SAX 2.0 ?2000 q?5 月v完成,DOM W二层规范支持甚臛_大多数语法分析器中存在更长时间。DOM W二层规范还没有完成Q但实_E_以用于生产。这两个 API 的新版本都有重大改进Q最明显的是?XML 名称I间的支持。该支持q允许“XML Schema 认”,q个?XML 相关的另一热门技术。公q__?JAXP 发布 1.0 最l发行版ӞSAX 2.0 ?DOM W一层规范都q没有完成。但是,׃没有包括q些新版本,实为开发h员带来很大不ѝ?/p>
q可以?JAXPQ但是也可以{待 JAXP 1.1Q它支持 SAX 2.0 ?DOMW二层规?。否则,发玎ͼJAXP 提供的优点以 SAX ?DOM 最新版本中的功能ؓ代hQƈ使应用程序更加难以编码。无论是否等待下一?JAXP 发行版,都要留意q个问题。如果将 JAXP 与语法分析器一起用,而语法分析器支持?DOM ?SAX 版本?JAXP 支持的要高,则可能会有类路径问题。所以,事先留意一下,q且Q一旦有 JAXP 1.1Q马上升U。基本理?JAXP 之后Q让我们看一?JAXP 依赖?APIQSAX ?DOM?/p>
![]()
![]()
![]()
![]()
回页?/font>
SAX QSimple API for XMLQ是用于处理 XML 的事仉动方法。它基本p多回调函数组成。例如,每当 SAX 语法分析器遇到元素的开始标记时p?
startElement()
。对于字W串Q将调用characters()
回调函数Q然后在元素l束标记处调?endElement()
。还有很多回调函数用于文档处理、错误和其它词汇l构。现在知道这是怎么回事了。SAX E序员实C个定义这些回调函数的 SAX 接口。SAX q实C个名?HandlerBase
的类Q该cd现所有这些回调函敎ͼq提供所有这些回调方法的~省I实现。(提到q一Ҏ因ؓ它在后面讲到?DOM 中很重要。)SAX 开发h员只需扩展q个c,然后实现需要插入特定逻辑的方法。所以,SAX 的关键在于ؓq些不同的回调函数提供代码,然后允许语法分析器在适当的时候触发这些回调函C的每一个?因此Q典型的 SAX q程如下Q?/p>
- 用特定供应商的语法分析器实现创徏一?
SAXParser
实例- 注册回调实现Q例如,通过使用扩展
HandlerBase
的类Q?- 开始进行语法分析,然后在触发回调实现时{待
JAXP ?SAX lg提供执行所有这些步骤的单方式。如果没?JAXPQSAX 语法分析器要直接从供应商c(?
org.apache.xerces.parsers.SAXParser
Q进行实例化Q或者必M用名?ParserFactory
的帮助类。第一个方法的问题很明显:不独立于供应商。第二个Ҏ的问题在于类厂需要一个自变量Q即要用的语法分析器类的字W串名称Q还是那?Apache c?org.apache.xerces.parsers.SAXParser
Q。可以通过不同语法分析器作ؓString
传递来更改语法分析器。用这U方法不必更改Q?import 语句Q但是还是要重新~译cR这昄不是最佌x案。如果能够不重新~译c而更改语法分析器Q可能会单得多,是不是这样呢Q?JAXP 提供了更好的替代ҎQ它允许语法分析器作ؓ Java pȝ属性来提供。当Ӟ当从 Sun 下蝲版本Ӟ得C?Sun 语法分析器的 JAXP 实现。可以从 Apache XML Web 站点下蝲?Apache Xerces 上构建其实现的相?JAXP 接口。因此(无论哪一U情况)Q更Ҏ在用的语法分析器需要更改类路径讄Q即从一U语法分析器实现更改到另一个,但是 ?/i>要求重新~译代码。这是 JAXP 的魔力,或抽象性?
JAXP
SAXParserFactory
cL能够L更改语法分析器实现的关键所在。必d个类的新实例Q等一会将讲到Q。创建新实例之后Q类厂提供一个方法来获得支持 SAX 的语法分析器。在内部QJAXP 实现处理依赖于供应商的代码,使您的代码不受媄响。这个类厂还提供其它一些优UҎ?除创?SAX 语法分析器实例的基本工作之外Q类厂还允许讄配置选项。这些选项影响所有通过cd获得的语法分析器实例。JAXP 1.0 中两个可用的功能是设|名U空间敏感?(
setNamespaceAware
(boolean awareness))Q和打开认 (setValidating
(boolean validating))。请CQ一旦设|了q些选项Q在调用该方法之后,它们媄?所?/i>?cd获得的实例?讄了类厂之后,调用
newSAXParser()
返回一个随时可用的 JAXPSAXParser
cd例。这个类装了一个下层的 SAX 语法分析器(SAX c?org.xml.sax.Parser
的实例)。它q防止向语法分析器类dM特定于供应商的附加功能。(q记得以前对XmlDocument
的讨论吗Q)q个cd以开始进行实际的语法分析。以下清单显C如何创建、配|和使用 SAX cd?
清单 1. 使用 SAXParserFactory
import java.io.File; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; // JAXP import javax.xml.parsers.FactoryConfigurationError; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParserFactory; import javax.xml.parsers.SAXParser; // SAX import org.xml.sax.AttributeList; import org.xml.sax.HandlerBase; import org.xml.sax.SAXException; public class TestSAXParsing { public static void main(String[] args) { try { if (args.length != 1) { System.err.println ("Usage: java TestSAXParsing [filename]"); System.exit (1); } // 获得SAX 语法分析器类? SAXParserFactory factory = SAXParserFactory.newInstance(); //讄讄名称I间敏感性选项Q关掉确认选项 factory.setValidating(true); factory.setNamespaceAware(false); SAXParser parser = factory.newSAXParser(); parser.parse(new File(args[0]), new MyHandler()); } catch (ParserConfigurationException e) { System.out.println("The underlying parser does not support " + " the requested features."); } catch (FactoryConfigurationError e) { System.out.println("Error occurred obtaining SAX Parser Factory."); } catch (Exception e) { e.printStackTrace(); } } } class MyHandler extends HandlerBase { //通过 DocumentHandler, ErrorHandler{实现的SAX回调函数 }
h意,在这D代码中Q在使用cd时可能发生两个特定于 JAXP 的问题:无法获得或配|?SAX cdQ以及无法配|?SAX 语法分析器。当无法获得 JAXP 实现中指定的语法分析器或pȝ属性时Q通常会发生第一个问?
FactoryConfigurationError
。当正在使用的语法分析器中的Ҏ不可用Ӟ会发生第二个问题ParserConfigurationException
。这两个问题都容易处理,应该不会?JAXP 的用造成M困难?在获得类厂、关闭名U空间ƈ打开“确认”之后,获?
SAXParser
Q然后开始语法分析。请注意Q?SAX 语法分析器的parse()
Ҏ取得前面提到?SAXHandlerBase
cȝ一个实例。(可以通过完整?Java 清单 查看该类的实?/font> 。)q要传递要q行语法分析的文件。但是,SAXParser
所包含的远不止q一个方法?获得
SAXParser
cȝ实例之后Q除了向语法分析器传?File
q行语法分析之外Q还可以用它做更多的事。由于如今大型应用中的应用程序组件之间通信方式Q“对象实例创就是其使用者”这L假定q不L安全的。换句话_一个组件可能创?SAXParser
实例Q而另一lgQ可能由另一开发h员编码)可能需要用那个实例。由于这个原因,提供了一些方法来定语法分析器的讄。执行此d的两个方法是isValidating()
Q它通知调用E序Q语法分析器要、或不要执行“确认”,以及isNamespaceAware()
Q它q回一个指C,说明语法分析器可以或不可以处?XML 文档中的名称I间。虽然这些方法能提供有关语法分析器可以执行功能的信息Q但是无法更改这些特性。必d语法分析器类厂别执行该操作?另外Q有多种Ҏ来请求对文档q行语法分析。除了只接受
File
?SAXHandlerBase
实例QSAXParser ?parse()
Ҏq能?String
形式接受 SAXInputSource
、JavaInputStream
?URLQ所有这些都要与HandlerBase
实例一h供。所以,不同cd的输入文档可以用不同方式的语法分析来处理?最后,可以直接通过 SAXParser ?
getParser()
Ҏ获得和用下层的 SAX 语法分析器(org.xml.sax.Parser
的实例)。获得这个下层实例之后,可以获得通常?SAX Ҏ。下一个清单显C?SAXParser
c(q个 JAXP ?SAX 语法分析的核心类Q的各种使用CZ?
清单 2. 使用 JAXP SAXParser
//获得SAXP的一个实? SAXParser saxParser = saxFactory.newSAXParser(); //查看是否支持 Validate 选项 boolean isValidating = saxParser.isValidating(); //查看是否支持 namespace 选项 boolean isNamespaceAware = saxParser.isNamespaceAware(); // q用一个File 和一个SAX HandlerBase 的实例进行多UŞ式的语法分析 saxParser.parse(new File(args[0]), myHandlerBaseInstance); // q用一?SAX InputSource实例 和一?SAX HandlerBase 实例 saxParser.parse(mySaxInputSource, myHandlerBaseInstance); //q用一?InputStream 实例和一个SAX HandlerBase 实例 saxParser.parse(myInputStream, myHandlerBaseInstance); // q用一?URI 和一个SAX HandlerBase 实例 saxParser.parse("http://www.newInstance.com/xml/doc.xml", myHandlerBaseInstance); //获得底层的(装QSAX 语法分析? org.xml.sax.Parser parser = saxParser.getParser(); //利用底层的语法分析器 parser.setContentHandler(myContentHandlerInstance); parser.setErrorHandler(myErrorHandlerInstance); parser.parse(new org.xml.sax.InputSource(args[0]));
目前为止Q关?SAX 已经讲了很多Q但是还没有揭示M不寻常或令h惊奇的东ѝ事实上QJAXP 的功能很,特别是当 SAX 也牵涉进来时。这很好Q因为有最的功能性意味着代码可移植性更强,q可以由其他开发h员与M?SAX 兼容?XML 语法分析器一起用,无论是免费(通过开放源码,希望如此Q还是通过商业途径。就是这栗在 JAXP 中?SAX 没有更多的东ѝ如果已l知?SAXQ那么现在已l掌握大U?98% 的内宏V只需学习两个新类和两?Java 异常Q您可以开始了。如果从没用过 SAXQ那也很单,现在可以开始?/p>
![]()
![]()
![]()
![]()
回页?/font>
如果要休息以q接 DOM 挑战Q那么先别休息。在 JAXP 中?DOM 的过E与 SAX 几乎相同Q所要做的全部只是更改两个类名和一个返回类型,q样差不多了。如果理?SAX 的工作原理和 DOM 是什么,则不会有M问题?/p>
DOM ?SAX 的主要差异是它们?API l构。SAX 包含一个基于事件的回调函数集,?DOM 有一个内存中的树状结构。换句话_?SAX 中,从不需要操作数据结构(除非开发h员手工创建)。因此,SAX 不提供修?XML 文档的功能。?DOM 正好提供q种cd的功能?
org.w3c.dom.Document
c表C?XML 文档Q它pC元素、属性和其它 XML l构?DOM 节点 l成。所以,JAXP 无需触发 SAX 回调Q它只负责从语法分析q回一?DOMDocument
对象?基本理解 DOM 以及 DOM ?SAX 的差异之后,没什么好说的了。以下代码看h?SAX 代码cM。首先,获得
DocumentBuilderFactory
Q与 SAX 中的方式相同)。然后,配置cd来处理确认和名称I间Q与 SAX 中的方式相同)。下一步,从类厂中?DocumentBuilder
Q它?SAXParser
cMQ(?SAX 中的方式相同. . . 啊,您都知道了)。然后,可以进行语法分析了Q生的 DOMDocument
对象传递给打印 DOM 树的Ҏ?
清单 3. 使用文档构徏器类?/b>
import java.io.File; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; // JAXP import javax.xml.parsers.FactoryConfigurationError; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilder; // DOM import org.w3c.dom.Document; import org.w3c.dom.DocumentType; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; public class TestDOMParsing { public static void main(String[] args) { try { if (args.length != 1) { System.err.println ("Usage: java TestDOMParsing [filename]"); System.exit (1); } // 获得 Document Builder Factory DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); //打开认选项Q关掉名U空间敏感性选项? factory.setValidating(true); factory.setNamespaceAware(false); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(new File(args[0])); // 从DOM C打印文档Qƈ加一初始I格 printNode(doc, ""); // 在这里也可以?DOM 文档q行修改 } catch (ParserConfigurationException e) { System.out.println("The underlying parser does not support the requested features."); } catch (FactoryConfigurationError e) { System.out.println("Error occurred obtaining Document Builder Factory."); } catch (Exception e) { e.printStackTrace(); } } private static void printNode(Node node, String indent) { // 打印 DOM ? }
此代码中可能会出C个不同的问题Q与 JAXP 中的 SAX cMQ:
FactoryConfigurationError
?ParserConfigurationException
。每一个的原因?SAX 中的相同。不是实现类 (FactoryConfigurationError
) 中有问题Q就是语法分析器不支持请求的Ҏ?(ParserConfigurationException
)。DOM ?SAX 的唯一差异是:?DOM 中,?DocumentBuilderFactory
替代SAXParserFactory
Q用DocumentBuilder
替代SAXParser
。就q么单!Q可?查看完整代码清单 Q该清单包括用于打印 DOM 树的Ҏ。)有了 DOM cd之后Q就可以获得
DocumentBuilder
实例?DocumentBuilder
实例可以使用的方法与 SAX 的非常类伹{主要差异是parse()
的变U不需?HandlerBase
cȝ实例。它们返回表C法分析之后的 XML 文档?DOMDocument
实例。另一唯一不同之处是:为类g SAX 的功能提供了两个ҎQ用 SAXErrorHandler
实现来处理语法分析时可能出现的问题的setErrorHandler()
Q和?SAXEntityResolver
实现来处理实体解析的setEntityResolver()
。如果不熟悉q些概念Q则需要通过联机或在我的书中学习 SAX。以下清单显CZ用这些方法的CZ?
清单 4. 使用 JAXP DocumentBuilder
//获得一?DocumentBuilder 实例 DocumentBuilder builder = builderFactory.newDocumentBuilder(); //查看是否支持 Validate 选项 boolean isValidating = builder.isValidating(); //查看是否支持 namespace 选项 boolean isNamespaceAware = builder.isNamespaceAware(); // 讄一?SAX ErrorHandler builder.setErrorHandler(myErrorHandlerImpl); // 讄一?SAX EntityResolver builder.setEntityResolver(myEntityResolverImpl); // q用多种Ҏ?file q行语法分析 Document doc = builder.parse(new File(args[0])); // q用 SAX InputSource Document doc = builder.parse(mySaxInputSource); // q用 InputStream Document doc = builder.parse(myInputStream, myHandlerBaseInstance); // q用 URI Document doc = builder.parse("http://www.newInstance.com/xml/doc.xml");
是不是感?DOM q一节有些o人厌烦?有这U想法的不止您一个,?DOM 代码有些令h厌烦是因为它是直接取得所学的 SAX 知识Q然后将其用?DOM。因此,和朋友、同事打赌吧Q说使用 JAXP 只是菜一?/p>
![]()
![]()
![]()
![]()
回页?/font>
最后要探讨的主题是 JAXP L更改cdcM用的语法分析器的能力。更?JAXP 使用的语法分析器实际意味着更改 cdQ因为所?
SAXParser
?DocumentBuilder
实例都来自这些类厂。既然确定装入哪个语法分析器的是cdQ因此,必须更改cd。可以通过讄 Java pȝ属?javax.xml.parsers.SAXParserFactory
来更改要使用?SAXParserFactory
接口实现。如果没有定义该属性,则返回缺省实玎ͼ供应商指定的M语法分析?。相同原理适用?DocumentBuilderFactory
实现。在q种情况下,查?javax.xml.parsers.DocumentBuilderFactory
pȝ属性。就q么单,我们已经学完了!q就?SAXP 的全部:提供?SAX 的挂钩,提供?DOM 的挂钩,q允许轻易更改语法分析器?
![]()
![]()
![]()
![]()
回页?/font>
如您所见,没多复杂的东西。更改系l属性,通过cd、而不是语法分析器或构建器来设|“确认”,以及弄清楚JAXP实际上不是h们通常所认ؓ的那Pq些是?JAXP 的最困难部分。除了没?SAX 2.0 ?DOMW二层规范支持之外,JAXP 在两个流行的 Java ?XML API 之上提供一个有帮助的可插入层。它使代码独立于供应商,q允怸~译语法分析代码而更改语法分析器。那么,?Sun、Apache XML 或其它方便之处下?JAXPQƈ使用它吧Ql关?JAXP 1.1Qƈ增加?SAX 2 ?DOM 2、XSLT 及更多内容的支持。您在q里获得W一手新闻,所以,请关?developerWorks?
]]>