XML学习笔记(四)

关于本课程的视频课程地址:http://edu.51cto.com/course/15238.html

1、java如何操作xml

dom、sax、jdom、dom4j

1.1、dom操作

1.1.1、dom简介

​ Document Object Model,在应用程序中,基于DOM的XML分析器将一个XML文档转换成一个对象模型的集合(通常称DOM树),应用程序通过对这个对象模型的操作,来实现对XML文档数据的操作。

  通过DOM接口,应用程序可以在任何时候访问XML文档中的任何一部分数据,因此,这种利用DOM接口的机制也被称作随机访问机制

  DOM树所提供的随机访问方式给应用程序的开发带来了很大的灵活性,它可以任意地控制整个XML文档中的内容。

  然而,由于DOM分析器把整个XML文档转化成DOM树放在了内存中,因此,当文档比较大或结构比较复杂时,对内存的需求就比较高。而且,对于结构复杂的树的遍历也是一项耗时的操作。所以,DOM分析器对机器性能的要求比较高,实现效率不十分理想。

  由于DOM分析器所采用的树结构的思想与XML文档的结构相吻合,同时鉴于随机访问所带来的方便,因此,DOM分析器还是有很广泛的应用价值的。

1.1.2、dom的组成

对于XML应用开发来说,DOM就是一个对象化的XML数据接口,一个与语言无关、与平台无关的标准接口规范。
DOM定义了HTML文档和XML文档的逻辑结构,给出了一种访问和处理这两种文档的方法。文档代表的是数据,而DOM则代表了如何去处理这些数据。
  作为W3C的标准接口规范,目前,DOM由三部分组成,包括:核心(core)、HTML接口和XML接口。
  核心部分是结构化文档比较底层对象的集合,这一部分所定义的对象已经完全可以表达出任何HTML和XML文档中的数据了。
  HTML接口和XML接口两部分则是专为操作具体HTML文档和XML文档所提供的高级接口。

1.1.3、dom模型回顾

<?xml version="1.0" encoding="UTF-8"?>
<student id="s01">
    <sname>关羽</sname>
    <addr>南京</addr>
</student>

对应内存中的dom树

mark

最常见的节点类型:

  元素:元素是XML的基本构建。

    元素可以有其他元素、文本节点或两者兼有来作为其子节点。

    元素节点还是可以有属性的唯一类型的节点。

  属性:属性节点包含关于元素节点的信息,但实际上,不认为它是元素的子节点。

  文本:确切来讲,文本节点是文本。它可以包含许多信息或仅仅是空白。

  文档(根节点) :文档节点是整个文档中所有其他节点的父节点。(根节点不等于根元素节点)。

  较不常见的节点类型:CDATA、注释、处理指令。

1.1.4、dom的api分析

Node、Document、NodeList接口、NamedNodeMap、Element

node接口

The Node interface is the primary datatype for the entire Document Object Model. It represents a single node in the document tree. While all objects implementing the Node interface expose methods for dealing with children, not all objects implementing the Node interface may have children. For example, Text nodes may not have children, and adding children to such nodes results in a DOMException being raised. 

The attributes nodeName, nodeValue and attributes are included as a mechanism to get at node information without casting down to the specific derived interface. In cases where there is no obvious mapping of these attributes for a specific nodeType (e.g., nodeValue for an Element or attributes for a Comment ), this returns null. Note that the specialized interfaces may contain additional and more convenient mechanisms to get and set the relevant information. 

Document

The Document interface represents the entire HTML or XML document. Conceptually, it is the root of the document tree, and provides the primary access to the document's data. 
Since elements, text nodes, comments, processing instructions, etc. cannot exist outside the context of a Document, the Document interface also contains the factory methods needed to create these objects. The Node objects created have a ownerDocument attribute which associates them with the Document within whose context they were created. 

NodeList

The NodeList interface provides the abstraction of an ordered collection of nodes, without defining or constraining how this collection is implemented. NodeList objects in the DOM are live. 
The items in the NodeList are accessible via an integral index, starting from 0. 

getLength() :获得集合的长度

Node item(int index):获得指定索引的节点

NamedNodeMap

public interface NamedNodeMap
Objects implementing the NamedNodeMap interface are used to represent collections of nodes that can be accessed by name. Note that NamedNodeMap does not inherit from NodeList; NamedNodeMaps are not maintained in any particular order. Objects contained in an object implementing NamedNodeMap may also be accessed by an ordinal index, but this is simply to allow convenient enumeration of the contents of a NamedNodeMap, and does not imply that the DOM specifies an order to these Nodes. NamedNodeMap objects in the DOM are live. 

Element

The Element interface represents an element in an HTML or XML document. Elements may have attributes associated with them; since the Element interface inherits from Node, the generic Node interface attribute attributes may be used to retrieve the set of all attributes for an element. There are methods on the Element interface to retrieve either an Attr object by name or an attribute value by name. In XML, where an attribute value may contain entity references, an Attr object should be retrieved to examine the possibly fairly complex sub-tree representing the attribute value. On the other hand, in HTML, where all attributes have simple string values, methods to directly access an attribute value can safely be used as a convenience. 

1.1.5、dom的解析操作(重点)

首先如果想要解析xml文件,必须获得到Document对象

DocumentBuilder类(抽象类):[DocumentBuilderFactory.newDocumentBuilder()]() 来获取此类的对象

DocumentBuilderFactory(抽象类):产生DocumentBuilder类的对象,这个类提供了一个静态的方法可以产生自己的实例

案例1:

package cn.org.kingdom.dom;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Attr;
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 DomParserDemo01 {
    public static void main(String[] args) throws ParserConfigurationException, FileNotFoundException, SAXException, IOException {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc = db.parse(new FileInputStream("src"+File.separator+"demo01.xml"));
        Element el = doc.getDocumentElement();
        System.out.println("节点的名字:"+el.getNodeName());
        System.out.println("节点的值:"+el.getNodeValue());
        System.out.println("节点的类型:"+el.getNodeType());
        System.out.println("=============================");
        Attr attr = el.getAttributeNode("id");
        System.out.println("属性的名字:"+attr.getName());
        System.out.println("属性的值:"+attr.getValue());
        System.out.println("属性的类型:"+attr.getNodeType());
        System.out.println("=============================");
        //获得根节点的所有子节点
        NodeList nl = el.getChildNodes();
        System.out.println("子节点的数量:"+nl.getLength());
        for(int i = 0 ;i<nl.getLength();i++) {
            Node n = nl.item(i);
            //屏蔽掉文本节点   
            //System.out.println(n.getNodeName()+"-->"+n.getNodeType());
            if(n.getNodeType()==1) {
                System.out.println(n.getLastChild().getNodeValue());
            }
        }
    }
}

案例2:

package cn.org.kingdom.dom;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

public class DomParseDemo02 {
    public static void main(String[] args) throws ParserConfigurationException, FileNotFoundException, SAXException, IOException {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc = db.parse(new FileInputStream("src"+File.separator+"demo01.xml"));
        Element el = doc.getDocumentElement();
        NamedNodeMap nnm = el.getAttributes();
        int length = nnm.getLength();
        System.out.println("el元素中拥有的属性数量为:"+length);
        for(int i = 0 ;i<nnm.getLength();i++) {
            Attr n = (Attr) nnm.item(i);
            System.out.println(n.getNodeName()+"-->"+n.getNodeValue());
        }
        Element el_sname=(Element) el.getElementsByTagName("sname").item(0);
        System.out.println(el_sname.getNodeName()+"-->"+el_sname.getFirstChild().getNodeValue());
        Element el_add = (Element) el_sname.getNextSibling().getNextSibling();
        System.out.println(el_add.getNodeName()+"-->"+el_add.getFirstChild().getNodeValue());
        System.out.println(el_add.getParentNode().getNodeName());
        System.out.println(doc.getXmlEncoding());
        System.out.println(doc.getXmlVersion());
    }
}

1.1.6、创建xml文档

•TransformerFactory:主要用来取得Transformer类的实例

•Transformer:完成输出

•DomSource:主要用来接收document对象

•StreamResult:指定要使用的输出流对象

案例:

package cn.org.kingdom.dom;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class DomCreate {
    public static void main(String[] args) throws ParserConfigurationException, TransformerException, FileNotFoundException {
        TransformerFactory tff = TransformerFactory.newInstance();
        Transformer tf = tff.newTransformer();
        //构建一个新的xml文档
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc = db.newDocument();
        //创建根元素节点
        Element root = doc.createElement("heros");
        doc.appendChild(root);
        //第一个子元素
        Element hero1 = doc.createElement("hero");
        hero1.setAttribute("id", "h01");
        Element elGuan = doc.createElement("name");
        elGuan.setTextContent("关羽");
        Element elAge = doc.createElement("age");
        elAge.setTextContent("13");
        hero1.appendChild(elGuan);
        hero1.appendChild(elAge);
        root.appendChild(hero1);
        //第二个子元素
        Element hero2 = doc.createElement("hero");
        hero2.setAttribute("id", "h02");
        Element elDiaoc = doc.createElement("name");
        elDiaoc.setTextContent("貂蝉");
        Element elAge2 = doc.createElement("age");
        elAge2.setTextContent("13");
        hero2.appendChild(elDiaoc);
        hero2.appendChild(elAge2);
        root.appendChild(hero2);
        //创建输入源
        DOMSource ds = new DOMSource(doc);
        //创建输出源
        StreamResult sr = new StreamResult(new FileOutputStream("src"+File.separator+"create.xml"));
        //输出的操作
        tf.transform(ds, sr);
    }
}

1.2、sax解析方式

7.2.1、sax简介

SAX的全称是Simple APIs for XML,即XML简单应用程序接口。

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

  局限性:

  1. SAX分析器在对XML文档进行分析时,触发了一系列的事件,由于事件触发本身是有时序性的,因此,SAX提供的是一种顺序访问机制,对于已经分析过的部分,不能再倒回去重新处理。即一旦经过了某个元素,我们没有办法返回去再去访问它。

  2. SAX分析器只做了一些简单的工作,大部分工作还要由应用程序自己去做。也就是说,SAX分析器在实现时,只是顺序地检查XML文档中的字节流,判断当前字节是XML语法中的哪一部分、是否符合XML语法,然后再触发相应的事件,而事件处理函数本身则要由应用程序自己来实现。同DOM分析器相比,SAX分析器缺乏灵活性。

  优势:由于SAX分析器实现简单,对内存要求比较低,(SAX不必将整个XML文档加载到内存当中,因此它占据内存要比DOM小), 因此实现效率比较高。对于大型的XML文档来说,通常会用SAX而不是DOM。并且对于那些只需要访问XML文档中的数据而不对文档进行更改的应用程序来说,SAX分析器更为合适。

1.2.2、sax解析(了解)

1、创建一个处理器,让这个处理器继承DefaultHandler类,并重写相关的方法

package cn.org.kingdom.sax;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class MyDefaultHanler extends DefaultHandler  {

    public void startDocument() throws SAXException {
        System.out.println("<?xml version='1.0' encoding='utf-8' ?>");
    }

    public void endDocument() throws SAXException {
        System.out.println("xml文档读取结束");
    }

    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        System.out.print("<"+qName);
        if(attributes!=null) {
            for(int i = 0;i<attributes.getLength();i++) {
                String attName = attributes.getQName(i);
                String value = attributes.getValue(i);
                System.out.print(" "+attName+"='"+value+"'");
            }
        }

        System.out.println(">");

    }

    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        System.out.println("</"+qName+">");
    }

    public void characters(char[] ch, int start, int length)
            throws SAXException {
        System.out.println(new String(ch,start,length));
    }

}

2、创建解析器类

•SAXParserFactory:主要用来创建SAXParser对象

•SAXParser:Parse(File f,DefaultHandler sax)

package cn.org.kingdom.sax;

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

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;

public class SaxDemo {
    public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
        //创建一个sax解析器的工厂对象
        SAXParserFactory spf = SAXParserFactory.newInstance();
        //SAXParser创建
        SAXParser sp = spf.newSAXParser();
        //解析
        sp.parse(new File("src"+File.separator+"demo01.xml"), new MyDefaultHanler());
    }
}

1.3、jdom的解析与创建操作

7.3.1、w3c的局限性

语言独立:DOM 并不是用人们心目中的 Java 语言设计的。虽然这种方法保留了在不同语言中非常相似的 API,它也使那些习惯 Java 语言的程序员感到更麻烦。例如:Java 语言内建了一种 String 类,而 DOM 则规范定义了自己的Text类。

严格的层次结构:DOM API 直接沿袭了 XML 规范。在XML中,每件东西都是一个结点,因此您能在DOM中找到一个几乎每件东西都可以扩展的基于Node 的接口和返回Node 的一系列方法。就多态性的观点来讲,它是优秀的,但是它在Java语言中的应用是困难而且不便的,其中从Node向叶类型作显式向下类型转换会导致代码的冗长和难以理解。

接口驱动:公共DOM API仅由接口组成。w3c 对提供实现并不感兴趣,它只对定义接口(比较有意义)感兴趣。但它也意味着作为 Java 程序员使用 API 在创建 XML对象时增加了负担,因为 w3c 标准大量使用工厂化的类和类似的灵活的但不直接的模式。

1.3.2、JDOM的简介

JDOM是一个开源项目,它基于树型结构,利用纯JAVA的技术对XML文档实现解析、生成、序列化以及多种操作。JDOM 直接为JAVA编程服务。它利用更为强有力的JAVA语言的诸多特性(方法重载、集合概念等),把SAX和DOM的功能有效地结合起来,以弥补DOM及SAX在实际应用当中的不足之处。

即:JDOM=DOM的修改性+SAX的大文件可读性,在使用设计上尽可能地隐藏原来使用XML过程中的复杂性。利用JDOM处理XML文档将是一件轻松、简单的事。

JDOM 主要用来弥补DOM及SAX在实际应用当中的不足之处。这些不足之处主要在于SAX没有文档修改、随机访问以及输出的功能,而对于DOM来说,JAVA程序员在使用时来用起来总觉得不太方便。

1.3.3、jdom解析文件操作

案例1:解析操作

package cn.org.kingdom.jdom;
import java.io.File;
import java.io.IOException;
import java.util.List;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
public class JdomParser {
    public static void main(String[] args) throws JDOMException, IOException {
        SAXBuilder sbi = new SAXBuilder();
        Document doc = sbi.build(new File("src"+File.separator+"demo01.xml"));
        Element rootEl = doc.getRootElement();
        System.out.println("根节点为:"+rootEl.getName());
        System.out.println("根节点中的属性有:");
        List<Attribute> list = rootEl.getAttributes();
        for(Attribute attr :list){
            System.out.println(attr.getName()+"-->"+attr.getValue());
        }
        System.out.println(rootEl.getChildText("sname"));
        System.out.println(rootEl.getChildText("addr"));
        List<Element> sublist = rootEl.getChildren();
        for(Element e:sublist){
            System.out.println(e.getName()+"-->"+e.getText());
        }
    }
}

1.3.4、jdom的创建操作

package cn.org.kingdom.jdom;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import org.jdom.Comment;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.XMLOutputter;

public class JdomCreateDemo {
    public static void main(String[] args) throws FileNotFoundException, IOException {
        XMLOutputter  out = new XMLOutputter();

        Document doc = new Document();
        //创建根节点
        Element root = new Element("heros");
        //设置根节点
        doc.setRootElement(root);

        Element element1 = new Element("hero");
        //采用一种代码链的风格方式
        element1.addContent(new Element("name").setText("曹操"))
                .addContent(new Element("age").setText("15"));

        Element element2 = new Element("hero");

        element2.addContent(new Element("name").setText("百丽守约"))
        .addContent(new Element("age").setText("20"))
        .addContent(new Comment("这是一个注释"));
        root.addContent(element1);
        root.addContent(element2);
        out.output(doc, new FileOutputStream("src"+File.separator+"jdom.xml"));
    }
}

1.3.5、jdom的总结

JDOM是作为一种轻量级API 被制定的,最主要的是它是以Java为中心的。它在遵循DOM主要规则的基础上除去了上述缺点

JDOM 是 Java 平台专用的,api使用 Java 语言的内建String支持,因此文本值也适用于 String 。它还可利用 Java 2 平台的类集,如 List 和Iterator ,给程序员提供了一个丰富的并且和Java 语言类似的环境。

在 JDOM 中,XML 元素就是 Element 的实例,XML 属性就是 Attribute 的实例,XML文档本身就是 Document 的实例。由于在XML 中所有这些都代表了不同的概念,因此它们总是作为自己的类型被引用,而不是作为一个含糊的“结点”。

类驱动,因为 JDOM 对象就是像 Document 、Element 和 Attribute 这些类的直接实例,因此创建一个新 JDOM 对象就如在 Java 语言中使用 new 操作符一样容易。它还意味着不需要进行工厂化接口配置 -- JDOM 的使用是直截了当的。

1.4、dom4j

1.4.1、dom4j的简介

当xml文档的大小大于10m的时候,如果采用jdom会出现性能问题,此时我们就可以选择dom4j

DOM4J是一套开源的类库。与JDOM不同的是:DOM4J使用接口和抽象基类,它的API要复杂一些,但是灵活性更好 ,基于接口设计,在一些常见的框架中比如hibernate、mybati等都使用是dom4j

1.4.2、dom4j的解析操作

package cn.org.kingdom.dom4j;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class Dom4jParser {
    public static void main(String[] args) throws FileNotFoundException, DocumentException {
        SAXReader reader = new SAXReader();
        Document doc = reader.read(new FileInputStream(new File("src"+File.separator+"demo01.xml")));
        Element root = doc.getRootElement();
        System.out.println(root.getName());
        List<Attribute> list = root.attributes();
        for (Attribute attr : list) {
            System.out.println(attr.getName()+"-->"+attr.getValue());
        }

        //根据名称直接获取属性的值
        System.out.println(root.attributeValue("id"));
        System.out.println(root.attributeValue("age"));
        //获取根元素下的子节点
        System.out.println("=====================");
        List<Element> list2 = root.elements();
        for (Element el : list2) {
            System.out.println(el.getName()+"-->"+el.getText());
        }
        System.out.println("****************************");

        Iterator<Element> iter = root.elementIterator();

        while(iter.hasNext()) {
            Element e = iter.next() ; 

            System.out.println(e.getName()+"-->"+e.getText());
        }

    }
}

1.4.3、dom4j的创建操作

package cn.org.kingdom.dom4j;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.XMLWriter;
public class Dom4jCreateDemo {
    public static void main(String[] args) throws IOException { 
        OutputStream is = new FileOutputStream(new File("src"+File.separator+"dom4j.xml"));
        XMLWriter writer = new XMLWriter(is);
        //注意:这里创建document没有jdom的中方便了
        Document doc = DocumentHelper.createDocument();
        Element root =DocumentHelper.createElement("stu");
        doc.setRootElement(root);
        root.addAttribute("sid", "s01");    
        Element elName = DocumentHelper.createElement("name").addText("zhangsan");
        Element elAge = DocumentHelper.createElement("age").addText("15");
        root.add(elName);
        root.add(elAge);    
        writer.write(doc);
    }
}

猜你喜欢

转载自blog.51cto.com/11230344/2307931
今日推荐