XML解析

DOM(Document Object Model)解析

优点:增删改查方便

缺点:需要读取整个xml才能构建DOM树。对于较大的xml,容易内存溢出

SAX(Simple API for XML)解析

优点:在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才会文档进行操作

缺点:不是持久的;事件过后,若没保存数据,那么数据就丢了;无状态性;从事件中只能得到文本,但不知该文本属于哪个元素

适用于只查询


JAXP(Java API for XML Processing)

可以进行DOM解析和SAX解析,由SUN公司提供,存在于JDK中

所在包:

org.w3c.dom:提供DOM方式解析XML的标准接口

org.xml.sax:提供SAX方式解析XML的标准接口

javax.xml:提供了解析XML文档的类

JAXP调用dom方式创建xml

创建一个如下所示的xml文件

<?xml version="1.0" encoding="UTF-8"?>
<recipe type="dessert">
<recipename cuisine="american" servings="1">Ice Cream Sundae</recipename>
</recipe>

java代码如下:

public static void createXML(String fileName) throws Exception{
    //获取DocumentBuilderFactory
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    //获取DocumentBuilder
        DocumentBuilder builder = factory.newDocumentBuilder();
	//获取Document对象
	Document document = builder.newDocument();
	//设置xml声明
	document.setXmlStandalone(false);//指定此文档是否是单独的的属性
	//创建跟元素 <recipe type="dessert">
	Element rootElement = document.createElement("recipe");
	//设置元素属性
	rootElement.setAttribute("type", "dessert");
	//创建元素<recipename>
	Element recipename = document.createElement("recipename");
	//为recipename元素添加属性
	recipename.setAttribute("cuisine", "american");
	recipename.setAttribute("servings", "1");
	//设置recipename元素中的值
	recipename.setTextContent("Ice Cream Sundae");
	rootElement.appendChild(recipename);
	//将根元素添加到document中
	document.appendChild(rootElement);
		
		
	//将xml映射到文件
	boolean flag = true;
	try{
	    //获取TransformerFactorty   用于创建 Transformer 和 Templates 对象。
	    TransformerFactory tf = TransformerFactory.newInstance();
	    //获取Transformer对象  处理来自不同源的 XML,并将转换输出写入各种接收器
	    //注意:在多线程同时运行时不能使用此类的对象
	  Transformer transformer = tf.newTransformer();
	  DOMSource source = new DOMSource(document);
	  //设置编码格式
	  transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
	  //设置indent = "yes" | "no". indent 指定了当输出结果树时,Transformer 是否可以添加额外的空白;其值必须为 yes 或 no。就是幽默诶有进行格式化
	  transformer.setOutputProperty(OutputKeys.INDENT, "yes");
	  PrintWriter pw = new PrintWriter(new FileOutputStream(fileName));
	  StreamResult result = new StreamResult(pw);
	  transformer.transform(source, result);
        }catch(Exception e){
	    flag = false;
	  e.printStackTrace();
	}
	if(flag){
	  System.out.println("生成XML文件成功!");
	}else{
	    System.out.println("生成XML文件失败!");
	}
	}

JAXP调用SAX解析XML

public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
		//创建解析器工厂,
		SAXParserFactory spf = SAXParserFactory.newInstance();
		//得到解析器,
		SAXParser parser = spf.newSAXParser();
		//得到读取器
		XMLReader reader = parser.getXMLReader();
		//给内容注册内容处理器
//		reader.setContentHandler(new MyContentHandler());
		reader.setContentHandler(new DefaultHandler(){
			public void startDocument() throws SAXException {
				// TODO Auto-generated method stub
				super.startDocument();
				System.out.println("读取文档开始");
			}
			public void endDocument() throws SAXException {
				// TODO Auto-generated method stub
				super.endDocument();
				System.out.println("读取文档结束");
			}
		});
		//解析文档
		reader.parse("book.xml");
}

由于dom用来增删改比较方便,所以选择了用期进行创建修改操作,而SAX方式可以快速的进行查找便利,所以选择用来做解析遍历,此处就不在编写dom解析xml的方式了。


第三方解析XML--DOM4J

解析XML,对XML进行遍历

首先要获取到一个Document对象

public Document parse(URL url) throws DocumentException {
        SAXReader reader = new SAXReader();
        Document document = reader.read(url);
        return document;
 }

然后开始进行遍历,在文档中找到两种方法见代码:

//方法1
  public void bar(Document document) throws DocumentException {

        Element root = document.getRootElement();

        // iterate through child elements of root
        for ( Iterator i = root.elementIterator(); i.hasNext(); ) {
            Element element = (Element) i.next();
            // do something
        }

        // iterate through child elements of root with element name "foo"
        for ( Iterator i = root.elementIterator( "foo" ); i.hasNext(); ) {
            Element foo = (Element) i.next();
            // do something
        }

        // iterate through attributes of root 
        for ( Iterator i = root.attributeIterator(); i.hasNext(); ) {
            Attribute attribute = (Attribute) i.next();
            // do something
        }
     }
//方法2
public void treeWalk(Document document) {
        treeWalk( document.getRootElement() );
    }

    public void treeWalk(Element element) {
        for ( int i = 0, size = element.nodeCount(); i < size; i++ ) {
            Node node = element.node(i);
            if ( node instanceof Element ) {
                treeWalk( (Element) node );
            }
            else {
                // do something....
            }
        }
    }

在文档中表明:如果说xml文件比较大的话,建议用第二种方法,可以避免了创建每个循环迭代器对象的成本。


Dom4j创建xml

/**
*创建XML
*/
 public Document createDocument() {
        Document document = DocumentHelper.createDocument();
        Element root = document.addElement( "root" );

        Element author1 = root.addElement( "author" )
            .addAttribute( "name", "James" )
            .addAttribute( "location", "UK" )
            .addText( "James Strachan" );
        
        Element author2 = root.addElement( "author" )
            .addAttribute( "name", "Bob" )
            .addAttribute( "location", "US" )
            .addText( "Bob McWhirter" );

        return document;
    }
/**
*将XML进行持久化(保存到文件)
*/
public void write(Document document) throws IOException {

        XMLWriter writer = new XMLWriter(
            new FileWriter( "output.xml" )
        );
        writer.write( document );
        writer.close();


        /*这个地方是定义输出格式
        *OutputFormat.createPrettyPrint()  方便阅读的格式(带空格,带换行)
        *OutputFormat.createCompactFormat();没有空格换行
        *format.setEncoding(String encoding) 可以设置编码格式,默认utf-8
        */
        OutputFormat format = OutputFormat.createPrettyPrint();
        writer = new XMLWriter( System.out, format );
        writer.write( document );
    }

以上dom4j代码摘自文档中