XML文档操作之JAXP下实现

来源:互联网 发布:学党规 知敬畏守规矩 编辑:程序博客网 时间:2024/06/06 04:00

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

0 0
原创粉丝点击