开发javaWEB项目,经常都要遇到xml文件,我们只要在xml配置项目的一些属性,那么项目就可以按我们所想的运作了。那么xml文件的数据是如何转化为系统可以识别的信息呢?这就需要解析xml文件了。
要解析xml文件就要有xml解析器,比较著名的有Apache的Xerces,微软的MSXML,Oracle的XMLParser等。如果系统要更换解析器就要修改源代码,那也太不人道了。幸运的事,这些解析器大都支持两套API:DOM和SAX,因此,我们针对DOM接口或SAX接口编程可以极大简化更改解析器时代码的修改。
另外,Oracle制定的JAXP规范在解析器之上提供了一层抽象,使我们可以独立于厂商API进行编程。在JavaSE中,JAXP的开发包由javax.xml,org.w3c.dom和org.xml.sax三个包组成。其中javax.xml.parsers包中定义了几个工厂方法用于加载DOM或SAX的实现类。其实现类可以很方便地更换,只要修改制定文件的一些配置即可。这个后面细讲。
因此针对JAXP编程可以随意更换解析器而不用修改任何的源代码。
以下具体说说DOM和SAX。
先说DOM吧。DOM把xml文档处理成一棵节点树,xml的元素,属性,文本,注释,数据段等在DOM中都有对应的类。且看类图:
有了这张图,再看后面的代码应该能容易一些。给出一个例子吧:
books.xml内容如下:
<?xml version="1.0" encoding="utf-8"?> <books> <book name="java"> <author>Bruce</author> <price>100</price> </book> <book name="c++"> <author>Dinail</author> <price>80</price> </book> </books>
代码如下:
import java.io.File; import java.io.IOException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; 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 SimpleTest { public void test(){ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();//获得解析器实现类,获取方法后面讲 try { DocumentBuilder db = dbf.newDocumentBuilder(); Document d = db.parse(new File("books.xml")); NodeList nl = d.getElementsByTagName("book");//获得所有的book节点 for(int i = 0;i < nl.getLength();i++){ Element e = (Element)nl.item(i);//将book节点转换成元素 String bookname = nl.item(i).getAttributes().item(0).getNodeValue();//获得book节点的属性列表,然后是第一个属性并得到其值 Node n1 = e.getElementsByTagName("author").item(0); Node n2 = e.getElementsByTagName("price").item(0); String author = n1.getFirstChild().getNodeValue(); String price = n2.getLastChild().getNodeValue(); System.out.println("bookname:"+bookname+"\n\tauthor:"+author+"\n\tprice:"+price); } } catch (ParserConfigurationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SAXException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void main(String[] args) { new SimpleTest().test(); } }
应该注意的是,<book>与<author>之间有一个text节点,类似的,还有其他一些空白节点。其他的注释已经讲的清楚了,以下是输出:
bookname:java author:Bruce price:100 bookname:c++ author:Dinail price:80
ok,回到上面的一个问题,如果要换解析器怎么办呢?或者说DocumentBuilderFactory.newInstance()是怎么找到实现类的呢?且听我细细道来。
关键之处在于javax.xml.parsers.DocumentBuilderFactory这个系统属性的设置。
可以通过System.setProperty("javax.xml.parsers.DocumentBuilderFactory","org.apache.parsers.jaxp.DocumentBuilderFactoryImp")
可以在执行时指定:java -Djavax.xml.parsers.DocumentBuilderFactory=org.apache.parsers.jaxp.DocumentBuilderFactoryImp
可以在jre/lib下添加jaxp.properties文件并添加一条记录:javax.xml.parsers.DocumentBuilderFactory=org.apache.parsers.jaxp.DocumentBuilderFactoryImp
如果都没找到,那就使用JDK自带的解析器了,在com\sun\org\apache\xerces\internal下
以下是SAX解析xml的一个例子,xml文件用上面那个:
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.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class SimpleTest { public void test(){ SAXParserFactory spf = SAXParserFactory.newInstance(); try { SAXParser sp = spf.newSAXParser(); sp.parse(new File("books.xml"),new SAXHandler()); } catch (ParserConfigurationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SAXException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void main(String[] args) { // TODO Auto-generated method stub new SimpleTest().test(); } } class SAXHandler extends DefaultHandler{ @Override public void startDocument() throws SAXException{ System.out.println("start parsing"); } @Override public void startElement(String uri,String localName,String qName,Attributes attr) throws SAXException{ System.out.print("<"+qName); int length = attr.getLength(); for(int i = 0;i < length;i++){ System.out.print(" "+attr.getQName(i)+"="+attr.getValue(i)); } System.out.print(">"); } @Override public void characters(char[] buf,int start,int length) throws SAXException{ System.out.print(new String(buf,start,length)); } @Override public void endElement(String uri,String qName) throws SAXException{ System.out.print("</"+qName+">"); } }ok,可以看出,SAX使用基于事件的机制,解析xml文档时要指定处理类,处理类指定遇到开始元素怎么办,遇到文本怎么办,遇到结束怎么办等等,详细资料可以查阅相关文档。 原文链接:https://www.f2er.com/xml/298731.html