j2ee —— 第 5 章 simple api for xml(sax). 何时使用 sax sax :状态无关 (stax...

38
J2EE—— 第 5 第 Simple API for XML(SA X)

Upload: charleen-morris

Post on 04-Jan-2016

412 views

Category:

Documents


8 download

TRANSCRIPT

Page 1: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

J2EE—— 第 5 章Simple API for XML(SAX)

Page 2: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误 何时使用 SAX

把现有数据转换成 XML 速度快,效率高

何时使用 DOM 修改 XML 结构,交互修改 jdom, dom4j

Page 3: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

回显具有 SAX 解析器的 XML文件

public class Echo { public static void main(String argv[]) { } }

Page 4: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

导入类import java.io.*;import org.xml.sax.*;import org.xml.sax.helpers.DefaultHandler;import javax.xml.parsers.SAXParserFactory;import javax.xml.parsers.ParserConfigurationExcep

tion;import javax.xml.parsers.SAXParser;

Page 5: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

针对 I/O 进行设置public static void main(String argv[]) {

if (argv.length != 1) { System.err.println("Usage: cmd filename"); System.exit(1);

} try {

// Set up output stream out = new OutputStreamWriter(System.out, "UTF8");

} catch (Throwable t) {

t.printStackTrace(); } System.exit(0);

} static private Writer out;

Page 6: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

实现 ContentHandler 接口public class Echo extends DefaultHandl

er { ... } startDocument endDocument startElement endElement characters SAXException

Page 7: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

设置解析器DefaultHandler handler = new Echo();SAXParserFactory factory = SAXParserFactory.newInstance(); try {

out = new OutputStreamWriter(System.out, "UTF8"); SAXParser saxParser = factory.newSAXParser();saxParser.parse( new File(argv[0]), handler );

}

Page 8: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

编写输出private void emit(String s)throws SAXException{

try {out.write(s);out.flush();

} catch (IOException e) {

throw new SAXException("I/O error", e);}

}

Page 9: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

隔开输出private void nl()throws SAXException{String lineEnd = System.getProperty("line.sep

arator"); try {

out.write(lineEnd);} catch (IOException e) {

throw new SAXException("I/O error", e);}

Page 10: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

文档事件public void startDocument() throws SAXException {

emit("<?xml version='1.0' encoding='UTF-8'?>");nl();

}public void endDocument() throws SAXException {

try {nl();out.flush();

} catch (IOException e) {throw new SAXException("I/O error", e);

}}

Page 11: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

元素开始事件public void startElement(String namespaceURI,String sName, // simple nameString qName, // qualified nameAttributes attrs) throws SAXException {

String eName = sName; // element name

if ("".equals(eName)) eName = qName; // not namespace-aware emit("<"+eName); if (attrs != null) {

for (int i = 0; i < attrs.getLength(); i++) { String aName = attrs.getLocalName(i); // Attr name if ("".equals(aName)) aName = attrs.getQName(i); emit(" "); emit(aName+"=\""+attrs.getValue(i)+"\"");

}}

emit(">");}

Page 12: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

元素结束事件public void endElement(String namespaceURI,String sName, // simple nameString qName // qualified name) throws SAXException {

String eName = sName; // element name if ("".equals(eName)) eName = qName; // not namespace-aware

emit("</"+eName+">"); }

Page 13: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

字符事件StringBuffer textBuffer; public void characters(char buf[], int offset,

int len) throws SAXException { String s = new String(buf, offset, len);if (textBuffer == null) {

textBuffer = new StringBuffer(s); } else {

textBuffer.append(s); }

}

Page 14: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

回显字符private void echoText() throws SAXExce

ption {if (textBuffer == null) return;String s = ""+textBuffer;emit(s);textBuffer = null;

}

Page 15: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

调用回显字符函数public void startElement(...) throws SAXException {

echoText(); String eName = sName; // element name...

}public void endElement(...) throws SAXException {

echoText(); String eName = sName; // element name...

}

Page 16: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

编译和运行程序 javac Echo.java java Echo slideSample.xml C:\dvlp\Sun\AppServer\jdk\jre\lib\rt.ja

r 程序输出

没有注释 元素属性在一行中 <item/> 和 <item></item> 是一样的

Page 17: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

确定引起空行的事件private void echoText() throws SAXException

{if (textBuffer == null) return; nl();emit("CHARS: |");String s = ""+textBuffer;emit(s);emit("|"); textBuffer = null;

}

Page 18: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

确定引起空行的事件:结果 CHARS: | | 空行是由 characters 事件引起的 压缩输出public void echoText() throws SAXException {

nl();emit("CHARS: "); String s = ""+textBuffer;if (!s.trim().equals(“”)) emit(s);

}

Page 19: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

回显解释器发送的每个字符集public void characters(char buf[], int offset, int len)throws SAXException {

if (textBuffer != null) {echoText();textBuffer = null;

}

String s = new String(buf, offset, len);...

}

Page 20: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

管理缩进private String indentString = " "; private int indentLevel = 0;public void startElement(...) throws SAXException {

indentLevel++; …

}public void endElement(...) throws SAXException {

nl();emit("END_ELM: ");emit("</"+sName+">");indentLevel--;

}

Page 21: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

输出缩进private void nl() throws SAXException {

...try {out.write(lineEnd);for (int i=0; i < indentLevel; i++)

out.write(indentString);} catch (IOException e) {

...}

}

Page 22: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

检查输出ELEMENT: <slideshow ... > CHARS: CHARS:

ELEMENT: <slide...END_ELM: </slide>

CHARS:CHARS:

Page 23: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

确定文档位置public void setDocumentLocator(Locator l) {

try {out.write("LOCATOR");out.write("SYS ID: " + l.getSystemId() );out.flush();

} catch (IOException e) {// Ignore errors

}}LOCATORSYS ID: file:<path>/../samples/slideSample01.xml

Page 24: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

显示处理指令public void processingInstruction(String target, String data) thro

ws SAXException { nl();emit("PROCESS: ");emit("<?"+target+" "+data+"?>");

} ELEMENT: <slideshow ... > PROCESS: <?my.presentation.Program QUERY="exec, tech, all"?>CHARS: ...

Page 25: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

处理 SAXParseException} catch (SAXParseException spe) {

// Error generated by the parserSystem.out.println("\n** Parsing error" + ", line " + spe.getLineNumber() + ", uri " + spe.getSystemId());System.out.println(" " + spe.getMessage() );

}** Parsing error, line 22, uri file:<path>/ slideSampleBa

d1.xml The element type "item" must be terminated by the matching end-tag “</item>"

Page 26: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

处理 SAXExceptioncatch (SAXException sxe) {

// Error generated by this application// (or a parser-initialization error)Exception x = sxe;if (sxe.getException() != null)

x = sxe.getException();x.printStackTrace();

}

Page 27: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

其它异常catch (ParserConfigurationException pce) {

// Parser with specified options can't be builtpce.printStackTrace();

}catch (IOException ioe) {

// I/O errorioe.printStackTrace();

}

Page 28: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

处理非致命错误和警告// treat validation errors as fatalpublic void error(SAXParseException e)throws SAXParseException{

throw e;}// dump warnings toopublic void warning(SAXParseException err) throws SAXParseException

{System.out.println("** Warning" + ", line " + err.getLineNumber()

+ ", uri " + err.getSystemId()); System.out.println(" " + err.getMessage());

}

Page 29: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

显示特殊字符和 CDATA 实体引用:Market Size &lt; predicted 输出:CHARS: Market Size < predicted CDATA 段:不需要替换特殊字符

Page 30: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

用 DTD 解析 <!ELEMENT slideshow (slide+)> 解析器不再传递以前正确回显的围绕 slide 元素的空白

字符 可忽略空白public void ignorableWhitespace (char buf[], int offse

t, int Len) throws SAXException { nl();emit("IGNORABLE");

} 回显实体引用(内部实体,外部实体)

Page 31: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

使用验证解析器// Use the validating parser SAXParserFactory factory = SAXParserFactory.newInstance(); factory.setValidating(true);

用 XML Schema 验证static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.

com/xml/jaxp/properties/schemaLanguage"; static final String W3C_XML_SCHEMA = "http://www.w3.org/200

1/XMLSchema"; factory.setNamespaceAware(true); saxParser.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_S

CHEMA);

Page 32: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

建立合适的错误处理程序try {

saxParser.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);

} catch (SAXNotRecognizedException x) {

// Happens if the parser does not support JAXP 1.2 ... } 关联文档和 Schema<documentRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation='YourSchemaDefinition.xsd' >

Page 33: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

试验验证错误 没有 DTD XML 和 DTD 不匹配

<!ELEMENT slide(image?, title, item*)> 元素没有在 DTD 中定义

<em>

Page 34: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

解析参数化 DTD slideshow2.dtd 引用 xhtml.dtd title 定义冲突 , 换名或使用名称空间解决 DTD 警告

非验证:重复声明 DTD 中引用未声明的元素 为没有声明的元素类型声明属性

XML 的 SAX 解析器警告 验证时没有 <!DOCTYPE …> 非验证:引用一个未定义的参数实体 字符编码声明不正确

Page 35: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

处理词法事件 org.xml.sax.ext.LexicalHandler 识别注释、 CDATA 段和对已解析实体的引用 LexicalHandler如何工作

comment(String comment) startCDATA(), endCDATA() startEntity(String name), endEntity(String nam

e) startDTD(String name, String publicId, String

systemId), endDTD()

Page 36: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

使用 LexcicalHandlerimport org.xml.sax.ext.LexicalHandler;public class Echo extends HandlerBase implements LexicalHandler {

public static void main(String argv[]) {

... // Use an instance of ourselves as the SAX event handler DefaultHandler handler = new Echo(); Echo handler = new Echo();

Page 37: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

设置词法处理程序SAXParser saxParser = factory.newSAXParser(); XMLReader xmlReader = saxParser.getXMLReader();xmlReader.setProperty( "http://xml.org/sax/properti

es/lexical-handler", handler ); 回显注释public void comment(char[] ch, int start, int length) t

hrows SAXException { String text = new String(ch, start, length);nl();emit("COMMENT: "+text);

}

Page 38: J2EE —— 第 5 章 Simple API for XML(SAX). 何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误

使用 DTDHandler 和 EntityResolver

未解析的实体或符号声明: DTDHandler

<!ENTITY myEntity SYSTEM "..URL.." NDATA gif>

<!NOTATION gif SYSTEM "..URL.."> notationDecl(String name, String publicId, String syst

emId) unparsedEntityDecl(String name, String publicId, Stri

ng systemId, String notationName) 公有 ID(URN) 转换成系统 ID(URL)resolveEntity(String publicId, String systemId)