Sax快速入门
来源:互联网 发布:婚庆音响设备数据 编辑:程序博客网 时间:2024/05/17 23:59
一、本教程旨在为希望运用SAX的Java程序员提供一份快速入门的教程。
二、基本的环境
Sax是一个用于各种各样的XML解析器(或者其他可以看做XML解析器的解析器)通用接口的实现,就像JDBC作为一个能供许多关系型
数据库的通用驱动的一样。如果你想用SAX,你需用如下的几样东西:
a. Java 1.1或更高版本
b. 一个能兼用SAX2(总共有这么几个版本:SAX2M,2001-11-12; SAX 2.0.1, 2002-1-29, SAX2.0.2, 2004-4-24)的XML解析器被安装
在你的Java classpath中
c. SAX2被安装在你的java classpath中(貌似Jdk已经集成了吧?)
大多数的Java/XML工具包括SAX2 和 XML解析器都用到SAX。大多数的web应用服务器也把它最为XML support的核心。特别强调的是,
JAXP 1.1 支持SAX2.
三、XML的解析
我们从创建DefaultHandler的一个子类开始:
import org.xml.sax.helpers.DefaultHandler;public class MySAXApp extends DefaultHandler{ public MySAXApp () {super(); }}
因为这是一个Java程序,我们将会创建一个Main方法来调用XMLReaderFactory 的createXMLReader方法来动态地选择一个SAX
驱动。注意了,在这里,我们只用了“throws Exception”,在真正的应用程序中,将会有容错处理:
public static void main (String args[])throws Exception {XMLReader xr = XMLReaderFactory.createXMLReader(); }
可能在你的Java环境中还没有整合默认的编译路径(或者可能是
META-INF/services/org.xl.sax.driver
system resource),那么你需要去为SAX driver设置 org.xml.sax.dirve 的Java 系统属性, 比如
java -Dorg.xml.sax.driver=com.example.xml.SAXDriver MySAXApp sample.xml下面是击中SAX2的驱动,它们的class names和相关信息如下:
gnu.xml.aelfred2.SAXDriver
Lightweight non-validating parser; Free Softwaregnu.xml.aelfred2.XmlReader
Optionally validates; Free Softwareoracle.xml.parser.v2.SAXParser
Optionally validates; proprietaryorg.apache.crimson.parser.XMLReaderImpl
Optionally validates; used in JDK 1.4; Open Sourceorg.apache.xerces.parsers.SAXParser
Optionally validates; Open Source或者,如果你不想在你的程序中使用指定的Sax drive, 你也可以直接用它的构造器。我们假设你的XML解析器叫做com.example.xml.SAXDriver,
这实际上可能不存在。你必须知道要知道用于解析的那个真正driver的名字,这样,可能进行如下操作:
public static void main (String args[])throws Exception {XMLReader xr = new com.example.xml.SAXDriver(); }我们用xr这个对象去解析XML文档,但是,我们必须先去注册一个事件handlers,以便于解析器用来report信息,从XMLReader中调用setConentHandler 和
setErrorHandler方法,在一个实际程序的应用中,这个hanlders通常要做成一个独立的对象,但是在这里,只是为了演示,我们把handlers绑定
在了最顶层的类中(即main方法所在的类),这样,我们必须去实例化这个顶层类并且为XML Reader这个解析器注册hanlders:
public static void main (String args[])throws Exception {XMLReader xr = XMLReaderFactory.createXMLReader();MySAXApp handler = new MySAXApp();xr.setContentHandler(handler);xr.setErrorHandler(handler); }
上面的代码创建了MySAXApp的一个实例去接受XML解析事件,并且把常规的content 事件和error 事件处理器注册到这个解析器上。
现在,就让我们来开始解析吧。
public static void main (String args[])throws Exception {XMLReader xr = XMLReaderFactory.createXMLReader();MySAXApp handler = new MySAXApp();xr.setContentHandler(handler);xr.setErrorHandler(handler);// Parse each file provided on the// command line.for (int i = 0; i < args.length; i++) { FileReader r = new FileReader(args[i]); xr.parse(new InputSource(r));} }
值得注意的是,每一个reader必须被包装成一个inputSource而被解析。以下是到目前为止这个demo的整个代码:
import java.io.FileReader;import org.xml.sax.XMLReader;import org.xml.sax.InputSource;import org.xml.sax.helpers.XMLReaderFactory;import org.xml.sax.helpers.DefaultHandler;public class MySAXApp extends DefaultHandler{ public static void main (String args[])throws Exception {XMLReader xr = XMLReaderFactory.createXMLReader();MySAXApp handler = new MySAXApp();xr.setContentHandler(handler);xr.setErrorHandler(handler);// Parse each file provided on the// command line.for (int i = 0; i < args.length; i++) { FileReader r = new FileReader(args[i]); xr.parse(new InputSource(r));} } public MySAXApp () {super(); }}你可以编译上述代码并且运行它。(需要确保的一点是,你因该在org.xml.sax.dirver property 文件中定义这个Sax driver class),如果
被解析的文档不是畸形的,这个程序将啥也不会出现(畸形的xml的话,会抛xml结构异常信息)。这是因为你还没为这个应用程序set up处理事件。
处理事件
当你开始去为XML解析实现响应方法时,这就会变得越来越有趣了。其中最重要的响应事件某过于文档的开始和结束,元素的开始和结束,字符数据
的处理。
为了找出document的start和end,这个应用程序必须实现startDocument和endDocument这两个方法:
public void startDocument () {System.out.println("Start document"); } public void endDocument () {System.out.println("End document"); }
这个start/endDocument 的event handler没有参数。当Sax driver一旦到达document的开头的时候,它会调用startDocument方法,一但到达结尾时,它会调用endDocument方法(即使这个文档存在一些错误)。
这个demo只是简单地输出了一些消息,但是,你的程序也可以在这个handler里增加任何你想要的代码。通常地,这些被增加的代码回去做
下面的几件事情:在momery中生成一些dom 树,输出,整合到database中,或者从XML stream中提取信息。
Sax driver将会通过同document一样的方式标志一个元素的start和end,这两个方法中会用一些参数被传递过来:
public void startElement (String uri, String name, String qName, Attributes atts) {if ("".equals (uri)) System.out.println("Start element: " + qName);else System.out.println("Start element: {" + uri + "}" + name); } public void endElement (String uri, String name, String qName) {if ("".equals (uri)) System.out.println("End element: " + qName);else System.out.println("End element: {" + uri + "}" + name); }
这个方法每次在遇到element start和end的时候,如果这个元素的namespace存在,它将会输出namespace和localname如果不存在namespace,
它将会输出它将会输出qName(qualified Name, 参考qName).
最后,SAX2通过characters这个方法显示一些常规的字符串数据。在下面的实现中,将会输出所有的字符数据(标签的文本数据)。代码可能有一点长
因为要编译一些特殊的字符:
public void characters (char ch[], int start, int length) {System.out.print("Characters: \"");for (int i = start; i < start + length; i++) { switch (ch[i]) { case '\\':System.out.print("\\\\");break; case '"':System.out.print("\\\"");break; case '\n':System.out.print("\\n");break; case '\r':System.out.print("\\r");break; case '\t':System.out.print("\\t");break; default:System.out.print(ch[i]);break; }}System.out.print("\"\n"); }
注意,因为SAX driver可以随意获取它想要的任意字符数据块,所以你不可能仅通过一个简单的characters事件就能计算出这个element的所有字符信息。
一下是关于characters的一个具体例子:
package com.aug.desmond.sax.start.test;import java.io.FileReader;import org.xml.sax.Attributes;import org.xml.sax.InputSource;import org.xml.sax.SAXException;import org.xml.sax.XMLReader;import org.xml.sax.helpers.DefaultHandler;import org.xml.sax.helpers.XMLReaderFactory;import static com.aug.desmond.util.Print.*;public class MySAXApp extends DefaultHandler {public static void main(String[] args) throws Exception{XMLReader xr = XMLReaderFactory.createXMLReader();MySAXApp handler = new MySAXApp();xr.setContentHandler(handler);xr.setErrorHandler(handler);for(int i=0; i<args.length; i++) {FileReader r = new FileReader(args[i]);xr.parse(new InputSource(r));}}@Overridepublic void characters(char ch[], int start, int length) throws SAXException {print(new String(ch, start, length));}@Overridepublic void endElement(String uri, String localName, String qName)throws SAXException {print("[end element] "+uri+","+localName+","+qName);}@Overridepublic void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {print("[start element] "+uri+","+localName+","+qName);}public MySAXApp() {super();}}XML文件:
<?xml version="1.0" encoding="UTF-8" ?><root><head/><body>world</body>out_of_tag_after_body<Chinese>China</Chinese></root>
输出的结果为:
[start element] ,root,root[start element] ,head,head[end element] ,head,head[start element] ,body,bodyworld[end element] ,body,bodyout_of_tag_after_body[start element] ,Chinese,ChineseChina[end element] ,Chinese,Chinese[end element] ,root,root
可以看出,
out_of_tag_after_body 在元素body 和Chinese之间,它也能够被Characters方法读出来,也就是说,Characters方法读的是tag之外的所有字符数据,
比如<a/><b/> 元素a,b之间即使没有数据,Characters也回去读它,只不过是空字符串而已。
Sax2的应用示例
下面是这个demo的全部代码:
import java.io.FileReader;import org.xml.sax.XMLReader;import org.xml.sax.Attributes;import org.xml.sax.InputSource;import org.xml.sax.helpers.XMLReaderFactory;import org.xml.sax.helpers.DefaultHandler;public class MySAXApp extends DefaultHandler{ public static void main (String args[])throws Exception {XMLReader xr = XMLReaderFactory.createXMLReader();MySAXApp handler = new MySAXApp();xr.setContentHandler(handler);xr.setErrorHandler(handler);// Parse each file provided on the// command line.for (int i = 0; i < args.length; i++) { FileReader r = new FileReader(args[i]); xr.parse(new InputSource(r));} } public MySAXApp () {super(); } //////////////////////////////////////////////////////////////////// // Event handlers. //////////////////////////////////////////////////////////////////// public void startDocument () {System.out.println("Start document"); } public void endDocument () {System.out.println("End document"); } public void startElement (String uri, String name, String qName, Attributes atts) {if ("".equals (uri)) System.out.println("Start element: " + qName);else System.out.println("Start element: {" + uri + "}" + name); } public void endElement (String uri, String name, String qName) {if ("".equals (uri)) System.out.println("End element: " + qName);else System.out.println("End element: {" + uri + "}" + name); } public void characters (char ch[], int start, int length) {System.out.print("Characters: \"");for (int i = start; i < start + length; i++) { switch (ch[i]) { case '\\':System.out.print("\\\\");break; case '"':System.out.print("\\\"");break; case '\n':System.out.print("\\n");break; case '\r':System.out.print("\\r");break; case '\t':System.out.print("\\t");break; default:System.out.print(ch[i]);break; }}System.out.print("\"\n"); }}输出
用到了如下的XML:
?xml version="1.0"?><poem xmlns="http://www.megginson.com/ns/exp/poetry"><title>Roses are Red</title><l>Roses are red,</l><l>Violets are blue;</l><l>Sugar is sweet,</l><l>And I love you.</l></poem>
如果这个文档的名字叫做roses.xml并且在你的classpath中有一个叫 com.example.xml.SAXDriver(这个driver实际上并不存在)的SAX2 driver,你可以通过如下的方式去
运行它:
java -Dorg.xml.sax.driver=com.example.xml.SAXDriver MySAXApp roses.xml输出结果如下:
Start documentStart element: {http://www.megginson.com/ns/exp/poetry}poemCharacters: "\n"Start element: {http://www.megginson.com/ns/exp/poetry}titleCharacters: "Roses are Red"End element: {http://www.megginson.com/ns/exp/poetry}titleCharacters: "\n"Start element: {http://www.megginson.com/ns/exp/poetry}lCharacters: "Roses are red,"End element: {http://www.megginson.com/ns/exp/poetry}lCharacters: "\n"Start element: {http://www.megginson.com/ns/exp/poetry}lCharacters: "Violets are blue;"End element: {http://www.megginson.com/ns/exp/poetry}lCharacters: "\n"Start element: {http://www.megginson.com/ns/exp/poetry}lCharacters: "Sugar is sweet,"End element: {http://www.megginson.com/ns/exp/poetry}lCharacters: "\n"Start element: {http://www.megginson.com/ns/exp/poetry}lCharacters: "And I love you."End element: {http://www.megginson.com/ns/exp/poetry}lCharacters: "\n"End element: {http://www.megginson.com/ns/exp/poetry}poemEnd document
如果这个roses.xml没有包含 xmlns="http://www.megginson.com/ns/exp/poetry" 这个名空间属性去申明所有的元素将都在这个名空间下,那么,就会有以下形式的输出:
Start documentStart element: poemCharacters: "\n"Start element: titleCharacters: "Roses are Red"End element: titleCharacters: "\n"Start element: lCharacters: "Roses are red,"End element: lCharacters: "\n"Start element: lCharacters: "Violets are blue;"End element: lCharacters: "\n"Start element: lCharacters: "Sugar is sweet,"End element: lCharacters: "\n"Start element: lCharacters: "And I love you."End element: lCharacters: "\n"End element: poemEnd document
你可能用到这两种类型的document:一种用了namespace,另一种没有。对于element(或attributes),也存在同样的情况。因此,要具体情况
具体分析以便写出合适的code。
Element 的Attributes
element的attributes也可以有namespace,用法和element的一样。下面是一个demo:
XML:
<?xml version="1.0" encoding="UTF-8" ?><root xmlns="http://www.desmond.com" xmlns:attr="https://www.presley.com"><head hd="hd" isHead="true"/><body attr:bd="bd">world</body><Chinese cn="cn" zone="8">China</Chinese></root>
Code:
package com.aug.desmond.sax.start.test;import java.io.FileReader;import org.xml.sax.Attributes;import org.xml.sax.InputSource;import org.xml.sax.SAXException;import org.xml.sax.XMLReader;import org.xml.sax.helpers.DefaultHandler;import org.xml.sax.helpers.XMLReaderFactory;import static com.aug.desmond.util.Print.*;public class MySAXApp extends DefaultHandler {public static void main(String[] args) throws Exception{XMLReader xr = XMLReaderFactory.createXMLReader();MySAXApp handler = new MySAXApp();xr.setContentHandler(handler);xr.setErrorHandler(handler);for(int i=0; i<args.length; i++) {FileReader r = new FileReader(args[i]);xr.parse(new InputSource(r));}}@Overridepublic void startElement(String uri, String localName,String qName, Attributes attributes) throws SAXException {print("[element] uri="+uri+", localName="+localName);print("length of attributes=" + attributes.getLength());// get info of each attributefor(int i = 0; i < attributes.getLength(); i++) {System.out.print("[uri="+ attributes.getURI(i)+ ",qName=" + attributes.getQName(i) + ",localName=" + attributes.getLocalName(i) + ", type=" + attributes.getType(i)+ ",value=" + attributes.getValue(i) + "]");}// get attribute by qNameprint("zone="+attributes.getValue("zone"));print("bd="+attributes.getValue("attr:bd"));// get attribute by uri, localNameprint("bd="+attributes.getValue("https://www.presley.com", "bd"));print("*************************");}public MySAXApp() {super();}}
Output:
[element] uri=http://www.desmond.com, localName=rootlength of attributes=0zone=nullbd=nullbd=null*************************[element] uri=http://www.desmond.com, localName=headlength of attributes=2[uri=,qName=hd,localName=hd, type=CDATA,value=hd][uri=,qName=isHead,localName=isHead, type=CDATA,value=true]zone=nullbd=nullbd=null*************************[element] uri=http://www.desmond.com, localName=bodylength of attributes=1[uri=https://www.presley.com,qName=attr:bd,localName=bd, type=CDATA,value=bd]zone=nullbd=bdbd=bd*************************[element] uri=http://www.desmond.com, localName=Chineselength of attributes=2[uri=,qName=cn,localName=cn, type=CDATA,value=cn][uri=,qName=zone,localName=zone, type=CDATA,value=8]zone=8bd=nullbd=null*************************
来自:http://www.saxproject.org/quickstart.html
- Sax快速入门
- SAX入门
- javawebday08(sax解析入门)
- xml--android--SAX快速上手
- Android入门开发之SAX
- SAX解析XML(入门)
- SAX轻松入门(二)--带验证的SAX解析
- SAX轻松入门(三)--SAX过滤器(filter)
- 快速入门
- Java解析XML文档SAX入门案例
- SAX
- SAX
- sax
- sax
- SAX
- sax
- SAX
- Sax
- 闪回数据归档的实验-oracle total recall
- 一些自己出差常用网站
- 一场讲座
- Android.mk预编译第三方静态库
- 关于C++中static关键字的几点总结
- Sax快速入门
- 没有下载积分,有没有好人给一点
- apache配置php的LoadModule php5_module "XX"引起apache启动服务opration failed错误解决
- SRWLock
- 以前能跑步的时候
- python操作Excel读写--使用xlrd
- C++中关于虚拟继承的一些总结
- c:forEach varStatus属性
- Ubuntu:重设密码