天天看点

JAXP学习(2)简单示例

本文结合实例对JAXP进行基本学习。

DOM (Document Object Model APIs)

DOM方式解析XML

The DOM API is generally an easier API to use. It provides a familiar tree structure of objects. You can use the DOM API to manipulate the hierarchy of application objects it encapsulates. The DOM API is ideal for interactive applications because the entire object model is present in memory, where it can be accessed and manipulated by the user.
JAXP学习(2)简单示例

下面给出示例的目录结构和示例

JAXP学习(2)简单示例

books.xml

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book category="COOKING">
  <title lang="en">Everyday Italian</title> 
  <author>Giada De Laurentiis</author> 
  <year>2005</year> 
  <price>30.00</price> 
</book>
<book category="CHILDREN">
  <title lang="en">Harry Potter</title> 
  <author>J K. Rowling</author> 
  <year>2005</year> 
  <price>29.99</price> 
</book>
<book category="WEB">
  <title lang="en">Learning XML</title> 
  <author>Erik T. Ray</author> 
  <year>2003</year> 
  <price>39.95</price> 
</book>
</bookstore>
           

Book.java

package entity;

public class Book {
    private String title;
    private String author;
    private String year;
    private String price;
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getAuthor() {
        return author;
    }
    public void setAuthor(String author) {
        this.author = author;
    }
    public String getYear() {
        return year;
    }
    public void setYear(String year) {
        this.year = year;
    }
    public String getPrice() {
        return price;
    }
    public void setPrice(String price) {
        this.price = price;
    }
    @Override
    public String toString() {
        return "Book [title=" + title + ", author=" + author + ", year=" + year + ", price=" + price + "]";
    }
    public Book() {
        super();
    }
    public Book(String title, String author, String year, String price) {
        super();
        this.title = title;
        this.author = author;
        this.year = year;
        this.price = price;
    }

}
           

JaxpDomTest.java

package test;

import java.io.IOException;
import java.io.InputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.junit.Test;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;

import entity.Book;
/**
 * 测试JAXP DOM方式操作XML
 * @author Administrator 2017年6月23日09:10:42
 *
 */
public class JaxpDomTest {
    /**
     * XML读取
     */
    @Test
    public void domTest(){
        try {
            //获取xml数据
            ClassLoader classLoader=Thread.currentThread().getContextClassLoader();
            InputStream is=classLoader.getResourceAsStream("xmldoc/books.xml");
            //获取DocumentBuilder
            DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
            DocumentBuilder db = factory.newDocumentBuilder();
            //将xml解析为Document
            Document doc = db.parse(is);
            //处理Document
            NodeList list = doc.getElementsByTagName("book");
            int nodeLength=list.getLength();
            for(int i=;i<nodeLength;i++){
                Element ele=(Element)list.item(i);
                String title=ele.getElementsByTagName("title").item().getTextContent();
            String author=ele.getElementsByTagName("author").item().getFirstChild().getNodeValue();
                String year=ele.getElementsByTagName("year").item().getFirstChild().getNodeValue();
                String price=ele.getElementsByTagName("price").item().getFirstChild().getNodeValue();
                Book book=new Book(title, author, year, price);
                System.out.println(book.toString());
            }
        } catch (DOMException e) {
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
           

读取xml内容并保存到Book实例中。domTest()运行结果

Book [title=Everyday Italian, author=Giada De Laurentiis, year=2005, price=30.00]
Book [title=Harry Potter, author=J K. Rowling, year=2005, price=29.99]
Book [title=Learning XML, author=Erik T. Ray, year=2003, price=39.95]

           

这里只简单演示读取XML操作,DOM的修改,添加,删除可结合API学习。

SAX(Simple API for XML APIs)

SAX方式解析XML

The Simple API for XML (SAX) is the event-driven, serial-access mechanism that does element-by-element processing. The API for this level reads and writes XML to a data repository or the web. For server-side and high-performance applications, you will want to fully understand this level. But for many applications, a minimal understanding will suffice.
JAXP学习(2)简单示例

SAX示例代码:

JaxpSaxTest.java

package test;

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.junit.Test;
import org.xml.sax.SAXException;

/**
 * JAXP SAX方式读取XML
 * @author Administrator 2017年6月28日10:05:54
 *
 */
public class JaxpSaxTest {
    @Test
    public void saxTest(){
        try {
            //获取SAXParser
            SAXParserFactory factory=SAXParserFactory.newInstance();
            SAXParser newSAXParser = factory.newSAXParser();
            //解析xml数据,并定义事件处理器(SAXParser会回调MySAXEventHandler中对应的方法).
            newSAXParser.parse(new File("src/xmldoc/books.xml"), new MySAXEventHandler());
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
           

MySAXEventHandler.java

package test;

import java.util.ArrayList;
import java.util.List;

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

import entity.Book;

/**
 * 自定义事件处理器继承DefaultHandler,根据需要重写DefaultHandler的方法
 * @author Administrator 2017年6月28日10:08:27
 *
 */
public class MySAXEventHandler extends DefaultHandler {
    /**
     * 标签名称,用以区分不同的标签
     */
    private String tagName="";
    /**
     * Book对应xml中<book>元素
     */
    private Book book=new Book();
    /**
     * Book集合对应xml中<bookstore>元素
     */
    private List<Book> bookstore=new ArrayList<>();

    /**
     * 文档开始事件
     */
    @Override
    public void startDocument() throws SAXException {
        System.out.println("........startDocument.......");
    }
    /**
     * 元素开始事件
     */
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        System.out.print("<"+qName+">");
        tagName=qName;
        if("book".equals(qName)){
            book=new Book();
        }
    }
    /**
     * 文本数据事件
     */
    @Override
    public void characters(char ch[], int start, int length) throws SAXException {
        String content=new String(ch, start, length);
        System.out.print(content);
        switch (tagName){
            case "title": 
                book.setTitle(content);
                break;
            case "author":
                book.setAuthor(content);
                break;
            case "year":
                book.setYear(content);
                break;
            case "price":
                book.setPrice(content);
                break;
        }
    }
    /**
     * 元素结束事件
     */
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        System.out.print("</"+qName+">");
        tagName="";//清空标记,防止endElement()方法结束后,再次回调characters()时,switch语句的条件仍然是qName值。
        if("book".equals(qName)){
            bookstore.add(book);
        }
    }
    /**
     * 文档结束时间
     */
    @Override
    public void endDocument() throws SAXException {
        System.out.println("\n"+".............endDocument..............");
        for(Book bk:bookstore){
            System.out.println(bk.toString());
        }
    }
}
           

运行saxTest(),运行结果:

........startDocument.......
<bookstore>
<book>
  <title>Everyday Italian</title> 
  <author>Giada De Laurentiis</author> 
  <year>2005</year> 
  <price>30.00</price> 
</book>
<book>
  <title>Harry Potter</title> 
  <author>J K. Rowling</author> 
  <year>2005</year> 
  <price>29.99</price> 
</book>
<book>
  <title>Learning XML</title> 
  <author>Erik T. Ray</author> 
  <year>2003</year> 
  <price>39.95</price> 
</book>
</bookstore>
.............endDocument..............
Book [title=Everyday Italian, author=Giada De Laurentiis, year=2005, price=30.00]
Book [title=Harry Potter, author=J K. Rowling, year=2005, price=29.99]
Book [title=Learning XML, author=Erik T. Ray, year=2003, price=39.95]
           

可以看出,使用SAX解析XML时,通常要自定义事件处理器继承DefaultHandler。

StAX(Streaming API for XML)

StAX方式解析XML

To summarize, StAX provides a standard, bidirectional pull parser interface for streaming XML processing, offering a simpler programming model than SAX and more efficient memory management than DOM. StAX enables developers to parse and modify XML streams as events, and to extend XML information models to allow application-specific additions.

StAX示例代码

JaxpStaxTest.java

package test;

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

import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

import org.junit.Test;
/**
 * JAXP StAX方式解析XML
 * @author Administrator 2017年6月28日10:22:31
 *
 */
public class JaxpStaxTest {
    /**
     * 基于指针的方式
     */
    @Test
    public void staxCursorTest(){
        try {
            //获取XMLStreamReader
            XMLInputFactory factory=XMLInputFactory.newFactory();
            File file=new File("src/xmldoc/books.xml");
            XMLStreamReader xmlStreamReader = factory.createXMLStreamReader(new FileInputStream(file));
            //用xmlStreamReader获取数据
            while(xmlStreamReader.hasNext()){
                int eventType=xmlStreamReader.getEventType();
                switch(eventType){
                    case XMLStreamReader.START_DOCUMENT:
                        System.out.println("------------START_DOCUMENT----------------");
                        break;
                    case XMLStreamReader.START_ELEMENT:
                        System.out.print("<"+xmlStreamReader.getLocalName()+">");
                        break;
                    case XMLStreamReader.CHARACTERS:
                        System.out.print(xmlStreamReader.getText());
                        break;
                    case XMLStreamReader.END_ELEMENT:
                        System.out.print("</"+xmlStreamReader.getLocalName()+">");
                        break;
                }
                int nextType=xmlStreamReader.next();
                if(nextType==XMLStreamReader.END_DOCUMENT){
                    System.out.println("\n"+"------------END_DOCUMENT------------------");
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (FactoryConfigurationError e) {
            e.printStackTrace();
        } catch (XMLStreamException e) {
            e.printStackTrace();
        }
    }
    /**
     * 基于迭代器的方式
     */
    @Test
    public void staxIteratorTest(){
        try {
            //获取XMLEventReader
            XMLInputFactory factory=XMLInputFactory.newFactory();
            File file=new File("src/xmldoc/books.xml");
            XMLEventReader xmlEventReader = factory.createXMLEventReader(new FileInputStream(file));
            //用XMLEvent获取数据
            while (xmlEventReader.hasNext()) {
                XMLEvent xmlEvent=xmlEventReader.peek();
                int eventType=xmlEvent.getEventType();
                switch(eventType){
                    case XMLEvent.START_DOCUMENT:
                        System.out.println("----START_DOCUMENT----");
                        break;
                    case XMLEvent.START_ELEMENT:
                        StartElement startElement = xmlEvent.asStartElement();
                        System.out.print("<"+startElement.getName()+">");
                        break;
                    case XMLEvent.CHARACTERS:
                        Characters characters = xmlEvent.asCharacters();
                        System.out.print(characters.getData());
                        break;
                    case XMLEvent.END_ELEMENT:
                        EndElement endElement = xmlEvent.asEndElement();
                        System.out.print("</"+endElement.getName()+">");
                        break;
                    case XMLEvent.END_DOCUMENT:
                        System.out.print("\n"+"-----END_DOCUMENT----");
                        break;
                }
                xmlEventReader.nextEvent();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (FactoryConfigurationError e) {
            e.printStackTrace();
        } catch (XMLStreamException e) {
            e.printStackTrace();
        }
    }
}
           

运行staxCursorTest()和staxIteratorTest()结果类似,如下所示:

----START_DOCUMENT----
<bookstore>
<book>
  <title>Everyday Italian</title> 
  <author>Giada De Laurentiis</author> 
  <year>2005</year> 
  <price>30.00</price> 
</book>
<book>
  <title>Harry Potter</title> 
  <author>J K. Rowling</author> 
  <year>2005</year> 
  <price>29.99</price> 
</book>
<book>
  <title>Learning XML</title> 
  <author>Erik T. Ray</author> 
  <year>2003</year> 
  <price>39.95</price> 
</book>
</bookstore>
-----END_DOCUMENT----
           

StAX提供了两种解析方式。直观的区别在于Cursor方式通过xmlStreamReader获取数据,Iterator方式通过xmlEvent获取数据。

XSLT(Extensible Stylesheet Language Transformations)

简单介绍XSLT

The Extensible Stylesheet Language Transformations (XSLT) standard defines mechanisms for addressing XML data (XPath) and for specifying transformations on the data in order to convert it into other forms. JAXP includes an interpreting implementation of XSLT
JAXP学习(2)简单示例

代码:

JaxpXsltTest.java

package test;

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.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.junit.Test;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

/**
 * JAXP xslt简单示例
 * @author Administrator 2017年6月28日10:53:35
 *
 */
public class JaxpXsltTest {
    @Test
    public void xsltTest(){
        try {
            // 获取Transformer
            TransformerFactory tFactory =TransformerFactory.newInstance();
            Transformer transformer = tFactory.newTransformer();
            //获取数据源
            DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse(new File("src/xmldoc/books.xml"));
            DOMSource source = new DOMSource(document);
            //获取结果流
            StreamResult result = new StreamResult(System.out);
            //将数据源转换(传输)到结果流中
            transformer.transform(source, result);

        } catch (TransformerConfigurationException e) {
            e.printStackTrace();
        } catch (TransformerFactoryConfigurationError e) {
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TransformerException e) {
            e.printStackTrace();
        }
    }
}
           
JAXP学习(2)简单示例

这里只是JAXP的简单示例,不同解析方式的理解和对比后续介绍。

参考资料:

XPath JAVA用法总结及代码样例

Java API for XML Processing (JAXP)