XML
一、Java XML 教程
1、Java XML 解析器
1.1、什么是XML解析?
解析XML是指将通过XML文档访问数据或修改数据的一个操作或方法。
Java库中提供了两种XML解析器:
1、像文档对象模型(Document Object Model,DOM)解析器这的树型解析器(tree parse),它们将读入的XML文档转换成树结构。
2、像XML简单API(Simple API for XML,SAX)解析器这样的流机制解析器(streaming parser),它们在读入XML文档时生成相应的事件。
1.2、XML解析器是什么?
XML解析器提供方法来访问或修改XML文档中的数据。 Java提供了多种选择来解析XML文档。以下是各种类型解析器其通常用于解析XML文档。
Dom解析器 -解析通过加载该文件的全部内容,并创建其完整分级树中存储的文件。
SAX解析器 -解析基于事件触发器的文档。不完整(部分)的文件加载到存储器中。
JDOM解析器 -解析以类似的方式,以DOM解析器但更简单的方法的文档。
StAX解析器 -解析以类似的方式,以SAX解析器但在更高效的方式的文档。
XPath解析器 -解析基于表达式XML并广泛选择使用XSLT。
DOM4J解析器 -Java库来解析XML,XPath和使用Java集合框架XSLT,为DOM,SAX和JAXP的支持。
2、Java DOM解析器
2.1、DOM解析器简介
文档对象模型是万维网联盟(W3C)的官方推荐。它定义了一个接口,使程序能够访问和更新样式,结构和XML文档的内容。支持DOM实现该接口的XML解析器。
何时使用?
在以下几种情况时,应该使用DOM解析器:
1、需要知道很多关于文档的结构
2、需要将文档的部分周围(例如,可能需要某些元素进行排序)
3、需要使用的文件中的信息超过一次
会得到什么?
当使用DOM 解析器解析一个XML文档,会得到一个树形结构,其中包含的所有文档的元素。 DOM提供了多种可用于检查文档的内容和结构的函数。
优势
DOM是用于处理文档结构的通用接口。它的一个设计目标是Java代码编写一个DOM兼容的解析器,运行在任何其他的DOM兼容的解析器不会有变化。
DOM接口
DOM定义了几个Java接口。这里是最常见的接口:
1、节点 - DOM的基本数据类型。
2、元素 - 要处理的对象绝大多数是元素。
3、Attr - 代表元素的属性。
4、文本 - 元素或Attr的实际内容。
5、文档 - 代表整个XML文档。文档对象是通常被称为DOM树。
常见的DOM方法
当正在使用DOM,有经常用到的几种方法:
1、Document.getDocumentElement() - 返回文档的根元素。
2、Node.getFirstChild() - 返回给定节点的第一个子节点。
3、Node.getLastChild() - 返回给定节点的最后一个子节点。
4、Node.getNextSibling() - 这些方法返回一个特定节点的下一个兄弟节点。
5、Node.getPreviousSibling() - 这些方法返回一个特定节点的前一个兄弟节点。
6、Node.getAttribute(attrName) - 对于给定的节点,则返回所请求的名字的属性。
2.2、Java DOM解析器 - 解析XML文档
使用DOM的步骤
以下是在使用DOM解析器解析文档使用的步骤。
1、导入XML相关的软件包。
2、创建DocumentBuilder
3、从文件或流创建一个文档
4、提取根元素
5、检查属性
6、检查子元素
document对象:
要操作XML,先就得有Document对象,把一个XML文件加载进内存的时候,在内存中形成所谓的一种树状结构,我们把这一个结构称之为DOM树.
注意:
我们在Java代码中所做的增/删/改/查操作,都仅仅是操作的是内存中的Document对象,和磁盘中的XML文件没有关系。比如:删除一个联系人信息之后,XML文件中数据依然存在,此时出现内存中的数据和磁盘文件中的数据不同步。所以,对于增删改操作,我们需要做同步操作(把内存中的数据和磁盘的XML文件数据保持一致)。
DOM:在第一次的时候就会把XML文件加载进内存,如果XML文件过大,可能会造成内存的溢出.
DOM:在做增删改查操作的时候比较简单,,但是性能却不高(线性搜索).
3、Java SAX解析器
3.1、Java SAX解析器简介
SAX解析器在解析XML输入数据的各个组成部分时会报告事件,但不会以任何方式存储文档,而是由事件处理器建立相应的数据结构。实际上DOM解析器是在SAX解析器的基础上构建的,它在接收到解析器事件时构建DOM树。
SAX(针对XML的简单API)是基于事件为XML文档的解析器。不像DOM解析器,SAX解析器创建没有解析树。 SAX是一个流接口用于XML的,这意味着使用SAX应用接收事件通知有关XML文档被处理的元素,属性,在按顺序每次开始在文档的顶部,并与所述闭合结束根元素。
1、读取XML文件从上到下,构成一个结构完整的XML文档的标记
2、令牌以相同的顺序进行处理,它们出现在文档中
3、报告应用程序,因为它们所出现解析器遇到标记的特性
4、应用程序提供了必须的解析器注册的“事件”处理程序
5、作为标记标识,在处理程序回调方法相关信息调用
什么时候使用?
应该使用SAX解析器的时候:
1、可以在XML文档从上往下处理以线性方式
2、该文件并不深层次嵌套
3、处理一个非常大的XML文档,DOM树会占用太多的内存。典型DOM的实现使用10字节的存储器以表示XML的一个字节
4、解决的问题涉及的XML文档的一部分
5、数据是可用的,只要它是由解析器看出,这样的SAX可以很好地用于到达流的XML文档
SAX的缺点
1、它是在一个只进入处理随机访问方式XML文档
2、如果需要跟踪的数据分析器已经看到或更改项目的顺序,必须自已编写代码和数据存储
4、Java StAX解析器
4.1、Java StAX解析器简介
StAX即Streaming API for XML,当前最有效的XML处理方法,因此特别适合于处理复杂流程,比如数据库绑定和SOAP消息。StAX创建的信息集是非常小,可以直接作为垃圾收集的候选对象。这让XML处理任务占用较小的空间,使得它不仅适用于小型堆设备,比如移动电话,而且适用于长期运行的服务器端应用程序。
与SAX不同,StAX能够对XML文档进行写操作,这减少了需要处理的API数量。
StAX提供两种不同的解析数据模型:光标模型和迭代器模型。
环境设置
为了使用StAX的解析器,应该准备好stax.jar在应用程序的类路径中。下载 stax-1.2.0.jar,以下是StAX API的功能:
1、读取XML文件从上到下,认识构成一个结构完整的XML文档的标记
2、令牌是以相同的顺序进行处理,它们出现在文档中
3、报告应用程序,因为解析器遇到标记的特性
4、应用程序提供了一个“事件”读取器充当了事件,以获得所需信息的迭代器和迭代。可另一个读取器是“光标”充当一个指向XML 节点。
5、由于事件被识别,XML元素可以从事件对象进行检索,并且可以进一步处理。
什么情况下使用?
应该使用的StAX解析器的时候:
1、可以处理在自上而下线性方式的XML文档。
2、文件并不深入嵌套。
3、处理一个非常大的XML文档的DOM树会占用太多的内存。典型的DOM的实现使用10字节的存储器以表示XML的一个字节。
4、要解决的问题涉及XML文档的一部分。
5、数据是可用的,只要它是由解析器处理,这样StAX可以很好地用于所收到超过数据流的XML文档。
SAX的缺点
1、因为它是在一个处理的方式,而不是随机访问XML文档。
2、如果需要跟踪的数据分析器已经看到或更改项目的顺序,必须编写代码和数据存储以自己方式处理。
XMLEventReader类
因为在解析XML文档时该类提供可用于迭代事件事件迭代器
1、StartElement asStartElement() - 用于检索值和元素的属性。
2、EndElement asEndElement() - 调用元件的端部。
3、Characters asCharacters() - 可用于获得字符,例如一个CDATA,空白等。
XMLEventWriter类
此接口指定创建事件的方法。
add(Event event) - 添加包含元素XML事件。
XMLStreamReader Class
因为在解析XML文档时该类提供可用于迭代事件事件迭代器
1、int next() - 用于检索下一个事件。
2、boolean hasNext() - 用于检查其他事件的存在与否
3、String getText() - 用于获取一个元素的文本
4、String getLocalName() - 用于获取一个元素的名称
XMLStreamWriter类
此接口指定创建事件的方法
1、writeStartElement(String localName) - 加入定名称开始元素。
2、writeEndElement(String localName) - 添加指定名称的结束元素。
3、writeAttribute(String localName, String value) - 编写属性到元素。
5、Java DOM4J解析器
5.1、Java DOM4J解析器解析
DOM4J是一个开源的,基于Java的库来解析XML文档,它具有高度的灵活性,高性能和内存效率的API。这是java的优化,使用Java集合像列表和数组。它可以使用DOM,SAX,XPath和XSLT。它解析大型XML文档时具有极低的内存占用。
环境设置
为了使用DOM4J解析器,应该 dom4j-1.6.1.jar 和 jaxen.jar 在应用程序的类路径中。下载 dom4j-1.6.1.zip.
什么情况下使用?
应该考虑使用DOM4J解析器的时候:
1、需要知道很多关于文档的结构
2、需要将文档的部分围绕(例如,可能需要某些元素进行排序)
3、需要使用的文件中的信息超过一次
4、你是一个Java开发人员,并希望利用XML的Java的优化解析。
会得到什么?
当解析一个DOM4J解析XML文档,可以灵活地得到一个树形结构,其中包含所有文档的元素,而不会影响应用程序的内存占用。DOM4J提供了多种可用于检查的情况下文档内容和结构的实用功能是良好的结构,其结构是公知的。 DOM4J使用XPath表达式来浏览XML文档。
优势
DOM4J使Java开发的灵活性和XML解析代码易于维护。它是轻量级的,快速的API。
6、总结
XML解析方式分为两种:dom和sax
dom:(Document Object Model, 即文档对象模型) 是 W3C 组织推荐的处理 XML 的一种方式。
sax: (Simple API for XML) 不是官方标准,但它是XML 社区事实上的标准,几乎所有的 XML 解析器都支持它。
XML解析器
Crimson、Xerces 、Aelfred2
**XML解析开发包**
Jaxp、Jdom、dom4j
- DOM解析
DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准。DOM是以层次结构组织的节点或信息片断的集合。这个层次结构允许开发人员在树中寻找特定信息。分析该结构通常需要加载整个文档和构造层次结构,然后才能做任何工作。由于它是基于信息层次的,因而DOM被认为是基于树或基于对象的。
DOM解析器把XML文档转化为一个包含其内容的树,并可以对树进行遍历。
DOM是拉模型,在遍历文档时,会把感兴趣的部分从读取器中拉出,不需要引发事件,允许我们选择性地处理节点。这大大提高了灵活性,以及整体效率。
2、DOM的基本对象有5个:Document,Node,NodeList,Element和Attr。**
2.1、Document对象
代表了整个XML的文档,所有其它的Node,都以一定的顺序包含在Document对象之内,排列成一个树形的结构,程序员可以通过遍历这颗树来得到XML文档的所有的内容,这也是对XML文档操作的起点。我们总是先通过解析XML源文件而得到一个Document对象,然后再来执行后续的操作。此外,Document还包含了创建其它节点的方法,比如createAttribut()用来创建一个Attr对象。它所包含的主要的方法有:
createAttribute(String):用给定的属性名创建一个Attr对象,并可在其后使用setAttributeNode方法来放置在某一个Element对 象上面。
createElement(String):用给定的标签名创建一个Element对象,代表XML文档中的一个标签,然后就可以在这个Element对象 上添加属性或进行其它的操作。
createTextNode(String):用给定的字符串创建一个Text对象,Text对象代表了标签或者属性中所包含的纯文本字符串。如果在 一个标签内没有其它的标签,那么标签内的文本所代表的Text对象是这个Element对象的唯一子对象。
getElementsByTagName(String):返回一个NodeList对象,它包含了所有给定标签名字的标签。
getDocumentElement():返回一个代表这个DOM树的根节点的Element对象,也就是代表XML文档根元素的那个对象。
2.2、Node对象
是DOM结构中最为基本的对象,代表了文档树中的一个抽象的节点。在实际使用的时候,很少会真正的用到Node这个对象,而是用到诸如Element、Attr、Text等Node对象的子对象来操作文档。Node对象为这些对象提供了一个抽象的、公共的根。虽然在Node对象中定义了对其子节点进行存取的方法,但是有一些Node子对象,比如Text对象,它并不存在子节点,这一点是要注意的。Node对象所包含的主要的方法有:
appendChild(org.w3c.dom.Node):为这个节点添加一个子节点,并放在所有子节点的最后,如果这个子节点已经存在,则先 把它删掉再添加进去。
getFirstChild():如果节点存在子节点,则返回第一个子节点,对等的,还有getLastChild()方法返回最后一个子节点。
getNextSibling():返回在DOM树中这个节点的下一个兄弟节点,对等的,还有getPreviousSibling()方法返回其前一个兄弟节 点。
getNodeName():根据节点的类型返回节点的名称。
getNodeType():返回节点的类型。
getNodeValue():返回节点的值。
hasChildNodes():判断是不是存在有子节点。
hasAttributes():判断这个节点是否存在有属性。
getOwnerDocument():返回节点所处的Document对象。
insertBefore(org.w3c.dom.Node new,org.w3c.dom.Node ref):在给定的一个子对象前再插入一个子对象。
removeChild(org.w3c.dom.Node):删除给定的子节点对象。
replaceChild(org.w3c.dom.Node new,org.w3c.dom.Node old):用一个新的Node对象代替给定的子节点对象。
2.3、NodeList对象
顾名思义,就是代表了一个包含了一个或者多个Node的列表。可以简单的把它看成一个Node的数组,我们可以通过方法来获得列表中的元素:
getLength():返回列表的长度。
item(int):返回指定位置的Node对象。
2.4、Element对象**
代表的是XML文档中的标签元素,继承于Node,亦是Node的最主要的子对象。在标签中可以包含有属性,因而Element对象中有存取其属性的方法,而任何Node中定义的方法,也可以用在Element对象上面。
getElementsByTagName(String):返回一个NodeList对象,它包含了在这个标签中其下的子孙节点中具有给定标签名字的标 签。
getTagName():返回一个代表这个标签名字的字符串。
getAttribute(String):返回标签中给定属性名称的属性的值。在这儿需要主要的是,应为XML文档中允许*有实体属性出现,而 这个方法对这些实体属性并不适用。这时候需要用到getAttributeNodes()方法来得到一个Attr对象来进行进一步的操作。
getAttributeNode(String):返回一个代表给定属性名称的Attr对象。
2.5、Attr对象
代表了某个标签中的属性。Attr继承于Node,但是因为Attr实际上是包含在Element中的,它并不能被看作是Element的子对象,因而在DOM中Attr并不是DOM树的一部分,所以Node中的getParentNode(),getPreviousSibling()和getNextSibling()返回的都将是null。也就是说,Attr其实是被看作包含它的Element对象的一部分,它并不作为DOM树中单独的一个节点出现。这一点在使用的时候要同其它的Node子对象相区别。
3、SAX解析
SAX是Simple API forXML的缩写,它并不是由W3C官方所提出的标准,可以说是“民间”的事实标准。实际上,它是一种社区性质的讨论产物。虽然如此,在XML中对SAX的应用丝毫不比DOM少,几乎所有的XML解析器都会支持它。
与DOM比较而言,SAX是一种轻量型的方法。我们知道,在处理DOM的时候,我们需要读入整个的XML文档,然后在内存中创建DOM树,生成DOM树上的每个Node对象。当文档比较小的时候,这不会造成什么问题,但是一旦文档大起来,处理DOM就会变得相当费时费力。特别是其对于内存的需求,也将是成倍的增长,以至于在某些应用中使用DOM是一件很不划算的事(比如在applet中)。这时候,一个较好的替代解决方法就是SAX。
SAX在概念上与DOM完全不同。首先,不同于DOM的文档驱动,它是事件驱动的,也就是说,它并不需要读入整个文档,而文档的读入过程也就是SAX的解析过程。所谓事件驱动,是指一种基于回调(callback)机制的程序运行方法。(如果你对Java新的代理事件模型比较清楚的话,就会很容易理解这种机制了)
回调:由我们在组件中定义,而不由我们调用,由容器或框架调用
SAX是推模型,它是一种靠事件驱动的模型。当它每发现一个节点就引发一个事件,而我们需要编写这些事件的处理程序。这样的做法很麻烦,且不灵活。
一、StAX 解析
针对于XML的流式API(StAX),是在2004年3月的JSR 173规范中引入,这是一种针对XML的流式拉分析API。StAX是JDK 6.0提供的一种新特征。
一个推模型分析器不断地生成事件,直到XML文档被完全分析结束。但是,拉分析由应用程序进行调整;因此,分析事件是由应用程序生成的。这意味着,使用StaX,你可以推迟分析-在分析时跳过元素并且分析多个文档。在使用DOM API的时候,你必须把整个的XML文档分析成一棵DOM结构,这样也就降低了分析效率。而借助于StAX,在分析XML文档时生成分析事件。
二、DOM4J
虽然DOM4J代表了完全独立的开发结果,但最初,它是JDOM的一种智能分支。它合并了许多超出基本XML文档表示的功能,包括集成的XPath支持、 XML Schema支持以及用于大文档或流化文档的基于事件的处理。它还提供了构建文档表示的选项,它通过DOM4J API和标准DOM接口具有并行访问功能。从2000下半年开始,它就一直处于开发之中。
为支持所有这些功能,DOM4J使用接口和抽象基本类方法。DOM4J大量使用了API中的Collections类,但是在许多情况下,它还提供一些替 代方法以允许更好的性能或更直接的编码方法。直接好处是,虽然DOM4J付出了更复杂的API的代价,但是它提供了比JDOM大得多的灵活性。
在添加灵活性、XPath集成和对大文档处理的目标时,DOM4J的目标与JDOM是一样的:针对Java开发者的易用性和直观操作。它还致力于成为比 JDOM更完整的解决方案,实现在本质上处理所有Java/XML问题的目标。在完成该目标时,它比JDOM更少强调防止不正确的应用程序行为。
DOM4J是一个非常非常优秀的JavaXML API,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件。如今你可以看到越来越多的Java软件都在使用DOM4J来读写XML,特别值得一提的是连Sun的JAXM也在用DOM4J.
3、DOM与SAX的区别
一、DOM:拉模型,把整个文档加载到内存中
优点:整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能;
缺点:将整个文档调入内存(包括无用的节点),浪费时间和空间;
使用场合:一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU)
二、SAX:推模型,事件驱动编程,基于回调SAX ,事件驱动。当解析器发现元素开始、元素结束、文本、文档的开始或结束等时,发送事件,程序员编写响应这些事件的代码,保存数据。
优点:不用事先调入整个文档,占用资源少;
缺点:不是持久的;事件过后,若没保存数据,那么数据就丢了;无状态性;从事件中只能得到文本,但不知该文本属于哪个元素;
使用场合:数据量较大的XML文档,占用内存高,机器内存少,无法一次加载XML到内存;只需XML文档的少量内容,很少回头访问;
性能比较
1)DOM4J性能最好,连Sun的JAXM也在用DOM4J.目前许多开源项目中大量采用DOM4J,例如大名鼎鼎的hibernate也用DOM4J来读取XML配置文件。如果不考虑可移植性,那就采用DOM4J.
2)SAX表现较好,这要依赖于它特定的解析方式-事件驱动。一个SAX检测即将到来的XML流,但并没有载入到内存(当然当XML流被读入时,会有部分文档暂时隐藏在内存中)。
Java设计模式
一、设计模式的分类
总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
其实还有两类:并发型模式和线程池模式。
二、设计模式的六大原则
1、开闭原则(Open Close Principle)
开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会提到这点。
2、里氏代换原则(Liskov Substitution Principle)
里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。—— From Baidu 百科
3、依赖倒转原则(Dependence Inversion Principle)
这个是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。
4、接口隔离原则(Interface Segregation Principle)
这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。
5、迪米特法则(最少知道原则)(Demeter Principle)
为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。
6、合成复用原则(Composite Reuse Principle)
原则是尽量使用合成/聚合的方式,而不是使用继承。