body, td {
font-family: calibri;
font-size: 10pt;
}

解析xml常用的有两种方式,DMO和SAX

DOM和SAX的区别:

  • DOM:
    • 在内存中生成树桩结构
    • 优点是可以支持增删改查各种操作
    • 缺点在于,如果文档过大的时候,可能会产生内存溢出的风险
  • SAX:
    • 基于事件驱动,边读边解析
    • 优点:占用内存小
    • 缺点,不支持增删改操作.(DOM4J会在内存中生成树状结构,虽然是SAX方式解析…)

XML的DOM解析

xml的DOM解析,主要会用到两个包中的类

  • javax.xml.parsers :用来解析
  • javax.xml.transform:用来回写

解析

    public static Document getDocument(String src) throws Exception{
//获取工厂类
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//获取解析器
DocumentBuilder builder = factory.newDocumentBuilder();
//返回Document(org.w3c.dom.Document)
return builder.parse(src);
}

处理

在拿到document之后,就可以想干哈就干哈了.

在元素末尾增加一个子元素

    /**
* DOM大法之--在元素末尾增加一个元素
* @throws Exception
*/
public static void addElementTest() throws Exception{
//解析
Document document = JaxpDomUtils.getDocument("src/book.xml");
//处理
NodeList nodeList = document.getElementsByTagName("书");
Node book2 = nodeList.item(1);

Element cat = document.createElement("cat");
cat.setTextContent("I am a cat");
book2.appendChild(cat);
//回写
JaxpDomUtils.writeBack(document, "src/book.xml");
}

这个地方需要注意,Node和Element. Node表示文档树上的一个节点,这个文档不局限于HTML或者XML,而element表示HTML或者xml中一个元素.

在任意位置增加元素

    /**
* DOM大法之--在任意位置增加元素
* @throws Exception
*/
public static void addElementAnyWhereTest() throws Exception{
Document document = JaxpDomUtils.getDocument("src/book.xml");
Node book2 = document.getElementsByTagName("书").item(1);
Node author2 = document.getElementsByTagName("作者").item(1);
Element cat = document.createElement("cat");
cat.setTextContent("I am a cat too");
book2.insertBefore(cat, author2);
JaxpDomUtils.writeBack(document, "src/book.xml");
}

删除一个节点

    /**
* DOM大法之--删除一个元素
* @throws Exception
*/
public static void deleteNodeTest() throws Exception{
Document document = JaxpDomUtils.getDocument("src/book.xml");
Node cat1 = document.getElementsByTagName("cat").item(0);
Node book = cat1.getParentNode();
book.removeChild(cat1);
JaxpDomUtils.writeBack(document, "src/book.xml");

}

这里比较蛋疼的是,必须先找到要删除的元素,然后再找他爹,然后通过他爹的remove方法把它删掉…

    /**
* DOM大法之--修改元素
* @throws Exception
*/
public static void changeNodeTest() throws Exception {
Document document = JaxpDomUtils.getDocument("src/book.xml");
Node author2 = document.getElementsByTagName("作者").item(1);
author2.setTextContent("西川结衣");
JaxpDomUtils.writeBack(document, "src/book.xml");

}

查找

    /**
* DOM大法之--删除一个元素
* @throws Exception
*/
public static void deleteNodeTest() throws Exception{
Document document = JaxpDomUtils.getDocument("src/book.xml");
Node cat1 = document.getElementsByTagName("cat").item(0);
Node book = cat1.getParentNode();
book.removeChild(cat1);
JaxpDomUtils.writeBack(document, "src/book.xml");

}

Node下面有很多get方法,需要的时候再翻文档吧.

回写

    public static void writeBack(Document document, String dest) throws Exception{
//回写的工厂类
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult(dest));
}

XML的SAX解析

SAX和DOM方式的不同:

  • DOM需要将整个XML文件都读取后再进行解析,如果XML文档非常大,就会消耗计算机的大量内存,并且容易导致内存溢出

  • SAX 是边读边解析.

SAX解析原理

SAX方式和DOM方式的套路差不多. 只有一点不一样,SAX方式没有增删改的功能,只是单纯的读取解析,所以就没有回写的必要了.
这玩意儿主要的方法,大概是这个样子的:
void parse(String uri, DefaultHandler dh)

那么这里就涉及到两个东西:

  • 解析器:

    • 获取解析器工厂

    • 获取解析器对象
    • 解析XML(XML 文件路径,事件处理器)

    解析器采用SAX方式在解析某个XML文档时,它只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器。

    事件处理器由程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松地得到sax解析器解析到的数据,从而可以决定如何对数据进行处理

  • 事件处理器:

    • 一般用DefaultHandler,他是SAX时间处理程序的默认基类.

    • 基于事件触发,比如遇到一个开始标签,就会去执行startElement()方法…(消息订阅机制?! 貌似上学的时候学过这玩意儿…)
      对于一个标准的XML它的消息触发机制大概是这个样子的.

    SAX解析范例

    写一个自己的Handler

    /**
    * 解析xml文件
    * @author thecatcher
    *
    */
    class MyHandler1 extends DefaultHandler{

    //开始标签
    @Override
    public void startElement(String uri, String localName, String qName,
    Attributes attributes) throws SAXException {
    System.out.println("read a start label for an element:"+qName);
    }
    //元素内容
    @Override
    public void characters(char[] ch, int start, int length)
    throws SAXException {
    String str = new String(ch,start,length);
    System.out.println(str);
    }
    //结束标签
    @Override
    public void endElement(String uri, String localName, String qName)
    throws SAXException {
    System.out.println("read a end label for an element:"+qName);
    }
    }

    发散一下,既然是个方法那就可以自己定义行为了. 比如读取特定标签

    /**
    * 读取特定标签
    * @author thecatcher
    *
    */
    class MyHandler21 extends DefaultHandler{
    private boolean flag=false;
    private int count =0;
    @Override
    public void startElement(String uri, String localName, String qName,
    Attributes attributes) throws SAXException {
    if("作者".equals(qName)){
    flag=true;
    count++;
    }
    }

    @Override
    public void characters(char[] ch, int start, int length)
    throws SAXException {
    if(flag&&count==2){
    String str=new String(ch, start, length);
    System.out.println(str);

    }
    }
    @Override
    public void endElement(String uri, String localName, String qName)
    throws SAXException {
    flag=false;
    }
    }

    解析主类:

        public void readXMLTest() throws ParserConfigurationException, SAXException, IOException{
    SAXParserFactory factory = SAXParserFactory.newInstance();
    SAXParser parser = factory.newSAXParser();
    parser.parse("src/book2.xml", new MyHandler21());
    }
  • 最新文章

    1. HIbernate的property-ref属性
    2. loadView、viewDidLoad、viewWillAppear、viewDidAppear等详解
    3. python and django
    4. Vijos 1243 生产产品 (单调队列优化的动态规划)
    5. android开发 替换bitmap中的颜色值
    6. setuid函数解析
    7. jQuery功能一览
    8. 使用BSD socket编写Windows版的网络程序
    9. php发送post请求的三种方法示例
    10. 8月9日,PS、计算机基础(预科)
    11. 十天学会php第五天
    12. bat脚本学习
    13. vim中常用基本命令
    14. 如何在Centos 7上用Logrotate管理日志文件
    15. Android更新UI的几种方法
    16. 开通mysql root 用户远程访问权限(转)
    17. Eclipse代码自动补全
    18. webstorm的快捷键和zencoding
    19. ViewPager滑动不畅及灵敏度的问题
    20. LOJ#3085. 「GXOI / GZOI2019」特技飞行(KDtree+坐标系变换)

    热门文章

    1. Verilog HDL那些事_建模篇笔记(实验八:键盘解码)
    2. centos 7 mini装maridb 10.1 binary版本
    3. SpringMVC中使用Json传数据
    4. 循环语句--while
    5. 【学】jQuery的源码思路4——增加一些功能
    6. UVA 1151 买还是建(最小生成树)
    7. Unity代码设置shader属性
    8. C#获取真实IP地址实现方法
    9. javascript事件执行流程分析
    10. windows平台eclipse for C++开发环境搭建