DOM解析手册

编程

JAVA解析XML手册

XML文档以层级标签的形式来组织数据,多用于配置文件、存储静态数据、交换数据。

XML文档解析

首先我们要知道,“XML中的内容都是结点”,这句话的意思是:XML文档中,无论是 <> </> 符号的里面的内容(属性)、之间的内容(结点值)、还是 <> 本身(结点),都是Node,就连标签之间的换行、空格都是一个节点。明白这个很重要,因为下面遍历结点时,返回的 属性名值对 、结点值内容、结点本身 都是一个Node类型。

实例

解析下面的XML文档

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

<users>

   <user userId="1001" idcard="370826199001133290">

       <name>张三</name>

       <address>广州</address>

       <age>18</age>

   </user>

   <user userId="1002" idcard="370826199001133291">

       <name>李四</name>

       <address>大连</address>

       <age>19</age>

   </user>

   <user userId="1003" idcard="370826199001133292">

       <name>王五</name>

       <address>广州</address>

       <age>20</age>

   </user>

   <user userId="1004" idcard="370826199001133293">

       <age>21</age>

       <address>广州</address>

       <name>冯六</name>

   </user>

</users>

DOM解析

DOM是html和xml的应用程序接口(API),以层次结构(类似于树型)来组织节点和信息片段,映射XML文档的结构,允许获取和操作文档的任意部分,是W3C的官方标准

原理

首先在内存中创建一个Document对象,然后把XML文档读取进来赋值给这个dom对象。由于dom对象是基于树结构的,所以对dom对象进行遍历即可。对内存中的dom对象可以进行查询、修改、删除操作,还可以写回原XML文档保存修改。

【优点】 ①允许应用程序对数据和结构做出更改。 ②访问是双向的,可以在任何时候在树中上下导航,获取和操作任意部分的数据。 【缺点】 ①整个文档必须一次性解析完。

②由于整个文档都需要载入内存,对于大文档成本高。

DOM解析详解

操作步骤:

1:创建DocumentBuilderFactory,由newInstance()方法获取工厂实例;

2:由工厂创建DocumentBuilder;

3:通过 Document dom=builder.parse(file); 读取xml文档创建dom对象;

4:通过dom对象的一系列方法获取某个结点、某名字的结点列表:

Element getElementById(String elementId) 

        返回具有带给定值的 ID 属性的 Element。

NodeList getElementsByTagName(String tagname)

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

5:通过NodeList对象获取结点列表中某个结点:

Node item(int index) 

        返回集合中的第 index 个项。

6:通过Node对象读取结点属性:

NamedNodeMap getAttributes() 

        包含此节点的属性的 NamedNodeMap(如果它是 Element);否则为 null。

然后对NamedNodeMap对象调用以下方法获取属性:(前面我们说过,属性也是结点)

Node  getNamedItem(String name) 

        检索通过名称指定的节点。

    或

Node item(int index)

        返回映射中第 index 个项。

最后,对返回的属性通过以下方法获取名、值:(属性也是结点)

String getNodeName() 

        此节点的名称,取决于其类型;

String getNodeValue()

        此节点的值,取决于其类型;

7:获取结点的子节点列表:

NodeList getChildNodes() 

        包含此节点的所有子节点的 NodeList。

8:获取结点值:

String getNodeName() 

        此节点的名称,取决于其类型;

String getNodeValue()

        此节点的值,取决于其类型;

总结:DOM方法解析XML文档,把元素、元素属性、元素值都看作Node类型,通过node.getNodeName()获取元素名、属性名, 通过getNodeValue()获取属性值、元素值,通过getChildNodes()获取子节点们,通过item(i)获取第i个属性或者第i个子节点。

DOM解析代码实例

构造Document对象:

   /**

    * 构建Document对象

    * @param xmlPath

    * @return

    */

   private static Document buildDocument(String xmlPath){

       try {

           DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();

           DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();

           InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(xmlPath);

           return documentBuilder.parse(inputStream);

      } catch (Exception e) {

           System.out.println(e);

      }

       return null;

  }

遍历DOM对象

Document:   XML文档对象,由解析器获取

NodeList: 节点数组

Node: 节点(包括element、#text)

Element: 元素,可用于获取属性参数

DOM解析完整代码示例

package com.demo;

import org.w3c.dom.Document;

import org.w3c.dom.Element;

import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

import javax.xml.parsers.ParserConfigurationException;

import java.io.File;

import java.io.IOException;

import java.io.InputStream;

import java.net.URL;

public class DomDemo {

  public static void main(String[] args) {

      try {

          find();

      } catch (Exception e) {

          System.out.println(e);

      }

  }

  private static User find() throws Exception {

      Document document = buildDocument("users.xml");

      NodeList list = document.getElementsByTagName("user");

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

          Element element = (Element) list.item(i);

          User student = new User();

          student.setUserId(Long.parseLong(element.getAttribute("userId")));

          student.setIdCard(element.getAttribute("idcard"));

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

          student.setAddress(element.getElementsByTagName("address").item(0).getTextContent());

          student.setAge(element.getElementsByTagName("age").item(0).getTextContent());

          System.out.println(student);

      }

      return null;

  }

  /**

    * 构建Document对象

    * @param xmlPath

    * @return

    */

  private static Document buildDocument(String xmlPath){

      try {

          DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();

          DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();

          InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(xmlPath);

          return documentBuilder.parse(inputStream);

      } catch (Exception e) {

          System.out.println(e);

      }

      return null;

  }

}

SAX(Simple API for XML)解析

流模型中的"推"模型分析方式。通过事件驱动,每发现一个节点就引发一个事件,事件推给事件处理器,通过回调方法完成解析工作,解析XML文档的逻辑需要应用程序完成

原理

通过parse(file,listener)函数用一个listener对xml文件进行查找,按顺序读取文档,遍历每个标签,当发现目标标签时,读取标签的属性、结点值等信息并返回。

【优势】 ①无需将整个xml文档载入内存,因此消耗内存少。 ②只在读取数据时检查数据,不需要保存在内存中。 ③可以在某个条件得到满足时停止解析,不必解析整个文档。 ④效率和性能较高,能解析大于系统内存的文档。 【缺点】 ①不能随机的访问xml中的节点。 ②单向导航,无法定位文档层次,很难同时访问同一文档的不同部分数据,不支持XPath。 ③不能修改文档。

SAX解析详解

操作步骤:

1:创建解析工厂:SAXParserFactory factory = SAXParserFactory.newInstance();

2:由工厂创建解析器:SAXParser parser = factory.newSAXParser();

3:通过解析器的parse()方法,对指定xml文档以指定handler之类进行解析查询:parser.parse(xmlFile, new MySaxListener());

我们要继承DefaultHandler类,定义相应的查询操作类:

1:重写父类中的文档开始方法、文档结束方法,定义开始、结束遍历xml文档时的操作:

void startDocument() 

        接收文档开始的通知。

void endDocument()

        接收文档结束的通知。

2:重写父类的标签开始方法、标签结束方法,定义遍历到一个开始、结束标签时的操作:

void startElement(String uri, String localName, String qName, Attributes attributes) //参数qName是标签名、attributes是属性列表

        接收元素开始的通知。

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

        接收元素结束的通知。

3:重写**characters**(char[] ch, int start, int length)方法:

   // 对事件发生时,元素的字符怎么处理  

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

      //参数ch是当上述4中事件随便一个发生时,对应的元素的值,值在ch中start开始,length长。从头到尾遍历整个xml文档时,每个标签的值依次被存入ch中。

}

总结:

也就是说,通过SAX解析xml文档是没有dom对象出现的,所以不会有node,不会有getNodeName()、getNodeValue()获取结点名、值。 总结:SAX解析XML文档的结点名是通过事件函数的参数qName获取的,属性是通过参数attributes的getValue("属性名")获取的, 结点值是通过当前事件函数发生时,characters(char[] ch, int start, int length)方法中的内容获取的。

【事件处理器类型】 ①访问XML DTD:DTDHandler ②低级访问解析错误:ErrorHandler ③访问文档内容:ContextHandler 【DefaultHandler类】 SAX事件处理程序的默认基类,实现了DTDHandler、ErrorHandler、ContextHandler和EntityResolver接口,通常 做法是,继承该基类,重写需要的方法,如startDocument() 注:关于遍历 ①深度优先遍历(Depthi-First Traserval) ②广度优先遍历(Width-First Traserval)

SAX解析详解

创建SAX解析器

SAXParserFactory saxf = SAXParserFactory.newInstance();

SAXParser sax = saxf.newSAXParser();

JDOM解析

JDOM方法是根据DOM方法的众多繁琐操作进行包装得到的,上面我们看到,DOM方法解析XML文档其实是很繁琐的,而且很混乱,标签、属性、换行空格都当作结点类型来处理。JDOM方法定义了一系列通俗、好记的方法来解析XML,方法的底层封装了一系列DOM操作,但是我们不必亲自去进行这些繁琐的工作了。

优点:

a、DOM方式的优点:查找方便,可以修改 缺点 a、DOM方式的缺点:装载整个文档,对内存容量要求高

在JDOM中,同一了根节点、普通结点、属性等全为Element类型。

JDOM解析详解

操作步骤:

1:创建一个SAXbuilder:SAXBuilder builder = new SAXBuilder();

2:创建文件输入流打开xml文件:InputStream in = new FileInputStream("XXX.xml");

3:通过builder,从输入流读取xml文件创建dom对象:Document dom = builder.build(in);

4:获取根节点:Element root=dom.getRootElement();

5:获取子节点列表:List<Element> childNodes = node.getChildren();

6:遍历子节点列表,获取第i个结点:Element node = childNodes.get(i);

7:读取结点信息:

1)结点属性值:node.getAttributeValue("属性名");

2)结点名:node.getName();

3)结点值:node.getValue();

4)子结点文本值:node.getChildText("子结点名");

Dom4j解析

Dom4j是目前最流行、最好用的XML解析工具,解析XML的速度最快。

Dom4j是一个Java的XML API,类似于jdom,用来读写XML文件的。

Mave依赖

     <dependency>

         <groupId>dom4j</groupId>

         <artifactId>dom4j</artifactId>

         <version>1.6.1</version>

     </dependency>

DOM4j解析详解

操作步骤:

1:创建SAXReader:SAXReader reader = new SAXReader();

2:创建文件输入流打开xml文件:InputStream in = new FileInputStream("XXX.xml");

3:通过reader和输入流读取xml文件到内存创建Document对象:Document dom = reader.read(in);

4:获取根节点:Element root=dom.getRootElement();

5:获取子节点列表:List<Element> childNodes = root.elements();

6:遍历子节点:Element node = childNodes.get(i);

7:读取结点信息:

1)结点属性值:node.attributeValue("属性名");

2)结点名:node.getName();

3)结点值:node.getValue();

4)子结点文本值:node.elementText("子结点名")

实例代码

package com.demo;

import org.dom4j.Attribute;

import org.dom4j.Document;

import org.dom4j.DocumentException;

import org.dom4j.Element;

import org.dom4j.io.SAXReader;

import java.io.InputStream;

import java.util.List;

public class Dom4jDemo {

   public static void main(String[] args) throws DocumentException {

       SAXReader reader = new SAXReader();

       InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("users.xml");

       Document document = reader.read(inputStream);

       Element rootElement = document.getRootElement();

       List<Element> elements = rootElement.elements("user");

       for (Element element :

               elements) {

           User user = new User();

           user.setUserId(Long.parseLong(element.attribute("userId").getValue()));

           user.setIdCard(element.attribute("idcard").getValue());

           user.setName(element.elementText("name"));

           user.setAddress(element.elementText("address"));

           user.setAge(element.elementText("age"));

           System.out.println(user);

      }

  }

}

总结:

1)DOM、JDOM、DOM4j都是把xml文档读取到内存中,生成dom对象进行遍历的;

DOM是Java原生的,所以比较繁琐;

JDOM是对DOM操作的封装,更加通俗、易记,操作也快了一点;

DOM4j解析xml的函数上与JDOM差不多,只不过有几个相同功能的函数名字不同而已,过程都是一样的;但由于底层使用了Xpath等方法加快了索引,所以检索性能更快。

2)SAX是基于事件驱动的,查询事件监听器继承自DefaultHandler,定义了检索xml过程中遇到开始标签、结束标签时执行的事件函数,从而查找需要的信息并返回而不是把整个文档都加载进来

比较

1)DOM4J性能最好,连Sun的JAXM也在用DOM4J。目前许多开源项目中大量采用DOM4J,例如大名鼎鼎的Hibernate也用DOM4J来读取XML配置文件。如果不考虑可移植性,那就采用DOM4J.

2)JDOM和DOM在性能测试时表现不佳,在测试10M文档时内存溢出。在小文档情况下还值得考虑使用DOM和JDOM。虽然JDOM的开发者已经说明他们期望在正式发行版前专注性能问题,但是从性能观点来看,它确实没有值得推荐之处。另外,DOM仍是一个非常好的选择。DOM实现广泛应用于多种编程语言。它还是许多其它与XML相关的标准的基础,因为它正式获得W3C推荐(与基于非标准的Java模型相对),所以在某些类型的项目中可能也需要它(如在JavaScript中使用DOM)。

3)SAX表现较好,这要依赖于它特定的解析方式-事件驱动。一个SAX检测即将到来的XML流,但并没有载入到内存.还有就是只能读取不能修改xml(当然当XML流被读入时,会有部分文档暂时隐藏在内存中)。

以上是 DOM解析手册 的全部内容, 来源链接: utcz.com/z/512404.html

回到顶部