目录结构一览
一、首先看一下XPath的简单介绍
二、使用XPath的解析XML的工具类
三、通过一个测试类展示工具类的使用
---只是用于测试,此种写法不适用于实际项目中
四、上面的测试类所使用的XML文件
五、适用于项目中的写法(XML Node→Object)
---解析一个XML节点,直接转换为一个对象并返回给调用者
1、解析XML返回对象的封装类
2、上面类的单元测试类
3、使用到的Bean类
首先看一下XPath的简单介绍
什么是XPath?
- XPath使用路径表达式在XML文档中进行导航
- XPath包含一个标准函数库
- XPath是 XSLT 中的主要元素
- XPath是一个 W3C 标准
XPath路径表达式
XPath使用路径表达式来选取XML文档中的节点或者节点集。这些路径表达式和我们在常规的电脑文件系统中看到的表达式非常相似。
XPath标准函数
XPath含有超过100个内建的函数。这些函数用于字符串值、数值、日期和时间比较、节点和QName处理、序列处理、逻辑值等等。
在XPath中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档节点(或称为根节点)。
XPath使用路径表达式来选取XML文档中的节点或节点集。节点是通过沿着路径(path)或者步(steps)来选取的。
使用XPath的解析XML的工具类
好吧,这还是09年底写的,会不会太老旧了?
import java.io.File; import java.io.IOException; import java.io.InputStream; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; /** * 解析XML的工具类,使用XPath * * @author ChenFeng * @version [版本号, 2009-12-22] * @see [相关类/方法] * @since [产品/模块版本] */ public class XMLParseUtil { private DocumentBuilder builder; private XPath xpath; /** * 默认构造函数 * * @throws ParserConfigurationException * 创建XML解析器出错! */ public XMLParseUtil() throws ParserConfigurationException { DocumentBuilderFactory domfactory = DocumentBuilderFactory .newInstance(); builder = domfactory.newDocumentBuilder(); XPathFactory xpfactory = XPathFactory.newInstance(); xpath = xpfactory.newXPath(); } /** * 根据路径解析XML文档 * * <pre> * 可能产生而没有显式抛出的异常: * 1) MalformedURLException :传入文件路径错误!找不到要解析的文件! * 2) SAXParseException : 文件格式错误!无法解析! * </pre> * * @param path * 文件路径 * @return Document对象 * @throws IOException * IO异常 * @throws SAXException * SAX异常 * @see [类、类#方法、类#成员] */ public Document parseDocument(String path) throws IOException, SAXException { return builder.parse(path); } /** * 根据文件解析XML文档 * * <pre> * 可能产生而没有显式抛出的异常: * 1) IllegalArgumentException :传入参数错误!如对象不能为空! * 2) SAXParseException : 文件格式错误!无法解析! * </pre> * * @param file * 文件 * @return Document对象 * @throws IOException * IO异常 * @throws SAXException * SAX异常 * @see [类、类#方法、类#成员] */ public Document parseDocument(File file) throws IOException, SAXException { return builder.parse(file); } /** * 根据输入流解析XML文档 * * <pre> * 可能产生而没有显式抛出的异常: * 1) IllegalArgumentException :传入参数错误!如对象不能为空! * 2) SAXParseException : 文件格式错误!无法解析! * </pre> * * @param is * 输入流 * @return Document对象 * @throws IOException * IO异常 * @throws SAXException * SAX异常 * @see [类、类#方法、类#成员] */ public Document parseDocument(InputStream is) throws IOException, SAXException { return builder.parse(is); } /** * 通过xpath取得节点列表 * * @param node * 节点 * @param expression * XPath表达式 * @return NodeList * @throws XPathExpressionException * XPath表达式异常 * @see [类、类#方法、类#成员] */ public NodeList selectNodes(Node node, String expression) throws XPathExpressionException { // XPath对象编译XPath表达式 XPathExpression xpexpreesion = this.xpath.compile(expression); Object object = xpexpreesion.evaluate(node, XPathConstants.NODESET); return (NodeList) object; } /** * 通过xpath取得单个节点 * * @param node * 节点 * @param expression * XPath表达式 * @return Node * @throws XPathExpressionException * XPath表达式异常 * @see [类、类#方法、类#成员] */ public Node selectSingleNode(Node node, String expression) throws XPathExpressionException { XPathExpression xpexpreesion = this.xpath.compile(expression); Object object = xpexpreesion.evaluate(node, XPathConstants.NODE); return (Node) object; } /** * 根据xpath取得节点的文本值 * * @param node * 节点 * @param expression * XPath表达式 * @return String * @throws XPathExpressionException * XPath表达式异常 * @see [类、类#方法、类#成员] */ public String getNodeStringValue(Node node, String expression) throws XPathExpressionException { XPathExpression xpexpreesion = this.xpath.compile(expression); Object object = xpexpreesion.evaluate(node, XPathConstants.STRING); return (String) object; } }
通过一个测试类展示工具类的使用
只是用于测试,此种写法不适用于实际项目中
import java.io.IOException; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.List; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPathExpressionException; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; /** * 入口程序 * * @author ChenFeng * @version [版本号, 2009-12-21] * @see [相关类/方法] * @since [产品/模块版本] */ public class XMLParseUtilTest { /** * 入口函数 * * @param args * @see [类、类#方法、类#成员] */ public static void main(String[] args) { String path = XMLParseUtilTest.class.getResource("bookstore.xml") .getPath(); XMLParseUtil xmlParse = null; try { xmlParse = new XMLParseUtil(); } catch (ParserConfigurationException e) { System.out.println("异常:创建XML解析器过程中有一个严重的配置错误!"); e.printStackTrace(); } if (null != xmlParse) { Document doc = null; try { doc = xmlParse.parseDocument(path); } catch (MalformedURLException e) { System.out.println("异常:传入文件路径错误!找不到要解析的文件!"); e.printStackTrace(); } catch (SAXParseException e) { System.out.println("异常:文件格式错误!无法解析!"); e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } if (null != doc) { NodeList bookNodeList = null; try { /** * [title/@lang='en']表示选取的book节点,必须满足子节点title的lang属性为en */ bookNodeList = (NodeList) xmlParse.selectNodes(doc, "//bookstore/book[title/@lang='en']"); } catch (XPathExpressionException e) { System.out.println("异常:XPath表达式错误!"); e.printStackTrace(); } if (null != bookNodeList) { List<Book> bookList = new ArrayList<Book>(); for (int i = 0; i < bookNodeList.getLength(); i++) { Node node = bookNodeList.item(i); Book book = parseBookNode(xmlParse, node); bookList.add(book); } for (Book book : bookList) { System.out.println(book.toString()); } } } } } /** * 解析单个book节点 * * @param util * @param node * @return * @throws XPathExpressionException * @see [类、类#方法、类#成员] */ public static Book parseBookNode(XMLParseUtil util, Node node) { String lang = ""; String title = ""; String author = ""; String year = ""; String price = ""; try { title = util.getNodeStringValue(node, "./title"); } catch (XPathExpressionException e) { System.out.println("异常:XPath表达式错误!"); e.printStackTrace(); } try { lang = util.getNodeStringValue(node, "./title/@lang"); } catch (XPathExpressionException e) { System.out.println("异常:XPath表达式错误!"); e.printStackTrace(); } try { author = util.getNodeStringValue(node, "./author"); } catch (XPathExpressionException e) { System.out.println("异常:XPath表达式错误!"); e.printStackTrace(); } try { year = util.getNodeStringValue(node, "./year"); } catch (XPathExpressionException e) { System.out.println("异常:XPath表达式错误!"); e.printStackTrace(); } try { price = util.getNodeStringValue(node, "./price"); } catch (XPathExpressionException e) { System.out.println("异常:XPath表达式错误!"); e.printStackTrace(); } Book book = new Book(lang, title, author, year, price); return book; } }
上面的测试类所使用的XML文件
文件名 : bookstore.xml
文件路径 : 与上面的两个类放到同一目录下
<?xml version="1.0" encoding="gbk"?> <bookstore> <book> <title lang="en">Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>28.5</price> </book> <book> <title lang="en">Junit IN Action</title> <author>Robert J.</author> <year>2007</year> <price>58.5</price> </book> <book> <title lang="en">Struts 2 IN Action</title> <author>Rhodes K.R</author> <year>2005</year> <price>53.6</price> </book> <book> <title lang="en">Thinking of Java 4th</title> <author>Bruce Eckel</author> <year>2007</year> <price>78.9</price> </book> <book> <title lang="zh">修炼架构师之道</title> <author>陈杰驰</author> <year>2009</year> <price>63.5</price> </book> <book> <title lang="zh">哲学:心灵,宇宙</title> <author>ChenFeng</author> <year>2010</year> <price>96</price> </book> </bookstore>
适用于项目中的写法(XML Node→Object)
解析一个XML节点,直接转换为一个对象并返回给调用者
解析XML返回对象的封装类
...
import java.io.File; import java.io.IOException; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPathExpressionException; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import cn.chenfeng.common.ServiceException; public class XMLParseManager { private XMLParseUtil xmlParser; public XMLParseManager() { try { xmlParser = new XMLParseUtil(); } catch (ParserConfigurationException e) { throw new ServiceException("XMLParseManager@XMLParseManager(): " + "Failed to create XML parser!" + e); } } /** * 初始化方法,通过文件对象初始化XML解析器和文档对象 * * @param xmlParser * @param document * @param file * @see [类、类#方法、类#成员] */ private Document getDocument(File file) { Document document = null; try { document = xmlParser.parseDocument(file); } catch (IllegalArgumentException e) { throw new ServiceException("XMLParseManager@getDocument: " + "An illegal or inappropriate argument!" + e); } catch (SAXParseException e) { throw new ServiceException("XMLParseManager@getDocument: " + "XML file error, can not parse!" + e); } catch (SAXException e) { throw new ServiceException("XMLParseManager@getDocument: " + "There is a SAXException!" + e); } catch (IOException e) { throw new ServiceException("XMLParseManager@getDocument: " + "There is an IOException!" + e); } return document; } /** * 获取节点的值 * * @return nodeValue * @see [类、类#方法、类#成员] */ private String getNodeValue(Node node, String xpath) { String nodeValue = null; try { nodeValue = xmlParser.getNodeStringValue(node, xpath); } catch (XPathExpressionException e) { throw new ServiceException("XMLParseManager@getNodeValue: " + "XPath expression [" + xpath + "] error!" + e); } return nodeValue; } /** * 根据作者姓名获取书籍 * * @param file * XML文件对象 * @param name * 书籍作者姓名 * @return myBook * @see [类、类#方法、类#成员] */ public Book getBookByAuthor(File file, String name) { Book myBook = null; if (null != file) { Document doc = getDocument(file); if (null != doc) { /* * [author='" + name + "'] 表示只取author为name参数值的book节点 */ String title = getNodeValue(doc, "//book[author='" + name + "']/title"); String lang = getNodeValue(doc, "//book[author='" + name + "']/title/@lang"); String author = getNodeValue(doc, "//book[author='" + name + "']/author"); String year = getNodeValue(doc, "//book[author='" + name + "']/year"); String price = getNodeValue(doc, "//book[author='" + name + "']/price"); myBook = new Book(lang, title, author, year, price); } } else { throw new ServiceException("XMLParseManager@getBookByAuthor: " + "File is null!"); } return myBook; } }
上面类的单元测试类
...
import java.io.File; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; public class XMLParseManagerTest { XMLParseManager xmlMgr; @Before public void setUp() throws Exception { xmlMgr = new XMLParseManager(); } @After public void tearDown() throws Exception { } @Test public void testGetMyBook() { String path = XMLParseManager.class.getResource("bookstore.xml") .getPath(); File xmlfile = new File(path); Book actualBook = xmlMgr.getBookByAuthor(xmlfile, "ChenFeng"); Assert.assertNotNull(actualBook); Book expectedBook = new Book("zh", "哲学:心灵,宇宙", "ChenFeng", 2010, 96.0); Assert.assertEquals(expectedBook, actualBook); } }
使用到的Bean类
...
package cn.chenfeng.XML.xpath; /** * Book类 * * @author ChenFeng * @version [版本号, 2009-12-21] * @see [相关类/方法] * @since [产品/模块版本] */ public class Book { private String lang; private String title; private String author; private int year; private double price; public Book() { } public Book(String lang, String title, String author, String year, String price) { this.lang = lang; this.title = title; this.author = author; this.year = (int) Integer.valueOf(year); this.price = (double) Double.valueOf(price); } public Book(String lang, String title, String author, int year, double price) { this.lang = lang; this.title = title; this.author = author; this.year = year; this.price = price; } public String getLang() { return lang; } public void setLang(String lang) { this.lang = lang; } 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 int getYear() { return year; } public void setYear(String year) { this.year = (int) Integer.valueOf(year); } public void setYear(int year) { this.year = year; } public double getPrice() { return price; } public void setPrice(String price) { this.price = (double) Double.valueOf(price); } public void setPrice(double price) { this.price = price; } public boolean equals(Object object) { Book b = (Book) object; if (this.lang.equals(b.getLang()) && this.title.equals(b.getTitle()) && this.author.equals(b.getAuthor()) && this.year == b.getYear() && this.price == b.price) { return true; } return false; } public String toString() { StringBuffer buf = new StringBuffer(""); buf.append("Book{\n").append(" lang=").append(lang) .append("\n title=").append(title).append("\n author=") .append(author).append("\n year=").append(year) .append("\n price=").append(price).append("\n}"); return buf.toString(); } }
完!