Java中XML数据


XML解析——Java中XML的四种解析方式

XML是一种通用的数据交换格式,它的平台无关性、语言无关性、系统无关性、给数据集成与交互带来了极大的方便。XML在不同的语言环境中解析方式都是一样的,只不过实现的语法不同而已。

  XML的解析方式分为四种:1DOM解析;2SAX解析;3JDOM解析;4DOM4J解析。其中前两种属于基础方法,是官方提供的平台无关的解析方式;后两种属于扩展方法,它们是在基础的方法上扩展出来的,只适用于java平台。

  针对以下XML文件,会对四种方式进行详细描述:

<?xml version="1.0" encoding="UTF-8"?>

<bookstore>

<book id="1">

<name>冰与火之歌</name>

<author>乔治马丁</author>

<year>2014</year>

<price>89</price>

</book>

<book id="2">

<name>安徒生童话</name>

<year>2004</year>

<price>77</price>

<language>English</language>

</book>

</bookstore>

XML

一、DOM解析

  DOM的全称是Document Object Model,也即文档对象模型。在应用程序中,基于DOMXML分析器将一个XML文档转换成一个对象模型的集合(通常称DOM树),应用程序正是通过对这个对象模型的操作,来实现对XML文档数据的操作。通过DOM接口,应用程序可以在任何时候访问XML文档中的任何一部分数据,因此,这种利用DOM接口的机制也被称作随机访问机制。

  DOM接口提供了一种通过分层对象模型来访问XML文档信息的方式,这些分层对象模型依据XML的文档结构形成了一棵节点树。无论XML文档中所描述的是什么类型的信息,即便是制表数据、项目列表或一个文档,利用DOM所生成的模型都是节点树的形式。也就是说,DOM强制使用树模型来访问XML文档中的信息。由于XML本质上就是一种分层结构,所以这种描述方法是相当有效的。

  DOM树所提供的随机访问方式给应用程序的开发带来了很大的灵活性,它可以任意地控制整个XML文档中的内容。然而,由于DOM分析器把整个XML文档转化成DOM树放在了内存中,因此,当文档比较大或者结构比较复杂时,对内存的需求就比较高。而且,对于结构复杂的树的遍历也是一项耗时的操作。所以,DOM分析器对机器性能的要求比较高,实现效率不十分理想。不过,由于DOM分析器所采用的树结构的思想与XML文档的结构相吻合,同时鉴于随机访问所带来的方便,因此,DOM分析器还是有很广泛的使用价值的。

    优点:

      1、形成了树结构,有助于更好的理解、掌握,且代码容易编写。

      2、解析过程中,树结构保存在内存中,方便修改。

    缺点:

      1、由于文件是一次性读取,所以对内存的耗费比较大。

      2、如果XML文件比较大,容易影响解析性能且可能会造成内存溢出。

  以下是解析代码:

public class DOMTest {

public static void main(String[] args) {

//创建一个DocumentBuilderFactory的对象

DocumentBuilderFactory dbf =
DocumentBuilderFactory.newInstance();

//创建一个DocumentBuilder的对象

try {

//创建DocumentBuilder对象

DocumentBuilder db = dbf.newDocumentBuilder();

//通过DocumentBuilder对象的parser方法加载books.xml文件到当前项目下

Document document = db.parse("books.xml");

//获取所有book节点的集合

NodeList bookList = document.getElementsByTagName("book");

//通过nodelist的getLength()方法可以获取bookList的长度

System.out.println("一共有" + bookList.getLength() + "本书");

//遍历每一个book节点

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

System.out.println("=================下面开始遍历第" + (i + 1) + "本书的内容=================");

//通过 item(i)方法 获取一个book节点,nodelist的索引值从0开始

Node book = bookList.item(i);

//获取book节点的所有属性集合

NamedNodeMap attrs = book.getAttributes();

System.out.println("第 " + (i + 1) + "本书共有" + attrs.getLength() + "个属性");

//遍历book的属性

for (int j = 0; j < attrs.getLength(); j++) {

//通过item(index)方法获取book节点的某一个属性

Node attr = attrs.item(j);

//获取属性名

System.out.print("属性名:" + attr.getNodeName());

//获取属性值

System.out.println("--属性值" + attr.getNodeValue());

}

//解析book节点的子节点

NodeList childNodes = book.getChildNodes();

//遍历childNodes获取每个节点的节点名和节点值

System.out.println("第" + (i+1) + "本书共有" +

childNodes.getLength() + "个子节点");

for (int k = 0; k < childNodes.getLength(); k++) {

//区分出text类型的node以及element类型的node

if (childNodes.item(k).getNodeType() == Node.ELEMENT_NODE) {

//获取了element类型节点的节点名

System.out.print("第" + (k + 1) + "个节点的节点名:"

+ childNodes.item(k).getNodeName());

//获取了element类型节点的节点值

System.out.println("--节点值是:" + childNodes.item(k).getFirstChild().getNodeValue());

//System.out.println("--节点值是:" + childNodes.item(k).getTextContent());

}

}

System.out.println("======================结束遍历第" + (i + 1) + "本书的内容=================");

}

} catch (ParserConfigurationException e) {

e.printStackTrace();

} catch (SAXException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

}

DOM

二、SAX解析

  SAX的全称是Simple APIs for XML,也即XML简单应用程序接口。与DOM不同,SAX提供的访问模式是一种顺序模式,这是一种快速读写XML数据的方式。当使用SAX分析器对XML文档进行分析时,会触发一系列事件,并激活相应的事件处理函数,应用程序通过这些事件处理函数实现对XML文档的访问,因而SAX接口也被称作事件驱动接口。

    优点:

      1、采用事件驱动模式,对内存耗费比较小。

      2、适用于只处理XML文件中的数据时。

    缺点:

      1、编码比较麻烦。

      2、很难同时访问XML文件中的多处不同数据。

  以下是解析代码:

public class SAXTest {

/**

* @param args

*/

public static void main(String[] args) {

//锟斤拷取一锟斤拷SAXParserFactory锟斤拷实锟斤拷

SAXParserFactory factory = SAXParserFactory.newInstance();

//通锟斤拷factory锟斤拷取SAXParser实锟斤拷

try {

SAXParser parser = factory.newSAXParser();

//锟斤拷锟斤拷SAXParserHandler锟斤拷锟斤拷

SAXParserHandler handler = new SAXParserHandler();

parser.parse("books.xml", handler);

System.out.println("~!~!~!共有" + handler.getBookList().size()

+ "本书");

for (Book book : handler.getBookList()) {

System.out.println(book.getId());

System.out.println(book.getName());

System.out.println(book.getAuthor());

System.out.println(book.getYear());

System.out.println(book.getPrice());

System.out.println(book.getLanguage());

System.out.println("----finish----");

}

} catch (ParserConfigurationException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (SAXException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

public class SAXParserHandler extends DefaultHandler {

String value = null;

Book book = null;

private ArrayList<Book> bookList = new ArrayList<Book>();

public ArrayList<Book> getBookList() {

return bookList;

}

int bookIndex = 0;

/**

* 用来标识解析开始

*/

@Override

public void startDocument() throws SAXException {

// TODO Auto-generated method stub

super.startDocument();

System.out.println("SAX解析开始");

}

/**

* 用来标识解析结束

*/

@Override

public void endDocument() throws SAXException {

// TODO Auto-generated method stub

super.endDocument();

System.out.println("SAX解析结束");

}

/**

* 解析xml元素

*/

@Override

public void startElement(String uri, String localName, String qName,

Attributes attributes) throws SAXException {

//调用DefaultHandler类的startElement方法

super.startElement(uri, localName, qName, attributes);

if (qName.equals("book")) {

bookIndex++;

//创建一个book对象

book = new Book();

//开始解析book元素的属性

System.out.println("======================开始遍历某一本书的内容=================");

//不知道book元素下属性的名称以及个数,如何获取属性名以及属性值

int num = attributes.getLength();

for(int i = 0; i < num; i++){

System.out.print("book元素的第" + (i + 1) +  "个属性名是:"

+ attributes.getQName(i));

System.out.println("---属性值是:" + attributes.getValue(i));

if (attributes.getQName(i).equals("id")) {

book.setId(attributes.getValue(i));

}

}

}

else if (!qName.equals("name") && !qName.equals("bookstore")) {

System.out.print("节点名是:" + qName + "---");

}

}

@Override

public void endElement(String uri, String localName, String qName)

throws SAXException {

//调用DefaultHandler类的endElement方法

super.endElement(uri, localName, qName);

//判断是否针对一本书已经遍历结束

if (qName.equals("book")) {

bookList.add(book);

book = null;

System.out.println("======================结束遍历某一本书的内容=================");

}

else if (qName.equals("name")) {

book.setName(value);

}

else if (qName.equals("author")) {

book.setAuthor(value);

}

else if (qName.equals("year")) {

book.setYear(value);

}

else if (qName.equals("price")) {

book.setPrice(value);

}

else if (qName.equals("language")) {

book.setLanguage(value);

}

}

@Override

public void characters(char[] ch, int start, int length)

throws SAXException {

// TODO Auto-generated method stub

super.characters(ch, start, length);

value = new String(ch, start, length);

if (!value.trim().equals("")) {

System.out.println("节点值是:" + value);

}

}

}

SAX

 三、JDOM解析

    特征:

      1、仅使用具体类,而不使用接口。

      2API大量使用了Collections类。

  以下是解析代码:

public class JDOMTest {

private static ArrayList<Book> booksList = new ArrayList<Book>();

/**

* @param args

*/

public static void main(String[] args) {

// 进行对books.xml文件的JDOM解析

// 准备工作

// 1.创建一个SAXBuilder的对象

SAXBuilder saxBuilder = new SAXBuilder();

InputStream in;

try {

// 2.创建一个输入流,将xml文件加载到输入流中

in = new FileInputStream("src/res/books.xml");

InputStreamReader isr = new InputStreamReader(in, "UTF-8");

// 3.通过saxBuilder的build方法,将输入流加载到saxBuilder中

Document document = saxBuilder.build(isr);

// 4.通过document对象获取xml文件的根节点

Element rootElement = document.getRootElement();

// 5.获取根节点下的子节点的List集合

List<Element> bookList = rootElement.getChildren();

// 继续进行解析

for (Element book : bookList) {

Book bookEntity = new Book();

System.out.println("======开始解析第" + (bookList.indexOf(book) + 1)

+ "书======");

// 解析book的属性集合

List<Attribute> attrList = book.getAttributes();

// //知道节点下属性名称时,获取节点值

// book.getAttributeValue("id");

// 遍历attrList(针对不清楚book节点下属性的名字及数量)

for (Attribute attr : attrList) {

// 获取属性名

String attrName = attr.getName();

// 获取属性值

String attrValue = attr.getValue();

System.out.println("属性名:" + attrName + "----属性值:"

+ attrValue);

if (attrName.equals("id")) {

bookEntity.setId(attrValue);

}

}

// 对book节点的子节点的节点名以及节点值的遍历

List<Element> bookChilds = book.getChildren();

for (Element child : bookChilds) {

System.out.println("节点名:" + child.getName() + "----节点值:"

+ child.getValue());

if (child.getName().equals("name")) {

bookEntity.setName(child.getValue());

}

else if (child.getName().equals("author")) {

bookEntity.setAuthor(child.getValue());

}

else if (child.getName().equals("year")) {

bookEntity.setYear(child.getValue());

}

else if (child.getName().equals("price")) {

bookEntity.setPrice(child.getValue());

}

else if (child.getName().equals("language")) {

bookEntity.setLanguage(child.getValue());

}

}

System.out.println("======结束解析第" + (bookList.indexOf(book) + 1)

+ "书======");

booksList.add(bookEntity);

bookEntity = null;

System.out.println(booksList.size());

System.out.println(booksList.get(0).getId());

System.out.println(booksList.get(0).getName());

}

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (JDOMException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

}

JDOM

4DOM4J解析

     特征:

      1JDOM的一种智能分支,它合并了许多超出基本XML文档表示的功能。

      2、它使用接口和抽象基本类方法。

      3、具有性能优异、灵活性好、功能强大和极端易用的特点。

      4、是一个开放源码的文件

  以下是解析代码:

public class DOM4JTest {

private static ArrayList<Book> bookList = new ArrayList<Book>();

/**

* @param args

*/

public static void main(String[] args) {

// 解析books.xml文件

// 创建SAXReader的对象reader

SAXReader reader = new SAXReader();

try {

// 通过reader对象的read方法加载books.xml文件,获取docuemnt对象。

Document document = reader.read(new File("src/res/books.xml"));

// 通过document对象获取根节点bookstore

Element bookStore = document.getRootElement();

// 通过element对象的elementIterator方法获取迭代器

Iterator it = bookStore.elementIterator();

// 遍历迭代器,获取根节点中的信息(书籍)

while (it.hasNext()) {

System.out.println("=====开始遍历某一本书=====");

Element book = (Element) it.next();

// 获取book的属性名以及 属性值

List<Attribute> bookAttrs = book.attributes();

for (Attribute attr : bookAttrs) {

System.out.println("属性名:" + attr.getName() + "--属性值:"

+ attr.getValue());

}

Iterator itt = book.elementIterator();

while (itt.hasNext()) {

Element bookChild = (Element) itt.next();

System.out.println("节点名:" + bookChild.getName() + "--节点值:" + bookChild.getStringValue());

}

System.out.println("=====结束遍历某一本书=====");

}

} catch (DocumentException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

DOM4J

Final:比较总结

  DOM4J性能最好,连SunJAXM也在用DOM4J。目前许多开源项目中大量采用DOM4J,例如大名鼎鼎的Hibernate也用DOM4J来读取XML配置文件。如果不考虑可移植性,那就采用DOM4J
      JDOMDOM在性能测试时表现不佳,在测试10M文档时内存溢出。在小文档情况下还值得考虑使用DOMJDOM。虽然JDOM的开发者已经说明他们期望在正式发行版前专注性能问题,但是从性能观点来看,它确实没有值得推荐之处。另外,DOM仍是一个非常好的选择。DOM实现广泛应用于多种编程语言。它还是许多其它与XML相关的标准的基础,因为它正式获得W3C推荐(与基于非标准的Java模型相对),所以在某些类型的项目中可能也需要它(如在JavaScript中使用DOM)。
      SAX表现较好,这要依赖于它特定的解析方式-事件驱动。一个SAX检测即将到来的XML流,但并没有载入到内存(当然当XML流被读入时,会有部分文档暂时隐藏在内存中)。

Java中XML数据的更多相关文章

  1. 第70节:Java中xml和tomcat

    第70节:Java中xml和tomcat 前言: 哭着也要看完,字数: jdbc crud - statement dao java.sql.Driver The interface that eve ...

  2. Java中XML格式的字符串4读取方式的简单比较

    Java中XML格式的字符串4读取方式的简单比较 1.java自带的DOM解析. import java.io.StringReader; import javax.xml.parsers.Docum ...

  3. Java中静态数据的初始化顺序

    Java的类中的数据成员中包含有静态成员(static)时,静态数据成员的初始化顺序是怎样的呢? [程序实例1] import java.util.*; import java.lang.*; imp ...

  4. Java中浮点型数据Float和Double进行精确计算的问题

    Java中浮点型数据Float和Double进行精确计算的问题 来源  https://www.cnblogs.com/banxian/p/3781130.html 一.浮点计算中发生精度丢失     ...

  5. XML解析——Java中XML的四种解析方式

    XML是一种通用的数据交换格式,它的平台无关性.语言无关性.系统无关性.给数据集成与交互带来了极大的方便.XML在不同的语言环境中解析方式都是一样的,只不过实现的语法不同而已. XML的解析方式分为四 ...

  6. JAVA中 XML与数据库互转 学习笔记三

    要求 必备知识 JAVA基础知识,XML基础知识,数据库的基本操作. 开发环境 MyEclipse10/MySql5.5 资料下载 源码下载   数据库在数据查询,修改,保存,安全等方面与其他数据处理 ...

  7. 使用Java创建XML数据

    ------------siwuxie095                         工程名:TestCreateXML 包名:com.siwuxie095.xml 类名:CreateXML. ...

  8. 使用Java读取XML数据

    ---------------siwuxie095 工程名:TestReadXML 包名:com.siwuxie095.xml 类名:ReadXML.java 打开资源管理器,在工程 TestRead ...

  9. XML解析——Java中XML的四种解析方式(转载 by 龍清扬)

    XML是一种通用的数据交换格式,它的平台无关性.语言无关性.系统无关性.给数据集成与交互带来了极大的方便.XML在不同的语言环境中解析方式都是一样的,只不过实现的语法不同而已. XML的解析方式分为四 ...

随机推荐

  1. 关于Doctype、严格模式与混杂模式

    <!Doctype> 文档声明,位于文档中的最前面的位置,处于<html>标签之前.此标签告知浏览器文档使用哪种HTML或XHTML规范. 用于告知浏览器以何种模式来渲染文档. ...

  2. MFC ListControl技巧汇总

    转自:http://hi.baidu.com/qi_xian/blog/item/1971aa22da89ada24723e856.html 以下未经说明,listctrl默认view 风格为repo ...

  3. Lexer and parser generators (ocamllex, ocamlyacc)

    Chapter 12 Lexer and parser generators (ocamllex, ocamlyacc) This chapter describes two program gene ...

  4. 2011–2012, Northern Subregional J. John’s Inversions

    考虑某一种状态,无论如何调整卡片位置,都不会减少逆序对数量,这就是我们要找的最优解. 显然在对于一个颜色的数字有序时,达到了上述状态. 于是,我们根据一个颜色的值排序后再计算逆序对就得到了答案. #i ...

  5. jQuery EasyUI,LinkButton(按钮)组件

    转自:https://www.cnblogs.com/adc8868/p/6639570.html jQuery EasyUI,LinkButton(按钮)组件 学习要点: 1.加载方式 2.属性列表 ...

  6. E20170602-ts

    questionnaire  n. 调查问卷; 调查表;  アンケート不是英语 collection   n. 征收; 收集,采集; 收藏品; 募捐; association   n. 联想; 协会, ...

  7. bzoj1085骑士精神(搜索)

    1085: [SCOI2005]骑士精神 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1893  Solved: 1051 Description ...

  8. ADSI和其他内容

    ADSI (Active Directory Services Interface)是Microsoft推出的一项技术,它统一了许多底层服务的编程接口,程序员可以使用一致的对象技术来访问这些底层服务. ...

  9. 牛客练习赛17-A-长方体

    题目描述 给出共享长方体一个顶点的三个面的面积,求它十二条边的边长和. 输入描述: 一行三个整数a, b, c表示面积(1 <= a, b, c <= 10000). 输出描述: 一行一个 ...

  10. docker血一样的教训,生成容器的时候一定要设置数据卷,把数据文件目录,配置文件目录,日志文件目录都要映射到宿主机上保存啊!!!

    打个比方,比如mysql,如果你想重新设置一下mysql的配置,不小心配错里,启动容器失败,已启动就停止了. 根本进不去mysql的容器里.如果之前run容器的时候,没有把数据文件,日志文件,配置文件 ...