XML解析技术主要有三种:

(1)DOM(Document Object Model)文档对象模型:是 W3C 组织推荐的解析XML 的一种方式,即官方的XML解析技术。

(2)SAX(Simple Api for XML)产生自 XML 社区,几乎所有的 XML 解析器都支持它。

(3)StAX(Stream Api for XML)一种拉模式处理XML文档的API。

DOM解析技术

DOM解析XML的做法是将整个XML 加载内存中,形成以树形结构存储的文档对象,所有对XML的操作都对内存中文档对象进行。

DOM解析的特点是要将整个XML文档加载到内存中,若文档比较大,则会占用很大的内存空间,但是由于整个文档都在内存中,可以方便地进行修改回写操作。

SAX解析技术

当XML 文档非常大时,将整个文档加载到内存中进行解析,可能会造成内存溢出,而且很多时候只是对文档中的部分节点进行操作,加载整个文档会导致工作效率的低下。SAX的思想是一边解析XML,然后对解析的部分进行相关处理,然后释放已处理完成的部分所占用的内存资源。SAX是一种推模式XML解析方式,由服务端主导,向客户端推送数据。

StAX解析技术

基本同SAX,不同之处在于,StAX是一种拉模式的XML解析技术,由客户端主导,从服务端拉取要解析的数据。Android系统中内置使用该种方式解析XML。

SAX与StAX的相同之处在于:相比DOM是一种更为轻量级的方案,采用串行方法读取 --- 文件输入流(字节、字符)读取,但是会导致编程较为复杂,且无法在读取过程中修改XML数据。

常见的XML解析开发包

JAXP 是sun官方推出实现技术,同时支持DOM、 SAX、 StAX。

DOM4j 是开源社区开源框架,支持DOM解析方式。

XML PULL是 Android 移动设备内置xml 解析技术,支持StAX解析方式。

XML的DOM解析方式

直接使用JDK自带的JAXP进行xml解析,所用到的相关类都存放在以下几个包中:

javax.xml.parsers  存放 DOM 和 SAX 解析器

javax.xml.stream  存放 STAX 解析相关类

org.w3c.dom 存放DOM解析时的数据节点类

org.xml.sax 存放SAX解析相关工具类

(一)加载解析XML文档

要解析一个XML文档,首先需要加载该文档

javax.xml.parsers中的DocumentBuilderFactory工厂类可以获取生成 DOM 对象树的解析器。

获得该类实例的方法是,调用该类的newInstance()方法。之后通过调用工厂类对象的newDocumentBuilder()方法便可以获取了DocumentBuilder这个DOM的XML解析器。

调用DocumentBuilder的parse()方法,便可以将XML文件解析为Document对象。

如:新建一个DomXmlParser类,添加一个loadFromFile方法:

 public class DomXmlParser {

          public static Document loadFromFile(String filename) throws Exception{

                    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

                    DocumentBuilder builder = factory.newDocumentBuilder();

                    Document document = builder.parse(filename);

                    return document;

          }

 }

注意,Document导包时,一定要是org.w3c.dom。

Document 接口表示整个 HTML 或 XML 文档。从概念上讲,它是文档树的根,并提供对文档数据的基本访问。

常用方法:

NodeList getElementsByTagName(String tagname):按文档顺序返回包含在文档中且具有给定标记名称的所有Element的NodeList。

Element getElementById(String elementId):返回具有带给定值的 ID 属性的 Element。注意,该方法只有在XML文档具有约束时才可以使用,所以一般没有带有约束的不会用到该方法。

NodeList 接口提供对节点的有序集合的抽象,没有定义或约束如何实现此集合。DOM 中的 NodeList 对象是活动的,删除某个元素时,会导致后续元素向前移动,即下标减一。NodeList 中的项可以通过从 0 开始的整数索引进行访问。

常用方法:

int getLength()列表中的节点数。

Node item(int index)返回集合中的第 index 个元素。

Node 接口是整个文档对象模型的主要数据类型。它表示该文档树中的单个节点。

几个主要的子接口:

Document:上面已然提到

Element:表示 HTML 或 XML 文档中的一个元素。

Attr :表示 Element 对象中的属性。

Text :并且表示 Element 或 Attr 的文本内容(在 XML 中称为字符数据)。

Comment:表示注释的内容

如有下面xml文档:

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

 <students>

     <student id="001">

         <name>zhangsan</name>

         <gender>male</gender>

         <age>23</age>

     </student>

     <student id="002">

         <name>lisi</name>

         <gender>male</gender>

         <age>24</age>

     </student>

     <student id="003">

         <name>xiaoqiao</name>

         <gender>female</gender>

         <age>18</age>

     </student>

     <student id="004">

         <name>diaochan</name>

         <gender>female</gender>

         <age>23</age>

     </student>

 </students>

各个节点的类型就是Element,节点的属性id就是Attr,节点中的值如femal、lisi等就是Text。

Node接口中提供了获取Node各种属性的方法,以及通过相对位置获取其他Node的方法,具体可以查看API帮助手册。

常用的有这么几个:

NodeList getChildNodes():包含此节点的所有子节点的 NodeList。

Node getFirstChild()此节点的第一个子节点。

Node getLastChild()此节点的最后一个节点。

Node getNextSibling()直接在此节点之后的节点。

Node getParentNode()此节点的父节点。

Node getPreviousSibling()直接在此节点之前的节点。

String getTextContent()此属性返回此节点及其后代的文本内容。

如,要输出所有学生的姓名:

DomXmlParser类:

 public class DomXmlParser {

          protected static Document document = null;

          public static Document loadFromFile(String filename) throws Exception{

                    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

                    DocumentBuilder builder = factory.newDocumentBuilder();

                    document = builder.parse(filename);

                    return document;

          }

 }

StudentParser类:

 public class StudentParser extends DomXmlParser {

          public static String[] getAllNames(){

                    NodeList students = document.getElementsByTagName("student");

                    String[] names = new String[students.getLength()];

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

                             Element stu = (Element) students.item(i);

                             names[i] = stu.getChildNodes().item(1).getTextContent();

                    }

                    return names;

          }

 }

getChildNodes()方法用于获取所有的子元素,返回一个NodeList对象。

如果对当前xml文档中的每一个student节点调用该方法获取子元素,会发现返回的NodeList中元素数目为7。

 <student id="001">

         <name>zhangsan</name>

         <gender>male</gender>

         <age>23</age>

 </student>

这是因为:每个回车换行被当做Text节点。一个student节点有4个回车换行节点以及<name>、<gender>、<age>这3个Element节点,所以总共有7个节点。

而对于<name>节点来说,则只有一个子节点,该节点是Text节点。

(二)修改回写

当完成了对XML的相关处理工作后,可以将修改写回到xml文档中,与加载解析相似,回写也需要相应的工厂类,相应的转换类。

 //获取Transformer工厂类实例

 TransformerFactory transformerFactory = TransformerFactory.newInstance();

 //通过工厂类获取Transformer实例

 Transformer transformer = transformerFactory.newTransformer();

 //选择要回写的内存中的document对象

 DOMSource domSource = new DOMSource(document);

 //要回写的目标文件

 StreamResult result = new StreamResult(new File("students_bak.xml"));

 //将内存DOM对象回写到文件中

 transformer.transform(domSource, result);

例如:

在DomXmlParser类中添加方法:

 public static boolean saveAs(String filename) throws Exception{

                    TransformerFactory factory = TransformerFactory.newInstance();

                    transformer = factory.newTransformer();

                    DOMSource source = new DOMSource(document);

                    StreamResult target = new StreamResult(new File(filename));

                    transformer.transform(source, target);

                    return true;

 }

调用:

 public static void main(String[] args) {

                    // TODO Auto-generated method stub

                    try {

                             StudentParser.loadFromFile("students.xml");

                             String[] names = StudentParser.getAllNames();

                             for (int i = 0; i < names.length; i++) {

                                      System.out.println(names[i]);

                             }

                             StudentParser.saveAs("students_bak.xml");

                    } catch (Exception e) {

                             // TODO Auto-generated catch block

                             e.printStackTrace();

                    }

 }

使用DOM解析XML实现完整的增删改查操作示例:

首先需要一个Student类:

 package cn.csc.bean;

 public class Student {

          private String id = null;

          private String name = null;

          private String gender = null;

          private int age = 0;

          public String getId() {

                    return id;

          }

          public void setId(String id) {

                    this.id = id;

          }

          public String getName() {

                    return name;

          }

          public void setName(String name) {

                    this.name = name;

          }

          public String getGender() {

                    return gender;

          }

          public void setGender(String gender) {

                    this.gender = gender;

          }

          public int getAge() {

                    return age;

          }

          public void setAge(int age) {

                    this.age = age;

          }

          public Student(String id, String name, String gender, int age) {

                    super();

                    this.id = id;

                    this.name = name;

                    this.gender = gender;

                    this.age = age;

          }

          public Student() {

                    super();

          }

          public String toString() {

                    return "[id:"+id+",name:"+name+",gender:"+gender+",age"+age+"]";

          }
}

1)通过id获取学生信息:

在StudentParser类中添加getStudentById(String id)方法:

 public static Student getStudentById(String id){

                    Student student = null;

                    NodeList students = document.getElementsByTagName("student");

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

                             Element stu = (Element) students.item(i);

                             if(stu.getAttribute("id").equals(id)){

                                      student = new Student();

                                      student.setName(((Element)stu.getElementsByTagName("name").item(0)).getTextContent());

                                      student.setGender(((Element)stu.getElementsByTagName("gender").item(0)).getTextContent());

                                      String age = ((Element)stu.getElementsByTagName("age").item(0)).getTextContent();

                                      student.setAge(Integer.parseInt(age));

                                      student.setId(id);

                                      return student;

                             }

                    }

                    return student;

 }

调用该方法:

 StudentParser.loadFromFile("students.xml");

 System.out.println(StudentParser.getStudentById("001"));

输出结果:

[id:001,name:zhangsan,gender:male,age23]

2)通过性别查找学生:

在StudentParser类中添加getStudentsByGender(String gender)方法:

 public static List<Student> getStudentsByGender(String gender){

                    List<Student> stus = new ArrayList<Student>();

                    Student tmp = null;

                    NodeList students = document.getElementsByTagName("student");

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

                             Element stu = (Element) students.item(i);

                             Element gen = (Element)stu.getElementsByTagName("gender").item(0);

                             if(gen.getTextContent().equals(gender)){

                                      tmp = new Student();

                                      tmp.setGender(gender);

                                      Element name = (Element) gen.getPreviousSibling().getPreviousSibling();

                                      tmp.setName(name.getTextContent());

                                      Element age = (Element) gen.getNextSibling().getNextSibling();

                                      tmp.setAge(Integer.parseInt(age.getTextContent()));

                                      tmp.setId(stu.getAttribute("id"));

                                      stus.add(tmp);

                             }

                    }

                    return stus;

 }

注意:回车换行作为Text节点的问题是上面连着调用两次getNextSibling()和getPreviousSibling()的原因所在。

调用:

 StudentParser.loadFromFile("students.xml");

 List<Student> students = StudentParser.getStudentsByGender("female");

 for (int i = 0; i < students.size(); i++) {

          System.out.println(students.get(i));

 }

输出结果:

[id:003,name:xiaoqiao,gender:female,age18]

[id:004,name:diaochan,gender:female,age23]

3)添加一条学生信息:

 public static boolean insert(Student stu){

                    Element root = (Element) document.getElementsByTagName("students").item(0);

                    Element student = document.createElement("student");

                    student.setAttribute("id", stu.getId());

                    Element name = document.createElement("name");

                    name.setTextContent(stu.getName());

                    Element gender = document.createElement("gender");

                    gender.setTextContent(stu.getGender());

                    Element age = document.createElement("age");

                    age.setTextContent(stu.getAge()+"");

                    student.appendChild(name);

                    student.appendChild(gender);

                    student.appendChild(age);

                    root.appendChild(student);

                    try {

                             saveAs("students.xml");

                    } catch (Exception e) {

                             // TODO Auto-generated catch block

                             e.printStackTrace();

                             return false;

                    }

                    return true;

 }

添加之后,一定要记得回写。

调用:

 StudentParser.loadFromFile("students.xml");

 StudentParser.insert(new Student("005","dqrcsc","male",25));

4)根据id修改学生信息:

 public static boolean update(String id, Student stu){

                    NodeList stus = document.getElementsByTagName("student");

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

                             Element tmp = (Element) stus.item(i);

                             if(tmp.getAttribute("id").equals(id)){

                                      tmp.setAttribute("id", stu.getId());

                                      tmp.getChildNodes().item(1).setTextContent(stu.getName());

                                      tmp.getChildNodes().item(3).setTextContent(stu.getGender());

                                      tmp.getChildNodes().item(5).setTextContent(stu.getAge()+"");

                                      try {

                                                saveAs("students.xml");

                                      } catch (Exception e) {

                                                // TODO Auto-generated catch block

                                                e.printStackTrace();

                                                return false;

                                      }

                                      return true;

                             }

                    }

                    return false;

 }

调用:

 StudentParser.update("001", new Student("000","zhangsan22","female",26));

5)根据年龄删除学生信息:

 public static int deleteStudentsOlderThan(int age){

                    int cnt = 0;

                    NodeList stus = document.getElementsByTagName("student");

                    Element root = document.getDocumentElement();

                    for(int i = stus.getLength()-1; i>=0; i--){

                             Element tmp = (Element) stus.item(i);

                             String str = tmp.getChildNodes().item(5).getTextContent();

                             int a = Integer.parseInt(str);

                             if(a>=age){

                                      root.removeChild(tmp);

                                      cnt++;

                             }

                    }

                    try {

                             saveAs("students_bak.xml");

                    } catch (Exception e) {

                             // TODO Auto-generated catch block

                             e.printStackTrace();

                    }

                    return cnt;

 }

调用:

 System.out.println(StudentParser.deleteStudentsOlderThan(22));

java拾遗1----XML解析(一) DOM解析的更多相关文章

  1. JAVA企业级开发-xml基础语法&约束&解析(04)

    一.什么是xml html:超文本标记语言.它主要是用来封装页面上要显示的数据,最后通过浏览器来解析html文件,然后把数据展示在浏览器上.同样我们可以使用JS和DOM技术对html文件进行解析和操作 ...

  2. Java---XML的解析(1)-DOM解析

    本章只讲DOM解析.接下来还会学习Dom4j和StAX 解析技术 DOM解析: DOM解析一次将所有的元素全部加载到内存中:如有以下XML文档: <user> <name>Ja ...

  3. Java从零开始学四十二(DOM解析XML)

    一.DOM解析XML xml文件 favorite.xml <?xml version="1.0" encoding="UTF-8" standalone ...

  4. Java解析XML文档——dom解析xml

    一.前言 用Java解析XML文档,最常用的有两种方法:使用基于事件的XML简单API(Simple API for XML)称为SAX和基于树和节点的文档对象模型(Document Object M ...

  5. [Java拾遗一] XML的书写规范与解析.

    前言今天天气大好, 起了个大早开始总结一些常用的基础知识. XML一直来说都很陌生, 使用大多是用于配置文件, 之前并没有细究过其中的约束规范, 今天刚好没事来学习并总结下. 1,XML基础介绍 XM ...

  6. XML解析之DOM解析技术案例

    Java代码: package com.xushouwei.xml; import java.io.File; import javax.xml.parsers.DocumentBuilder; im ...

  7. xml的SAX解析和dom解析的区别

    一,区别 DOM解析 SAX解析 原理: 一次性加载xml文档,不适合大容量的文件读取 原理: 加载一点,读取一点,处理一点.适合大容量文件的读取 DOM解析可以任意进行增删改成 SAX解析只能读取 ...

  8. xml解析之----DOM解析

    DOM模型(documentobject model) •DOM解析器在解析XML文档时,会把文档中的全部元素.依照其出现的层次关系.解析成一个个Node对象(节点). •在dom中.节点之间关系例如 ...

  9. XML文件解析之DOM解析

    XML文件是一种通用的数据交换格式,它的平台无关性,语言无关性,系统无关性,给数据集成与交互带来了极大的方便.基本的解析方式包括DOM解析和SAX解析,具体来说包括DOM解析,SAX解析,DOM4J解 ...

随机推荐

  1. CMAKE 编译报错

    报错如下: CMake Error: your C compiler: "CMAKE_C_COMPILER-NOTFOUND" was not found. 没有安装 gcc 和 ...

  2. autocomplete属性在谷歌浏览器不起作用

    大家都知道autocomplete属性是表单字段中的HTML5新属性,该属性有两种状态值,分别为"on" 和 "off",该属性可省略:省略属性值后默认值为&q ...

  3. 对checkpoint not completed的理解

    如果数据库存在两个日志组log1和log2,首先.-->log1-->log2-->log1,此时(log2切换到log1)触发checkpoint.该checkpoint will ...

  4. Python全栈之路--Django ORM详解

    ORM:(在django中,根据代码中的类自动生成数据库的表也叫--code first) ORM:Object Relational Mapping(关系对象映射) 我们写的类表示数据库中的表 我们 ...

  5. Android监听HOME键的最简单的方法

    public static final int FLAG_HOMEKEY_DISPATCHED = 0x80000000; public void onCreate(Bundle savedInsta ...

  6. 将apache添加到服务

    拿apache为例 1.将应用程序放在PATH的任一个目录下,一般放在/usr/sbin/.执行下面命令 cp /usr/local/apache2/bin/httpd /usr/sbin/httpd ...

  7. Android RxJava使用介绍(四) RxJava的操作符

    本篇文章继续介绍下面类型的操作符 Combining Observables(Observable的组合操作符) Error Handling Operators(Observable的错误处理操作符 ...

  8. view无限旋转

    - (void) showRefreshAnimation { [UIView animateWithDuration: options:UIViewAnimationOptionCurveLinea ...

  9. ASP.NET中的配置文件

    ASP.NET中的配置文件 原创 2014年10月13日 08:15:27 1199   在机房收费系统的时候曾经应用过配置文件,当时也就那么一用对配置文件了解的不是很透彻,下面就来总结一下有关配置文 ...

  10. 自动化测试 python2.7 与 selenium 2 学习

    windows环境搭建 # 下载 python[python 开发环境] http://python.org/getit/ # 下载 setuptools [python 的基础包工具]setupto ...