JAXP是java API for xml PRocessing的缩写。

其API可以在javax.xml.parsers 这个包中找到。这个包向用户提供了两个最重要的工厂类,SAXParserFactory 和DocumentBuilderFactory,我们可以通过这两个类实现之后对XML文件的操作。作为一个xml的解析器,w3c组织官方推荐使用Dom(Document Object Model 文档对象模型)方式进行解析,但是实际上的社区标准是SAX(Simple API For XML)。两者各有各的好处,下面是简易的两点区别:

  • dom方式可以实现对XML文档的CRUD(即增删改查操作)
  • sax主要是能够快速的查找某一个节点的值(注意不能CRUD)

今天我们就一起来看一看Dom方式来解析XML吧。

原理

DOM是一个以“面向对象”思路进行操作的方式,所谓对象就是指Dom实际上是将一个xml文件一下子装载到JVM中,然后根据XML文件的格式和内容在JAXP中创建一个“对象树”模型的方式,然后只需要针对这些对象进行操作就可以实现对XML文档的操作。


怎样得到一个对象模型:

  • 利用DocumentBuilderFactory创建一个解析工厂实例(工厂)
  • 得到一个DocumentBuilder解析器(机器)
  • 然后通过对机器装载xml文件得到一个解析对象Document的实例
  • 对这个Document进行一些列的操作即可
private static Document getDocument(String filePath) {
        // TODO Auto-generated method stub
        //get the prase factory
                DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
                //get the prase machine
                DocumentBuilder builder;
                Document document = null;
                try {
                    builder = factory.newDocumentBuilder();
                    //get the Object of the xml.file
                    document = builder.parse(filePath);
                } 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();
                }

            return document;
    }

完成了对xml文档的操作之后,这就完了吗?思考发现并没有完成,因为我们操作的文档上之前一下子加载到内存中的文件,我们改变的仍旧只是内存中的文件,要想对原文件进行彻底的修改,我们还得有一些写回的操作,这就需要用到TransformerFactory类和Transformer类。

  • 使用TransformerFactory工厂类得到一个工厂
  • 通过工厂“加工”出来一个Transformer类
  • 调用Transformer的transform方法就可以完成写回的操作了。

    但是通过查询API文档,发现transform方法的参数需要进行一些包装。

    所以还需要下面的包装方法。
public static  void WriteBack(Document document,String path){
        TransformerFactory factory= TransformerFactory.newInstance();
        try {
            Transformer transformer= (Transformer) factory.newTransformer();
            DOMSource source = new DOMSource(document);
            StreamResult result= new StreamResult(new File("src/Person.xml"));
            transformer.transform(source, result);
        } catch (TransformerConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (TransformerException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

剩下的操作就是比较简单的了,代码中注释也比较详尽,就不在过多的描述。


小结:

好处:全面,操控范围广

缺点:文件一下子装载到内存中,有可能导致内存泄漏(1、虽然Windows下有虚拟内存解决方案;2、我们也可以手动的更改Java虚拟机中-Xxm (大小)方式更改运行时内存;但最好是对文件较小的时候采用这个方式)


下面是我的项目中src目录下的一个Person.xml文件:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Persons>
    <Person>
        <Name>Summer</Name>
        <Age>20</Age>
        <Address>ShangHai</Address>
    </Person>

    <Person>
        <Name>GRB</Name>
        <Age>10</Age>
        <Address>DaLian</Address>
    </Person>
</Persons>

下面是对这个XML文档的CRUD操作:

package com.summer.jaxp;

import java.io.File;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class PraseXMLByJAXP {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //set the xml file path
        String filePath="src/Person.xml";
        //get the operation object ----document
        Document document= getDocument(filePath);

        //get the xml file result
        getTheResult(document);

        //update the xml file
        upDateTheXMLFile(document);

        //add one Node
        addOneNode(document,filePath);

        //delete one node
        deleteOneNode(document , filePath , "Address");

        //operate the attribute
        operateTheAttribute(document,filePath);

    }

    private static void operateTheAttribute(Document document, String filePath) {
        // TODO Auto-generated method stub
        Element person = (Element) document.getElementsByTagName("Person").item(1);
        //add some attribute
        person.setAttribute("sex", "Man");
        person.setAttribute("married", "Yes");

        //update one special attribute
        person.setAttribute("sex", "Woman");

        //delete one special attribute
        person.removeAttribute("sex");

        //remember to write the operation result back to xml file, or that's only be saved in memary
        WriteBack(document, filePath);
    }

    private static void deleteOneNode(Document document, String filePath,
            String TagName) {
        //you must get the node's parent then operate its's father to remove this node
        Node oldChild = document.getElementsByTagName(TagName).item(1);
        oldChild.getParentNode().removeChild(oldChild);
        WriteBack(document, filePath);

    }

    private static void addOneNode(Document document,String filePath) {
        // TODO Auto-generated method stub
        Node parent =  document.getElementsByTagName("Person").item(1);
        Node child= document.createElement("Hobby");
        child.setTextContent("Basketball and Coding!");
        parent.appendChild(child);
        WriteBack(document, filePath);
    }

    private static Document getDocument(String filePath) {
        // TODO Auto-generated method stub
        //get the prase factory
                DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
                //get the prase machine
                DocumentBuilder builder;
                Document document = null;
                try {
                    builder = factory.newDocumentBuilder();
                    //get the Object of the xml.file
                    document = builder.parse(filePath);
                } 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();
                }

            return document;
    }

    /**
     * write the operation result back to xml file
     * @param document
     * @param path
     */
    @Test
    public static  void WriteBack(Document document,String path){
        TransformerFactory factory= TransformerFactory.newInstance();
        try {
            Transformer transformer= (Transformer) factory.newTransformer();
            DOMSource source = new DOMSource(document);
            StreamResult result= new StreamResult(new File("src/Person.xml"));
            transformer.transform(source, result);
        } catch (TransformerConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (TransformerException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private static void upDateTheXMLFile(Document document) {
        // TODO Auto-generated method stub
        NodeList list=document.getElementsByTagName("Name");
        for(int i=1;i<list.getLength();i++){
            Node node= list.item(i);
            node.setTextContent("GRB");
        }
        WriteBack(document, "src/Person.xml");

    }

    private static void getTheResult(Document document) {
        // TODO Auto-generated method stub
        NodeList list=document.getElementsByTagName("Name");
        for(int i=0;i<list.getLength();i++){
            System.out.println(list.item(i).getTextContent());
        }
    }

}

代码运行后的Person.xml有很多已经改变,下面是总的操作的结果:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Persons>
    <Person>
        <Name>Summer</Name>
        <Age>20</Age>
        <Address>ShangHai</Address>
    </Person>

    <Person married="Yes">
        <Name>GRB</Name>
        <Age>10</Age>

        <Hobby>Basketball and Coding!</Hobby>
    </Person>
</Persons>

分析:

细心地朋友会发现:

  • 第二个Person节点的属性多了一个
  • 第二个Person节点的子节点address少了一个
  • 第二个Person节点多了一个子节点hobby

    这便是对XML文档操作的最好的体现。

总结:

使用解析器对xml的解析虽然方式众多,但是在实际中不同的情况选取合适的方式能大大减少不必要的麻烦。所以我们要谨慎的考虑到底要使用那种方式。

XML文档操作之JAXP下实现的更多相关文章

  1. XML文档操作集锦(C#篇)

    在JSON没流行起来的时候xml一直作为程序存储配置信息的主流介质:特别是小型数据表方面还是不错的选择,所以经常涉及到的操作无非也就是增删改查,这篇博客主要是对这些对比较常用的操作做了个简单的总结 文 ...

  2. 关于XML文档操作类

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.X ...

  3. xml文档操作

    /** * */package com.gootrip.util; import java.io.ByteArrayOutputStream;import java.io.File;import ja ...

  4. 用ORM的思想操作XML文档,一个对象就搞定不要太简单。滚蛋吧!XmlDocument、XmlNode、Xml***……

    大家有没有这样的感受,一涉及XML文档操作就得百度一遍.是不是非!常!烦!.各种类型,各种方法,更别提为了找到一个节点多费劲.本来想写个XML操作的工具方法,写了两行一想既然XML文档是有规律的,如果 ...

  5. XPath操作XML文档

    NET框架下的Sytem.Xml.XPath命名空间提供了一系列的类,允许应用XPath数据模式查询和展示XML文档数据. 3.1XPath介绍 主要的目的是在xml1.0和1.1文档节点树种定位节点 ...

  6. C#XmlHelper帮助类操作Xml文档的通用方法汇总

    前言 该篇文章主要总结的是自己平时工作中使用频率比较高的Xml文档操作的一些常用方法和收集网上写的比较好的一些通用Xml文档操作的方法(主要包括Xml序列化和反序列化,Xml文件读取,Xml文档节点内 ...

  7. dom4j解析xml文档全面介绍

    一.dom4j介绍 dom4j是一个Java的XML API,类似于jdom,用来读写XML文件的.dom4j是一个非常非常优秀的Java XML API,具有性能优异.功能强大和极端易用使用的特点, ...

  8. dom4j 间隔插入节点 处理复杂的xml文档

    前几周跟着老师做了一个小项目,个人主要负责xml文档处理,处理过程还是比较复杂的.此外这篇文章并不是讲基本的dom4j读写xml文档, 所以阅读此文的前提是你已经有了dom4j或jdom等处理xml文 ...

  9. XMLHelper类 源码(XML文档帮助类,静态方法,实现对XML文档的创建,及节点和属性的增、删、改、查)

    以下是代码: using System; using System.Collections.Generic; using System.Linq; using System.Web; using Sy ...

随机推荐

  1. Java 中 json字符串转换为类

    使用到alibaba.fastjson包 具体实现 JSONObject jsonObject = JSONObject.parseObject(msg); SmsSenderStatus smsSe ...

  2. Linux允许、禁止ping包

    默认情况下Linux系统允许ping,但是在某些情况下为了安全起见,我们都把服务器设置为禁ping  临时允许ping命令可使用命令: echo 0 >/proc/sys/net/ipv4/ic ...

  3. Cisco Port-Channel 设置(链路聚合)

    Port-Channel 的在实际工作中的主要作用是将两个或多个端口捆绑成为一个虚拟通道. interface Port-channel1 description port(1/0/5-6) swit ...

  4. HTTP 协议详解(超级经典)-转

    什么是HTTP协议 协议是指计算机通信网络中两台计算机之间进行通信所必须共同遵守的规定或规则,超文本传输协议(HTTP)是一种通信协议,它允许将超文本标记语言(HTML)文档从Web服务器传送到客户端 ...

  5. 使用PHP脚本远程部署git项目

    准备工作: 1.coding.net创建私有项目 2.安装了Web服务 Git服务的服务器 服务器端: 1.nginx.php-fpm统一用www用户 www 目录,这个可以通过修改配置文件实现. [ ...

  6. Linux sort -n 与 -g 排序对比

    公司业务需要,天天用awk统计数值然后排序,出问题了,如下: count.sh 是一个统计脚本,把awk输出的值按占比.条数.类型 在重新输出 awk -F\| '{print $16}' *MQTT ...

  7. text-size-adjust: none并没有什么用

    在样式文件中添加text-size-adjust: none,并没有什么用,移动端浏览器自动调整字体大小还是在进行,webkit已取消对其支持,移动端避免浏览器因为横屏.竖屏模式自动缩放字体大小可以加 ...

  8. consul怎么在windows下安装

    1.去官网下载:https://www.consul.io/downloads.html 2.解压: 3.设置环境变量:path添加 E:\programfiles\consul: 4.cmd启动: ...

  9. VLAN之间单臂路由通信

    实验目的 理解单臂路由的应用场景 掌握路由器子接口的配置方法 掌握子接口封装VLAN的配置方法 理解单臂路由的工作原理 实验原理 单臂路由解决用户需要跨越VLAN实现通信的情况. 原理:通过一台路由器 ...

  10. 排序算法的C语言实现(上 比较类排序:插入排序、快速排序与归并排序)

    总述:排序是指将元素集合按规定的顺序排列.通常有两种排序方法:升序排列和降序排列.例如,如整数集{6,8,9,5}进行升序排列,结果为{5,6,8,9},对其进行降序排列结果为{9,8,6,5}.虽然 ...