您的当前位置:首页正文

java解析xml的4种方式的优缺点对比及实现详解

2022-02-08 来源:客趣旅游网
java解析xml的4种⽅式的优缺点对⽐及实现详解

⼀、介绍及优缺点分析

DOM(Document Object Model)

DOM是⽤与平台和语⾔⽆关的⽅式表⽰XML⽂档的官⽅W3C标准。DOM是以层次结构组织的节点或信息⽚断的集合。这个层次结构允许开发⼈员在树中寻找特定信息。分析该结构通常需要加载整个⽂档和构造层次结构,然后才能做任何⼯作。由于它是基于信息层次的,因⽽DOM被认为是基于树或基于对象的。【优点】

①允许应⽤程序对数据和结构做出更改。

②访问是双向的,可以在任何时候在树中上下导航,获取和操作任意部分的数据。整个⽂档树在内存中,便于操作;⽀持删除、修改、重新排列等多种功能【缺点】

①通常需要加载整个XML⽂档来构造层次结构,消耗资源⼤。

将整个⽂档调⼊内存(包括⽆⽤的节点),浪费时间和空间;使⽤场合:⼀旦解析了⽂档还需多次访问这些数据;硬件资源充⾜(内存、CPU)SAX(Simple API for XML)

SAX处理的优点⾮常类似于流媒体的优点。分析能够⽴即开始,⽽不是等待所有的数据被处理。⽽且,由于应⽤程序只是在读取数据时检查数据,因此不需要将数据存储在内存中。这对于⼤型⽂档来说是个巨⼤的优点。事实上,应⽤程序甚⾄不必解析整个⽂档;它可以在某个条件得到满⾜时停⽌解析。⼀般来说,SAX还⽐它的替代者DOM快许多。

选择DOM还是选择SAX? 对于需要⾃⼰编写代码来处理XML⽂档的开发⼈员来说, 选择DOM还是SAX解析模型是⼀个⾮常重要的设计决策。 DOM采⽤建⽴树形结构的⽅式访问XML⽂档,⽽SAX采⽤的是事件模型。

DOM解析器把XML⽂档转化为⼀个包含其内容的树,并可以对树进⾏遍历。⽤DOM解析模型的优点是编程容易,开发⼈员只需要调⽤建树的指令,然后利⽤navigation APIs访问所需的树节点来完成任务。可以很容易的添加和修改树中的元素。然⽽由于使⽤DOM解析器的时候需要处理整个XML⽂档,所以对性能和内存的要求⽐较⾼,尤其是遇到很⼤的XML⽂件的时候。由于它的遍历能⼒,DOM解析器常⽤于XML⽂档需要频繁的改变的服务中。

SAX解析器采⽤了基于事件的模型,它在解析XML⽂档的时候可以触发⼀系列的事件,当发现给定的tag的时候,它可以激活⼀个回调⽅法,告诉该⽅法制定的标签已经找到。SAX对内存的要求通常会⽐较低,因为它让开发⼈员⾃⼰来决定所要处理的tag.特别是当开发⼈员只需要处理⽂档中所包含的部分数据时,SAX这种扩展能⼒得到了更好的体现。但⽤SAX解析器的时候编码⼯作会⽐较困难,⽽且很难同时访问同⼀个⽂档中的多处不同数据。【优势】

①不需要等待所有数据都被处理,分析就能⽴即开始。②只在读取数据时检查数据,不需要保存在内存中。③可以在某个条件得到满⾜时停⽌解析,不必解析整个⽂档。④效率和性能较⾼,能解析⼤于系统内存的⽂档。

不⽤事先调⼊整个⽂档,占⽤资源少;SAX解析器代码⽐DOM解析器代码⼩,适于Applet,下载。【缺点】

①需要应⽤程序⾃⼰负责TAG的处理逻辑(例如维护⽗/⼦关系等),⽂档越复杂程序就越复杂。②单向导航,⽆法定位⽂档层次,很难同时访问同⼀⽂档的不同部分数据,不⽀持XPath。

不是持久的;事件过后,若没保存数据,那么数据就丢了;⽆状态性;从事件中只能得到⽂本,但不知该⽂本属于哪个元素;使⽤场合:Applet;只需XML⽂档的少量内容,很少回头访问;机器内存少。JDOM(Java-based Document Object Model)

JDOM的⽬的是成为Java特定⽂档模型,它简化与XML的交互并且⽐使⽤DOM实现更快。由于是第⼀个Java特定模

型,JDOM⼀直得到⼤⼒推⼴和促进。正在考虑通过“Java规范请求JSR-102”将它最终⽤作“Java标准扩展”。从2000年初就已经开始了JDOM开发。

JDOM与DOM主要有两⽅⾯不同。⾸先,JDOM仅使⽤具体类⽽不使⽤接⼝。这在某些⽅⾯简化了API,但是也限制了灵活性。第⼆,API⼤量使⽤了Collections类,简化了那些已经熟悉这些类的Java开发者的使⽤。

JDOM⽂档声明其⽬的是“使⽤20%(或更少)的精⼒解决80%(或更多)Java/XML问题”(根据学习曲线假定为20%)。

JDOM对于⼤多数Java/XML应⽤程序来说当然是有⽤的,并且⼤多数开发者发现API⽐DOM容易理解得多。JDOM还包括对程序⾏为的相当⼴泛检查以防⽌⽤户做任何在XML中⽆意义的事。然⽽,它仍需要您充分理解XML以便做⼀些超出基本的⼯作(或者甚⾄理解某些情况下的错误)。这也许是⽐学习DOM或JDOM接⼝都更有意义的⼯作。

JDOM⾃⾝不包含解析器。它通常使⽤SAX2解析器来解析和验证输⼊XML⽂档(尽管它还可以将以前构造的DOM表⽰作为输⼊)。它包含⼀些转换器以将JDOM表⽰输出成SAX2事件流、DOM模型或XML⽂本⽂档。JDOM是在Apache许可证变体下发布的开放源码。【优点】

①使⽤具体类⽽不是接⼝,简化了DOM的API。②⼤量使⽤了Java集合类,⽅便了Java开发⼈员。【缺点】

①没有较好的灵活性。②性能较差。

DOM4J(Document Object Model for Java)

虽然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是⼀个⾮常⾮常优秀的Java XML API,具有性能优异、功能强⼤和极端易⽤使⽤的特点,同时它也是⼀个开放源代码的软件。如今你可以看到越来越多的Java软件都在使⽤DOM4J来读写XML,特别值得⼀提的是连Sun的JAXM也在⽤DOM4J.【优点】

①⼤量使⽤了Java集合类,⽅便Java开发⼈员,同时提供⼀些提⾼性能的替代⽅法。②⽀持XPath。③有很好的性能。【缺点】

①⼤量使⽤了接⼝,API较为复杂。总结:

如果XML⽂档较⼤且不考虑移植性问题建议采⽤DOM4J;如果XML⽂档较⼩则建议采⽤JDOM;

如果需要及时处理⽽不需要保存数据则考虑SAX。

适合⾃⼰的才是最好的,如果时间允许,建议⼤家讲这四种⽅法都尝试⼀遍然后选择⼀种适合⾃⼰的即可。下⾯解析实现过程:

1、⾸先新建个test.xml⽂件

Alexia 23

Female

Edward 24 Male

wjm 23

Female

wh 24 Male

2、创建xmlDocument.java

public interface XmlDocument { /**

* 解析XML⽂档 * @param fileName * ⽂件全路径名称 */

public void parserXml(String fileName);}

3、列出四种⽅式的实现dom4j的实现

//dom4j的实现

public class Dom4jTest implements XmlDocument { public void parserXml(String fileName) { File inputXml = new File(fileName);

SAXReader saxReader = new SAXReader();

try {

Document document = saxReader.read(inputXml); Element users = document.getRootElement();

for (Iterator i = users.elementIterator(); i.hasNext();) { Element user = (Element) i.next();

for (Iterator j = user.elementIterator(); j.hasNext();) { Element node = (Element) j.next();

System.out.println(node.getName() + \":\" + node.getText()); }

System.out.println(); }

} catch (DocumentException e) {

System.out.println(e.getMessage()); } }

public static void main(String[] args) { Dom4jTest domj4= new Dom4jTest(); //获取⽂件路径

String path = Dom4jTest.class.getClassLoader().getResource(\"test.xml\").getPath(); System.out.println(path); domj4.parserXml(path); }

dom的实现

//dom的实现

public class DomTest implements XmlDocument {

private Document document;

public void parserXml(String fileName) { try {

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document document = db.parse(fileName); NodeList users = document.getChildNodes();

for (int i = 0; i < users.getLength(); i++) { Node user = users.item(i);

NodeList userInfo = user.getChildNodes(); for (int j = 0; j < userInfo.getLength(); j++) { Node node = userInfo.item(j);

NodeList userMeta = node.getChildNodes();

for (int k = 0; k < userMeta.getLength(); k++) { if(userMeta.item(k).getNodeName() != \"#text\")

System.out.println(userMeta.item(k).getNodeName() + \":\" + userMeta.item(k).getTextContent()); }

System.out.println(); } }

} catch (FileNotFoundException e) { e.printStackTrace();

} catch (ParserConfigurationException e) { e.printStackTrace();

} catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }

public static void main(String[] args) { DomTest domj4= new DomTest(); //获取⽂件路径

String path = Dom4jTest.class.getClassLoader().getResource(\"test.xml\").getPath(); System.out.println(path); domj4.parserXml(path); }}}

sax的实现

//sax的实现

public class SaxTest implements XmlDocument {

public void parserXml(String fileName) {

SAXParserFactory saxfac = SAXParserFactory.newInstance(); try {

SAXParser saxparser = saxfac.newSAXParser(); InputStream is = new FileInputStream(fileName); saxparser.parse(is, new MySAXHandler()); } catch (ParserConfigurationException e) { e.printStackTrace();

} catch (SAXException e) { e.printStackTrace();

} catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }

public static void main(String[] args) { SaxTest saxTest = new SaxTest();

String path = Dom4jTest.class.getClassLoader().getResource(\"test.xml\").getPath(); saxTest.parserXml(path); }}

class MySAXHandler extends DefaultHandler { boolean hasAttribute = false;

Attributes attributes = null;

public void startDocument() throws SAXException { // System.out.println(\"⽂档开始打印了\"); }

public void endDocument() throws SAXException { // System.out.println(\"⽂档打印结束了\"); }

public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if (qName.equals(\"users\")) { return; }

if (qName.equals(\"user\")) { return; }

if (attributes.getLength() > 0) { this.attributes = attributes; this.hasAttribute = true; } }

public void endElement(String uri, String localName, String qName) throws SAXException {

if (hasAttribute && (attributes != null)) {

for (int i = 0; i < attributes.getLength(); i++) {

System.out.print(attributes.getQName(0) + \":\" + attributes.getValue(0)); } } }

public void characters(char[] ch, int start, int length) throws SAXException { System.out.print(new String(ch, start, length)); }}

jdom的实现

//jdom的实现

public class JdomTest implements XmlDocument {

public void parserXml(String fileName) { SAXBuilder builder = new SAXBuilder(); try {

Document document = builder.build(fileName); Element users = document.getRootElement(); List userList = users.getChildren(\"user\"); for (int i = 0; i < userList.size(); i++) {

Element user = (Element) userList.get(i); List userInfo = user.getChildren(); for (int j = 0; j < userInfo.size(); j++) {

System.out.println(((Element) userInfo.get(j)).getName() + \":\" + ((Element) userInfo.get(j)).getValue()); }

System.out.println(); }

} catch (JDOMException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }

}

public static void main(String[] args) { JdomTest jdomTest = new JdomTest();

String path = Dom4jTest.class.getClassLoader().getResource(\"test.xml\").getPath(); jdomTest.parserXml(path); }}

到这⾥,这四种实现⽅式都可以⽤了,个⼈的见解是:推荐使⽤dom4j的⽅式。以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。

因篇幅问题不能全部显示,请点此查看更多更全内容