Java解析XML

Java解析XML

本文介绍了使用JAXP和DOM4J解析java的方法.

编辑者:洋葱
引用来源
http://inotgaoshou.iteye.com/blog/1012188
http://developer.51cto.com/art/200903/117512.htm
http://baike.baidu.com/link?url=JKEP_Z5D0HWgDW0kHYKpwRTU3tyGeLooE94744iYIAItwTKK2yQREqoqkLEEqez6QK9vGLWpH0AXTkF_ARWvLa
转载请注明所有引用地址.

一.XML解析方式
1.DOM解析

DOM的全称是Document Object Model,也即文档对象模型。在应用程序中,基于DOM的XML分析器将一个XML文档转换成一个对象模型的集合(通常称DOM树),应用程序正是通过 对这个对象模型的操作,来实现对XML文档数据的操作。通过DOM接口,应用程序可以在任何时候访问XML文档中的任何一部分数据,因此,这种利用DOM 接口的机制也被称作随机访问机制。

DOM接口提供了一种通过分层对象模型来访问XML文档信息的方式,这些分层对象模型依据XML的文档 结构形成了一棵节点树。无论XML文档中所描述的是什么类型的信息,即便是制表数据、项目列表或一个文档,利用DOM所生成的模型都是节点树的形式。也就 是说,DOM强制使用树模型来访问XML文档中的信息。由于XML本质上就是一种分层结构,所以这种描述方法是相当有效的。

DOM树所提 供的随机访问方式给应用程序的开发带来了很大的灵活性,它可以任意地控制整个XML文档中的内容。然而,由于DOM分析器把整个XML文档转化成DOM树 放在了内存中,因此,当文档比较大或者结构比较复杂时,对内存的需求就比较高。而且,对于结构复杂的树的遍历也是一项耗时的操作。所以,DOM分析器对机 器性能的要求比较高,实现效率不十分理想。不过,由于DOM分析器所采用的树结构的思想与XML文档的结构相吻合,同时鉴于随机访问所带来的方便,因 此,DOM分析器还是有很广泛的使用价值的。

2.SAX 解析

SAX的全称是Simple APIs for XML,也即XML简单应用程序接口。与DOM不同,SAX提供的访问模式是一种顺序模式,这是一种快速读写XML数据的方式。当使用SAX分析器对 XML文档进行分析时,会触发一系列事件,并激活相应的事件处理函数,应用程序通过这些事件处理函数实现对XML文档的访问,因而SAX接口也被称作事件 驱动接口。

二.使用JAXP解析XML

/**
1.DOM生成和解析XML文档
为 XML 文档的已解析版本定义了一组接口。
解析器读入整个文档,然后构建一个驻留内存的树结构,然后代码就可以使用 DOM 接口来操作这个树结构。
优点:整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能;
缺点:将整个文档调入内存(包括无用的节点),浪费时间和空间;
使用场合:一旦解析了文档还需多次访问这些数据;硬件资源充足(内存、CPU)。 

对XML文档的操作
1.获取/添加/修改/删除节点值
2.获取/设置/修改/删除属性值
3.层次遍历节点树
*/
public class DomDemo implements XmlDocument { 
    public static void main(String[] args){
        String fileName="book.xml";
        DomDemo dom=new DomDemo();
        dom.parserXml(fileName);
        dom.init();
        dom.createXml("book.out.xml");
    }
    //文档对象
    private Document document; 
    /**
    创建一个空的文档对象
    */
    public void init() { 
        try { 
            //构建一个工厂
            DocumentBuilderFactory factory = DocumentBuilderFactory .newInstance(); 
            //新建一个实例
            DocumentBuilder builder = factory.newDocumentBuilder(); 
            //获取文档对象
            this.document = builder.newDocument(); 
        } catch (ParserConfigurationException e) { 
            System.out.println(e.getMessage()); 
        }   
    } 
    /**
    创建一个XML文件
    */
    public void createXml(String fileName) { 


        //创建一个元素,并作为根节点
        Element root = this.document.createElement("books"); 
        this.document.appendChild(root);
        //创建一个节点
        Element book = this.document.createElement("book"); 

            //创建一个子节点,并设置子节点的文本内容
            Element bookName = this.document.createElement("书名"); 
                bookName.appendChild(this.document.createTextNode("Java编程思想第4版")); 
            book.appendChild(bookName); 


            Element price = this.document.createElement("定价"); 
                //设置属性
                price.setAttribute("单位", "元");
                price.appendChild(this.document.createTextNode("108.00")); 
            book.appendChild(price); 

            //如上
            Element author = this.document.createElement("作者"); 
                author.setAttribute("性别", "男");
                author.appendChild(this.document.createTextNode("Bruce Eckel")); 
            book.appendChild(author);

            //如上
            Element isbnNo = this.document.createElement("ISBN编号"); 
                isbnNo.appendChild(this.document.createTextNode("9787111213826")); 
            book.appendChild(isbnNo);

        root.appendChild(book); 
        //保存
        save(document,fileName, "gbk");
    } 
    /**
    从文件解析XML文档
    */
    public void parserXml(String fileName) {
        try {
            // 创建工厂,构建示例,加载文件,获取文档树对象
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document document = db.parse(fileName);
            // 获取所有直接子节点
            NodeList books = document.getChildNodes();
            // 遍历,第一层
            for (int i = 0; i < books.getLength(); i++) {
                Node book = books.item(i);
                System.out.println(book.getNodeName());
                NodeList bookInfo = book.getChildNodes();
                // 遍历,第二层
                for (int j = 0; j < bookInfo.getLength(); j++) {
                    Node node = bookInfo.item(j);
                    System.out.println("\t"+node.getNodeName());
                    NodeList bookMeta = node.getChildNodes();
                    // 遍历,第三层
                    for (int k = 0; k < bookMeta.getLength(); k++) {
                        System.out.print("\t\tnode>>"
                                + bookMeta.item(k).getNodeName() + ":"
                                + bookMeta.item(k).getTextContent());
                        // 输出示例 书名:Java编程思想第4版

                        /**
                         * 获取属性,而且可以设置属性
                         */
                        NamedNodeMap map = bookMeta.item(k).getAttributes();
                        if (map != null) {
                            for (int l = 0; l < map.getLength(); l++) {
                                Node att = map.item(l);
                                System.out.println(" "+att.getNodeName() + "="
                                        + att.getTextContent());
                                //设置属性
                                att.setTextContent("changed");
                            }
                        }
                    }
                }
            }
            /**
             * 通过输出结果我们可以发现,JAVA使用DOM解析时,<标签>与<标签>之间也是节点
             */
            System.out.println("解析完毕");
            //将修改的结果保存
            save(document,fileName, "gbk");
        } catch (FileNotFoundException e) {
            System.out.println(e.getMessage());
        } catch (ParserConfigurationException e) {
            System.out.println(e.getMessage());
        } catch (SAXException e) {
            System.out.println(e.getMessage());
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    } 

    public void save(Document document, String fileName, String encoding) {

//      System.out.println("encoding="+document.getXmlEncoding());
        // 实例化转换器工厂
        TransformerFactory tf = TransformerFactory.newInstance();
        try {
            // 实例一个转换器
            Transformer transformer = tf.newTransformer();
            // 构建一个文档源
            DOMSource source = new DOMSource(document);
            // 设置字符编码
            transformer.setOutputProperty(OutputKeys.ENCODING, encoding);
            // 设置缩排
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");

            PrintWriter pw = new PrintWriter(new FileOutputStream(fileName));
            StreamResult result = new StreamResult(pw);
            // 通过转换器将文档树源写入文件
            transformer.transform(source, result);

            System.out.println("XML文件保存成功!");
        } catch (TransformerConfigurationException e) {
            System.out.println(e.getMessage());
        } catch (IllegalArgumentException e) {
            System.out.println(e.getMessage());
        } catch (FileNotFoundException e) {
            System.out.println(e.getMessage());
        } catch (TransformerException e) {
            System.out.println(e.getMessage());
        }
    }
} 

//
/**
2.SAX生成和解析XML文档

为解决DOM的问题,出现了SAX。SAX ,事件驱动。
当解析器发现元素开始、元素结束、文本、文档的开始或结束等时,发送事件,程序员编写响应这些事件的代码,保存数据。
优点:
    不用事先调入整个文档,占用资源少;
    SAX解析器代码比DOM解析器代码小,适于Applet,下载。
缺点:
    不是持久的;事件过后,若没保存数据,那么数据就丢了;
    无状态性;从事件中只能得到文本,但不知该文本属于哪个元素;
使用场合:Applet;只需XML文档的少量内容,很少回头访问;机器内存少; 

*/
public class SaxDemo implements XmlDocument {
    public static void main(String[] args){
        SaxDemo demo=new SaxDemo();
        String fileName="book.out.xml";
        demo.parserXml(fileName);
    }
    public void createXml(String fileName) {   
        System.out.println("<<"+fileName+">>");   
    }
    //解析
    public void parserXml(String fileName) {   
        //实例化一个工厂
        SAXParserFactory saxfac = SAXParserFactory.newInstance();   
        try {   
            //实例化一个解析器
            SAXParser saxparser = saxfac.newSAXParser();   
            InputStream is = new FileInputStream(fileName);  
            //使用MySAXHandler处理文档
            saxparser.parse(is, new MySAXHandler());
        } catch (ParserConfigurationException e) {   
            e.printStackTrace();   
        } catch (SAXException e) {   
            e.printStackTrace();   
        } catch (FileNotFoundException e) {   
            e.printStackTrace();   
        } catch (IOException e) {   
            e.printStackTrace();   
        }   
    }
    public void save(Document document, String fileName, String encoding) {
        // TODO Auto-generated method stub
    }   
}   
class MySAXHandler extends DefaultHandler {   
    boolean hasAttribute = false;   
    Attributes attributes = null;   
    //解析开始事件
    public void startDocument() throws SAXException {   
        System.out.println("文档解析开始");   
    }   
    //解析结束事件
    public void endDocument() throws SAXException {   
        System.out.println("文档解析结束");   
    }   
    //解析到一个元素的起始标签
    public void startElement(String uri, String localName, String qName,   
        Attributes attributes) throws SAXException {   
        System.out.println("elementStart> "+qName);   
        if (attributes.getLength() > 0) {   
            this.attributes = attributes;   
            this.hasAttribute = true;   
        }   
    }   
    //解析到一个元素的结束标签
    public void endElement(String uri, String localName, String qName)   throws SAXException {   
        //打印属性
        if (hasAttribute && (attributes != null)) {   
            for (int i = 0; i < attributes.getLength(); i++) {   
                System.out.println("attr> "+attributes.getQName(0)+"="+ attributes.getValue(0));   
            }   
        }
        System.out.println(qName+">elementEnd");
    }
    //解析到元素内容
    public void characters(char[] ch, int start, int length)   throws SAXException {   
        //输出内容
        System.out.println("content> "+new String(ch, start, length));   
    }   
}

三.使用Dom4j 解析XML

百度百科上有大量的说明,这里写一个很小的应用


/***
 * 使用Dom4j操作XML文档.
 * 操作列表:
 * 加载,解析,读取,添加,修改,保存.
 */
public class Dom4jInstance {
    public static void main(String[] args) throws DocumentException, IOException {
        String outFile="Dom4jDemo.xml";
        Dom4jInstance ins=new Dom4jInstance();
        ins.load(outFile);
        ins.iterator();
        ins.addNode();
        ins.save(outFile);
    }
    private Document doc=null;
    //1.从文件加载XML文档
    public void load(String fileName) throws DocumentException{
        File file=new File(fileName);
        if(!file.exists()){
            System.out.println("文件不存在!");
            return ;
        }
        SAXReader reader = new SAXReader();
        doc= reader.read(file);
        System.out.println("加载成功!");
    }
    //2.遍历xml
    public void iterator(){
        doc.accept(new MyVisitor());
    }
    private class MyVisitor extends VisitorSupport {
        //访问元素
        public void visit(Element element) {
            System.out.println("\t"+element.getName());
        }
        //访问属性
        public void visit(Attribute attr) {
            System.out.print("\t"+attr.getName()+"="+attr.getValue()+" ");
        }
        //访问元素内值
        public void visit(Text node) {
            System.out.println("\t\t"+node.getText());
        }
    }
    //3.使用XPath获取某个元素
    public void update(String xpath){
        List<Node> list=doc.selectNodes(xpath);
        for(Node node : list){
            System.out.println(node.getName()+"="+node.getText());
        }
    }
    //4.添加一个节点并设置属性
    public void addNode(){
        List<Node> list=doc.selectNodes("//books/book");
        for(Node n : list){
            Element e=(Element)n;
            e.addElement("出版社").addAttribute("地址", "北京").setText("清华大学出版社");
        }
    }
    //5.选择编码格式并保存到文件
    public void save(String outFile) throws IOException{
        XMLWriter writer;
        // 美化格式
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding(doc.getXMLEncoding());
        writer = new XMLWriter(new FileOutputStream(outFile), format );
        System.out.println("已写入文件"+outFile);
        writer.write(doc);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值