文件处理之XML-----DOM方式

关于XML解析的几种方式,可以去看看别人家的博客,这里主要展示DOM,SAX,DOM4J三种方式生成xml和解析xml的示例!
四种生成和解析XML文档的方法详解(介绍+优缺点比较+示例)

DOM方式生成xml:

public static void DomCreateXml() throws Exception {
        // 1、创建一个DocumentBuilderFactory的对象
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        // 2、创建一个DocumentBuilder对象
        DocumentBuilder db = dbf.newDocumentBuilder();
        // 3、创建一个新的Document
        Document document = db.newDocument();
        // 创建元素
        Element songs = document.createElement("songs");
        // 创建子元素(使用一个循环来创建子元素)
        for (int i = 0; i < 5; i++) {
            // 创建元素
            Element song = document.createElement("song");
            Element name = document.createElement("name");
            // 向name中添加数据
            // 如果改变数据可以直接定义三个数组 或者创建一个实体类 吧他们放入集合中再来赋值
            name.setTextContent("春天里");
            Element time = document.createElement("time");
            time.setTextContent("5:20");
            Element size = document.createElement("size");
            size.setTextContent("30m");
            //添加到上一级的元素
            song.appendChild(name);
            song.appendChild(time);
            song.appendChild(size);
            songs.appendChild(song);
        }
        // 添加元素到文档
        document.appendChild(songs);

        // 保存到项目的 demo/目录下
        // 首先创建一个TransformerFactory对象
        TransformerFactory tff = TransformerFactory.newInstance();
        // 再利用tff创建一个Transformer
        Transformer tf = tff.newTransformer();
        // xml 换行
        tf.setOutputProperty(OutputKeys.INDENT, "yes");
        // 关联文档 和 创建xml文件
        tf.transform(new DOMSource(document), new StreamResult("demo/dom.xml"));

    }

使用DOM创建xml的时候需要注意DOM数的层级关系,因为DOM是w3c的标准,所以DOM具有一定的通用性,在JavaScript中操作html和上面的代码类似,这里就不赘述。下面我们再来看一下如何

DOM方式解析xml:

这里写代码片public static void DomParseXml() throws Exception {
        // 1、创建一个DocumentBuilderFactory的对象
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        // 2、创建一个DocumentBuilder对象
        DocumentBuilder db = dbf.newDocumentBuilder();
        // 3、通过调用db的parse的方法加载xml文件
        Document parse = db.parse(new FileInputStream("demo/dom.xml"));
        // 获取到了parse对象之后 就可以进行节点的解析,开始解析song节点
        NodeList songs = parse.getElementsByTagName("song");
        for (int i = 0; i < songs.getLength(); i++) {
            // 通过item定位每一首歌的集合
            Node song = songs.item(i);
            // 通过song获取当前song节点里面的属性集合
            NamedNodeMap attributes = song.getAttributes();
            // 输出一下里面的属性
            System.out.println(attributes.getLength());
            // 遍历属性
            for (int j = 0; j < attributes.getLength(); j++) {
                // 那一个song节点里某一个属性
                Node item = attributes.item(j);
                // 打印属性值
                System.out.println(item.getNodeName() + " = " + item.getNodeValue() + "");
            }
            // 遍历子节点
            NodeList childNodes = song.getChildNodes();
            // 输出一下子节点的长度
            System.out.println(childNodes.getLength());
            // 遍历子节点并且输出
            for (int k = 0; k < childNodes.getLength(); k++) {
                // 判断一下是否是空格
                if (childNodes.item(k).getNodeType() == Node.ELEMENT_NODE) {
                        System.out.println(childNodes.item(k).getNodeName() + " = " +   childNodes.item(k).getTextContent());
                }
            }
        }
    }

在获取子节点的值的时候需要注意并不是getNodeVaue()方法,而是getTextContent()方法,当然还可以使用 childNodes.item(k).getFirstChild().getNodeValue()方法获取节点值。

SAX方式生成XML

public static void SAXCreateXml() throws Exception {
        // 创建一个xml文件
        StreamResult streamResult = new StreamResult(new FileOutputStream("demo/sax.xml"));
        // 创建好了xml文件之后需要进行设置 包括设置xml的内容
        // 创建SAXTransformerFactory对象
        SAXTransformerFactory tff = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
        // 通过tff创建TransformerHandler对象
        TransformerHandler handler = tff.newTransformerHandler();
        // 格式化xml文档
        handler.getTransformer().setOutputProperty(OutputKeys.INDENT, "yes");
        // 设置handler和xml文档关联
        handler.setResult(streamResult);

        // 关联了之后我们需要向xml文件中添加元素 
        // 首先打开document文档
        handler.startDocument();
        // 方便添加属性
        AttributesImpl attr = new AttributesImpl();
        // 打开
        handler.startElement("", "", "songs", attr);
        for (int i = 0; i < 5; i++) {
            //这里直接定义字符串  也可自行定义数组或者集合(定义集合需要判断是否为空)
            String s1 = "童话镇",s2="4:30 秒",s3="4 M";
            // 先清空一下属性
            attr.clear();
            attr.addAttribute("", "", "id", "", "1");
            handler.startElement("", "", "song", attr);

            attr.clear();
            handler.startElement("", "", "name", attr);
            handler.characters(s1.toCharArray(), 0, s1.length());
            handler.endElement("", "", "name");

            attr.clear();
            handler.startElement("", "", "time", attr);
            handler.characters(s2.toCharArray(), 0, s2.length());
            handler.endElement("", "", "time");

            attr.clear();
            handler.startElement("", "", "size", attr);
            handler.characters(s3.toCharArray(), 0, s3.length());
            handler.endElement("", "", "size");

            handler.endElement("", "", "song");
        }

        // 关闭
        handler.endElement("", "", "songs");
        handler.endDocument();
    }

这里我使用的是自己定义的字符串,当然也可自行定义数组或者集合,定义集合的时候需要判断一下是否为空,不要报了空指针。

SAX方式解析XML

main函数

public static ArrayList<Song> SAXParseXml() throws Exception {
        // 1、获取一个SAXParserFactory对象
        SAXParserFactory factory = SAXParserFactory.newInstance();
        // 2、通过factory 创建SAXParser对象
        SAXParser parser = factory.newSAXParser();
        // 3、parse的对象的parse方法加载xml文件
        // 创建一个工具类继承DefaultHandler
        SAXHandler saxHandler = new SAXHandler();
        parser.parse(new FileInputStream("demo/songs.xml"), saxHandler);
        // 输出一下list的长度
        System.out.println(saxHandler.getList().size());
        List<Song> list = saxHandler.getList();
        for (Song s : list) {
            System.out.println(s.getId());
            System.out.println(s.getName());
            System.out.println(s.getTime());
            System.out.println(s.getSize());
        }
        return (ArrayList<Song>) saxHandler.getList();
    }

SAXHandler类:

public class SAXHandler extends DefaultHandler {

    private List<Song> list ;
    private Song song = null;
    private String string = null;

    // 生成getList方法 输出
    public List<Song> getList() {
        return list;
    }

    public SAXHandler() {
        this.list =new ArrayList<Song>();
    }

    @Override
    public void startDocument() throws SAXException {
        super.startDocument();
        System.out.println("开始解析");
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        // TODO Auto-generated method stub
        super.startElement(uri, localName, qName, attributes);
        if (qName.equals("song")) {
            // 创建实体类song的对象
            song = new Song();
            // 遍历song
            for (int i = 0; i < attributes.getLength(); i++) {
                System.out.println(attributes.getQName(i) + " = " + attributes.getValue(i));
                System.out.println("\n==========================");

                // 把id保存到实体类中
                if (attributes.getQName(i).equals("id")) {
                    song.setId(attributes.getValue(i));
                }

            }
        } else if (!qName.equals("song") && !qName.equals("songs")) {
            System.out.println("节点名:" + qName);
        }

    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        // TODO Auto-generated method stub
        super.characters(ch, start, length);
        // 必须把节点值定义成全局的变量 否则endElement就很难获取到值
        string = new String(ch, start, length);
        // 去掉换行
        if (!string.trim().equals("")) {
            System.out.println("节点值:" + string + "\n");
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        // TODO Auto-generated method stub
        super.endElement(uri, localName, qName);
        if (qName.equals("song")) {
            System.out.println("=============结束===============");
            // 添加到集合中去
            list.add(song);
            // 添加到了集合中之后清空一下song
            song = null;
        } else if (qName.equals("name")) {
            song.setName(string);
        } else if (qName.equals("time")) {
            song.setTime(string);
        } else if (qName.equals("size")) {
            song.setSize(string);
        }

    }

    @Override
    public void endDocument() throws SAXException {
        // TODO Auto-generated method stub
        super.endDocument();
        System.out.println("结束解析");
    }

}

实体类Song:

package com.entity;

public class Song {

    private String id;
    private String name;
    private String time;
    private String size;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }

    public String getSize() {
        return size;
    }

    public void setSize(String size) {
        this.size = size;
    }
}

上面操作:解析xml文档 —->保存到集合中—->输出
当然你不保存到集合直接输出也是可以的,直接把关于实体类和集合的代码删除可以,只是我们一般都要保存值,然后再取出来,因为我感觉有一定的普遍性,所以就贴出了保存到集合的例子。
SAX方法其实是这四种方式中解析速度是最快的,没错在中小型的xml数据中比dom4j还要快,大型的数据中dom4j是最好的,Hibernate使用dom4j就是个例子。看过开头的那篇博客都知道,SAX也有一些缺点,这里不再赘述。

DOM4J方式生成XML文档

public static void DOM4JCreateXML() throws Exception {
        //1、创建document对象 
        Document document = DocumentHelper.createDocument();
        //2、创建根节点
        Element rootElement = document.addElement("songs");
        //3、创建子元素节点
        Element song = rootElement.addElement("song");

        Element name = song.addElement("name");
        name.setText("今天你要嫁给我");
        Element time = song.addElement("time");
        time.setText("5:20");
        Element size = song.addElement("size");
        size.setText("10M");
        //4、生成xml文件
        XMLWriter xmlWriter = new XMLWriter(
                new FileOutputStream("demo/dom4j.xml"),
                //格式化 
                OutputFormat.createPrettyPrint()
                );
        //写入到文档
        xmlWriter.write(document);
        //关闭xmlWriter
        xmlWriter.close();
    }

如果没有什么特别要求的话,我觉得大家还是使用DOM4J比较好,代码量少,生成的xml文档也美观。另外,DOM4J还可以支持很多复杂的xml文档,本人还没有使用过,如果你知道也可以和我说说,非常欢迎!

DOM4J方式解析XML文档

// 创建SAXReader对象
        SAXReader saxReader = new SAXReader();
        // 加载books.xml文件并且获取document对象
        Document document = saxReader.read(new InputStreamReader(new  FileInputStream("demo/dom4j.xml"), "utf-8"));
        //通过document获取根节点
        Element rootElement = document.getRootElement();
        //通过根节点获取迭代器
        Iterator elementIterator = rootElement.elementIterator();
        while (elementIterator.hasNext()) {
            Element song = (Element) elementIterator.next();
            //获取book的属性名及属性值
            List<Attribute> attributes = song.attributes();
            for (Attribute attr : attributes) {
                System.out.println(attr.getName()+" = "+attr.getValue());
            }

            //对song的子节点名和子节点值进行遍历
            Iterator elementIterator2 = song.elementIterator();
            while (elementIterator2.hasNext()) {
                Element songChild = (Element) elementIterator2.next();
                System.out.println("节点名:"+songChild.getName()+"  "+songChild.getStringValue());
            }
        }
    }

这里介绍了三种方式解析XML文档,JDOM的话,本人觉得没有使用的必要,完全可以使用DOM4J方式替代,另外DOM这种方式遇到大文件的时候也处理不好,所以我推荐使用SAX方式和DOM4J方式解析和生成XML文档。最最重要的一点,差点忽略了,DOM方式和SAX是JAVA中自带的,不需要导入额外的JAR包,而JDOM和DOM4都需要导入额外的JAR包。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值