利用DOM、SAX技术解析XML文档

利用DOM、SAX技术解析XML文档
    我们知道XML文档现在大多用来传输数据和做配置文件,但不管是什么样的应用,都离不开读取XML中保存的数据信息。下面我们就来看看在java中,通过sun公司发布的API如何来解析获取XML中的数据信息。
    解析XML,有2种技术,一种是DOM,一种是SAX。
    DOM全称:Document Object Model(文档对象模型),这种技术会将整个XML文档全部加载到内存中,形成一棵倒立的文档树。我们通过字面意思可以这样来理解:文档对象模型(将整个XML文档,加载到内存,按照预先的模型,形成一棵目录树对象,我们对数据节点(一会再说什么是节点)的所有操作,都在这棵树上)。正因为XML的完整信息都加载到了内存,所以,DOM可以对内存中的这棵文档树修改/添加/删除节点,并能写入到XML文档中(对XML文档进行实际的操作),还可以任意来回滚动访问任意节点。
    什么是节点呢?在文档树中,一切都是节点,例:
    <stu>
        <oneStu id = "10">
            <name>ltz</name>
            <age>22</age> 
        </oneStu>
    </stu>
    这个XML在文档树中的节点数有11个,怎么说呢?<stu></stu>是一个,<stu>与<oneStu>之间的空格也是一个,同样的,<oneStu>是一个,<oneStu>与<name>之间也是一个,<name></name>是一个,ltz又是一个。。。这就是一切都是节点。。。(当然了,我们这里没有加入层次的概念,只是单纯的说明在DOM中,一切都是节点)。
    还有个问题需要注意的是,在XML的根元素加载到文档树中以后,会在根元素的上面再有一个节点。也就是XML中的跟元素,到DOM中就不是根节点了。
    下面我们来看看如何利用DOM技术获取XML中的信息:
package net.ltz.dom;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class ForSummary{
 /**
  * 获取Document对象
  * @return 返回Document对象
  * @throws Exception
  */
 private Document getDOC(String xmlPath) throws Exception{
  //建造文档建造工厂对象
  DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
  //生产出文档建造对象
  DocumentBuilder db = dbf.newDocumentBuilder();
  //建造解析xml文件的文档对象
  Document doc = db.parse(xmlPath);
  return doc;
 }
 
 /**
  * 获取文档树的信息(这里就不使用递归了,主要是熟悉DOM本身的语法操作)
  * @param doc
  */
 private void getMSG(Document doc){
  //因为进来以后,得到的是xml的根元素的父节点,前面叙述的时候有讲到
  //所以要找到根元素就要获取当前节点的子节点
  Node fristElement = doc.getFirstChild();
  //获取节点名
  String fristElementName = fristElement.getNodeName();
  //获取节点类型1对应的是元素,2是属性,3是文档,共有12种,可以参看API
  int fristElementType = fristElement.getNodeType();
  //获取节点的值,只有元素、文本节点有值,其他的节点调用这个方法返回NULL
  String firstElementValue = fristElement.getNodeValue();
  System.out.println("节点名:"+fristElementName+"  节点类型:"+fristElementType+"  节点值:"+firstElementValue);
 
  fristElement.getTextContent();//获取从这个节点往下的所有的文本节点内容。返回String
  
  //获取同级节点
  //因为我现在还在xml的根元素这,所以,要继续往下才有同级节点
  Node secondNode = fristElement.getLastChild();//getFrist/lastChild是获取当前节点的第一/最后一个子节点
  secondNode.getNextSibling();//获取同级下一个
  secondNode.getPreviousSibling();//获取同级上一个
  
  
  //获取指定标签的节点
  NodeList defineNodeList = doc.getElementsByTagName("db");
  //因为在一个xml中,元素名相同的很多,所以返回的是一个NodeList
  for(int i = 0;i<defineNodeList.getLength();i++){
   //注意,NodeList不是用[]来指定下标,是用item()
   System.out.println(defineNodeList.item(i).getNodeName());
  }
  
  //获取父级节点
  Node parentNode = secondNode.getParentNode();  
  
 }
 
 public static void main(String [] args) throws Exception{
  ForSummary fs = new ForSummary();
  Document doc = fs.getDOC("db.xml");
  fs.getMSG(doc);
 }
}

    至于修改和保存XML,请百度一下^_^,太多了。。。很难写
   
    SAX技术:基于事件驱动的,在操作的时候,不会将XML完整的加载到内存。而是从上到下的依次到xml中去读取,并且在每个元素的开始、结束处都会触发一个事件。如果我们要处理的话,就捕捉这个事件,不处理不用管就行。这样的方式有个缺点就是不能来回滚动,不管读哪里的数据,都要从头到尾依次读,也不能往xml中写入数据。但是它不占用多大的内存空间。
    private void getXMLUseSAX()throws Exception{
  SAXParserFactory spf = SAXParserFactory.newInstance();
  SAXParser sp = spf.newSAXParser();
  sp.parse("db.xml", new DefaultHandler(){
   @Override
   public void startDocument() throws SAXException {
    System.out.println("开始读取文档");
   }
   @Override
   public void endDocument() throws SAXException {
    System.out.println("结束读取文档");
   }
   @Override
   public void startElement(String uri, String localName,
     String qName, Attributes attributes) throws SAXException {
    System.out.println("读取元素  "+qName+"  开始");
   }
   @Override
   public void endElement(String uri, String localName, String qName)
     throws SAXException {
    System.out.println("读取元素  "+qName+"  结束");
   }
   @Override
   public void characters(char[] ch, int start, int length)
     throws SAXException {
    System.out.println("文档内容:"+new String(ch,start,length));
   }
  });
 }
  
   这两种技术都有优缺点,所以,我们一般会结合使用。在要操作xml或者对接点进行修改的时候,就用DOM,只读取的话,可以用SAX.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

easewalk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值