j2ee —— 第 5 章 simple api for xml(sax). 何时使用 sax sax :状态无关 (stax...
TRANSCRIPT
J2EE—— 第 5 章Simple API for XML(SAX)
何时使用 SAX SAX :状态无关 (StAX :状态相关 ) 事件驱动模型,不能倒退到文档前面部分 SAX 与 DOM :相同的错误处理、处理验证错误 何时使用 SAX
把现有数据转换成 XML 速度快,效率高
何时使用 DOM 修改 XML 结构,交互修改 jdom, dom4j
回显具有 SAX 解析器的 XML文件
public class Echo { public static void main(String argv[]) { } }
导入类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;
针对 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;
实现 ContentHandler 接口public class Echo extends DefaultHandl
er { ... } startDocument endDocument startElement endElement characters SAXException
设置解析器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 );
}
编写输出private void emit(String s)throws SAXException{
try {out.write(s);out.flush();
} catch (IOException e) {
throw new SAXException("I/O error", e);}
}
隔开输出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);}
文档事件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);
}}
元素开始事件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(">");}
元素结束事件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+">"); }
字符事件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); }
}
回显字符private void echoText() throws SAXExce
ption {if (textBuffer == null) return;String s = ""+textBuffer;emit(s);textBuffer = null;
}
调用回显字符函数public void startElement(...) throws SAXException {
echoText(); String eName = sName; // element name...
}public void endElement(...) throws SAXException {
echoText(); String eName = sName; // element name...
}
编译和运行程序 javac Echo.java java Echo slideSample.xml C:\dvlp\Sun\AppServer\jdk\jre\lib\rt.ja
r 程序输出
没有注释 元素属性在一行中 <item/> 和 <item></item> 是一样的
确定引起空行的事件private void echoText() throws SAXException
{if (textBuffer == null) return; nl();emit("CHARS: |");String s = ""+textBuffer;emit(s);emit("|"); textBuffer = null;
}
确定引起空行的事件:结果 CHARS: | | 空行是由 characters 事件引起的 压缩输出public void echoText() throws SAXException {
nl();emit("CHARS: "); String s = ""+textBuffer;if (!s.trim().equals(“”)) emit(s);
}
回显解释器发送的每个字符集public void characters(char buf[], int offset, int len)throws SAXException {
if (textBuffer != null) {echoText();textBuffer = null;
}
String s = new String(buf, offset, len);...
}
管理缩进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--;
}
输出缩进private void nl() throws SAXException {
...try {out.write(lineEnd);for (int i=0; i < indentLevel; i++)
out.write(indentString);} catch (IOException e) {
...}
}
检查输出ELEMENT: <slideshow ... > CHARS: CHARS:
ELEMENT: <slide...END_ELM: </slide>
CHARS:CHARS:
确定文档位置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
显示处理指令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: ...
处理 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>"
处理 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();
}
其它异常catch (ParserConfigurationException pce) {
// Parser with specified options can't be builtpce.printStackTrace();
}catch (IOException ioe) {
// I/O errorioe.printStackTrace();
}
处理非致命错误和警告// 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());
}
显示特殊字符和 CDATA 实体引用:Market Size < predicted 输出:CHARS: Market Size < predicted CDATA 段:不需要替换特殊字符
用 DTD 解析 <!ELEMENT slideshow (slide+)> 解析器不再传递以前正确回显的围绕 slide 元素的空白
字符 可忽略空白public void ignorableWhitespace (char buf[], int offse
t, int Len) throws SAXException { nl();emit("IGNORABLE");
} 回显实体引用(内部实体,外部实体)
使用验证解析器// 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);
建立合适的错误处理程序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' >
试验验证错误 没有 DTD XML 和 DTD 不匹配
<!ELEMENT slide(image?, title, item*)> 元素没有在 DTD 中定义
<em>
解析参数化 DTD slideshow2.dtd 引用 xhtml.dtd title 定义冲突 , 换名或使用名称空间解决 DTD 警告
非验证:重复声明 DTD 中引用未声明的元素 为没有声明的元素类型声明属性
XML 的 SAX 解析器警告 验证时没有 <!DOCTYPE …> 非验证:引用一个未定义的参数实体 字符编码声明不正确
处理词法事件 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()
使用 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();
设置词法处理程序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);
}
使用 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)