JAXP是java API for xml PRocessing的缩写。JAXP API主要的部分在javax.xml.parsers 这个包中。在这个包中,向用户提供了两个最重要的工厂类,SAXParserFactory 和DocumentBuilderFactory,相应地,提供了SAXParser 和DocumentBuilder两个类。
SAX是由XML-DEV定义的;DOM是由W3C定义的。让我们来看看这些API库。
SAX指一种"事件驱动"的处理方式,他对XML文件连续地一个对象一个对象地操作,由于它的这个特点,所以它可以用于服务器端或者对速度有非凡要求的地方。
相比较而言DOM是个使用起来更简单些。他是将所有个XML数据全部读到内存里面,然后使用"树"结构将这些数据组织起来,用户可以对XML的数据进行任意的操作。
至于XSLT,我们在这里就不介绍太多,假如感爱好请参考相应的资料。我们还是先看看SAX。
SAX
SAX的框架轮廓
系统是从SAXParserFactory产生parser的实例开始的。一个parser中包含了一个SAXReader对象,当这个parser调用parse方法的时候,这个reader就调用回调方法已实现这个应用;而这些方法呢?是定义在ContentHandler,ErrorHandler,DTDHandler and EntityResolver接口中的。
以下是对SAX API库的概述:
更具体地api介绍,请参看SAX的官方API文档。
例子:
在我们这个例子中,我们处理一个xml文件,然后将其值set到对象中。这是一个非经常用的使用情况。以下就是我们需要处理的xml文件。
Test.xml<?xml version="1.0" ?> <customers> <customer> <id>#001</id> <name>Micke</name> <address>Najing</address> </customer> <customer> <id>#002</id> <name>Car</name> <address>Suzhou</address> </customer> <customer> <id>#003</id> <name>Jimmy</name> <address>ChengDu</address> </customer> <customer> <id>#004</id> <name>Henry</name> <address>Xi'an</address> </customer></customers>
这是一个非常简单的xml文件,customers中间有数个customer,每一个customer中包含三个属性id, name, address。
根据这个xml文件,我们将Date Object设置如下。
/* * Customers.java * Create @ 2004-4-27 22:04:45 * by Jiabo */import java.util.*;/** * Customers * Create @ 2004-4-27 22:04:45 * by Jiabo */public class Customers { private Vector customers; public Customers() { customers = new Vector(); } public void addCustomer(Customer customer) { customers.add(customer); } public String toString() { String newline = System.getProperty("line.separator"); StringBuffer buf = new StringBuffer(); for (int i = 0; i < customers.size(); i++) { buf.append(customers.elementAt(i)).append(newline); } return buf.toString(); }}class Customer { private String id; private String name; private String address; /** * @return */ public String getAddress() { return address; } /** * @return */ public String getId() { return id; } /** * @return */ public String getName() { return name; } /** * @param string */ public void setAddress(String string) { address = string; } /** * @param string */ public void setId(String string) { id = string; } /** * @param string */ public void setName(String string) { name = string; } public String toString(){ return "Customer: ID='" + id + "' Name='" + name + "' Address='" + address + "'"; }}
接下来是xml的处理器。
/* * Test.java * Created on 2004-4-10 * by Jiabo */import java.util.*;import org.xml.sax.*;import org.xml.sax.helpers.DefaultHandler;/** * Test * Create on 2004-4-10 19:20:27 * by Jiabo */public class Unmarshaller extends DefaultHandler { private Customers customers; private Stack stack; private boolean isStackReadyForText; private Locator locator; /** * init */ public Unmarshaller() { stack = new Stack(); isStackReadyForText = false; } /** * @return customers */ public Customers getCustomers() { return customers; } /** * callbacks */ public void setDocumentLocator(Locator rhs) { locator = rhs; } //========================================== // SAX DocumentHandler methods //========================================== public void startElement( String uri, String sName, String qName, Attributes attrs) { isStackReadyForText = false; if (sName.equals("customers")) { stack.push(new Customers()); } else if (sName.equals("customer")) { stack.push(new Customer()); } else if ( sName.equals("id") sName.equals("name") sName.equals("address")) { stack.push(new StringBuffer()); isStackReadyForText = true; } else { } } public void endElement(String namespaceURI, String sName, String qName){ isStackReadyForText = false; Object temp = stack.pop(); if (sName.equals("customers")) { customers = (Customers) temp; } else if (sName.equals("customer")) { ((Customers) stack.peek()).addCustomer((Customer) temp); } else if (sName.equals("id")) { ((Customer) stack.peek()).setId(temp.toString()); } else if (sName.equals("name")) { ((Customer) stack.peek()).setName(temp.toString()); } else if (sName.equals("address")) { ((Customer) stack.peek()).setAddress(temp.toString()); } } public void characters(char[] data, int start, int length) { if (isStackReadyForText == true) { ((StringBuffer) stack.peek()).append(data, start, length); } else { } }}
在这里我们处理xml文件的思路非常简单,就是使用一个栈,碰到"<"表示element的开始,然后就看与我们既定的Data Object的名字是否相符合,符合就new一个该对象,并将其压栈;不符合就什么都不做,sax的处理框架就会自己去处理下一个element。而当碰到"/>"的时候我们还是看的他名字与DataObject的名字是否相符,相符合的话就出栈,然后set进对象里面。如此循环,就处理完了我们上面那个简单得xml文件。
我们需要做的事情就只有这些。其他如何处理的,handler回自己调用相应的startElement,endElement等方法去处理。
以下是程序的入口:
/* * main.java * Create @ 2004-4-27 22:18:41 * by Jiabo */import java.io.*;import javax.xml.parsers.*;import org.xml.sax.*;/** * main * Create @ 2004-4-27 22:18:41 * by Jiabo */public class Main { public static void main(String args[]) { Customers customers = null; if (args.length != 1) { System.err.println("Usage: cmd filename"); System.exit(1); } try { Unmarshaller handler = new Unmarshaller(); SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser saxParser = factory.newSAXParser(); File file = new File(args[0]); InputSource src = new InputSource(new FileInputStream(file)); saxParser.parse( src ,handler); customers = handler.getCustomers(); } catch (Throwable t) { t.printStackTrace(); } System.out.println(customers); }}
如前面所述,通过一个工厂方法得到一个SAXParser的实例,然后就可以编译这个xml文件了。这样你就可以得到如下结果:
Customer: ID ='#001' Name='Micke' Address='Najing' Customer: ID ='#002' Name='Car' Address='Suzhou' Customer: ID ='#003' Name='Jimmy' Address='ChengDu' Customer: ID ='#004' Name='Henry' Address='Xi'an'
Sax的系统框架中还有其他得好些方法,读者不妨试试他们是如何使用的,这对以后实战处理xml文件会有很大的方便。
新闻热点
疑难解答