新增鏈接http://m.blog.csdn.net/article/details?id=7305068,這一篇更加實用躯泰,不過概念偏少谭羔。
DOM和SAX的最終作用是可以讓我們利用java JavaScript等語言來獲取xml文件中的節(jié)點及文本、屬性等信息麦向。
本文引自其他博客瘟裸,內容易懂,為了節(jié)省時間诵竭,直接摘抄過來了话告。
http://yangjunfeng.iteye.com/blog/401377
? JAVA 解析 XML 通常有兩種方式,DOM 和 SAX卵慰。DOM 雖然是 W3C 的標準沙郭,提供了標準的解析方式,但它的解析效率一直不盡如人意裳朋,因為使用DOM解析XML時病线,解析器讀入整個文檔并構建一個駐留內存的樹結構(節(jié)點樹),然后您的代碼才可以使用 DOM 的標準接口來操作這個樹結構。但大部分情況下我們只對文檔的部分內容感興趣送挑,根本就不用先解析整個文檔绑莺,并且從節(jié)點樹的根節(jié)點來索引一些我們需要的數(shù)據(jù)也是非常耗時的。
SAX是一種XML解析的替代方法惕耕。相比于文檔對象模型DOM纺裁,SAX 是讀取和操作 XML 數(shù)據(jù)的更快速、更輕量的方
法赡突。SAX 允許您在讀取文檔時處理它对扶,從而不必等待整個文檔被存儲之后才采取操作。它不涉及 DOM 所必需的開銷和概念跳躍惭缰。 SAX API是一個基于事件的API 浪南,適用于處理數(shù)據(jù)流,即隨著數(shù)據(jù)的流動而依次處理數(shù)據(jù)漱受。SAX API
在其解析您的文檔時發(fā)生一定事件的時候會通知您络凿。在您對其響應時,您不作保存的數(shù)據(jù)將會 被拋棄昂羡。
下面是一個SAX解析XML的示例(有點長絮记,因為詳細注解了SAX事件處理的所有方法),SAX API中主要有四種處理事件的接口虐先,它們分別是ContentHandler怨愤,DTDHandler, EntityResolver 和 ErrorHandler 蛹批。下面的例子可能有點冗長撰洗,實際上只要繼承DefaultHandler 類 ,再覆蓋一部分 處理事件的方法 同樣可以達到這個示例的效果腐芍,但為了縱觀全局差导,還是看看SAX API里面所有主要的事件解析方法吧。( 實際上DefaultHandler就是實現(xiàn)了上面的四個事件處理器接口猪勇,然后提供了每個抽象方法的默認實現(xiàn)设褐。)
1,ContentHandler 接口 :接收文檔邏輯內容的通知 的處理器接口泣刹。
Java代碼 ?收藏代碼
'import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
class MyContentHandler implements ContentHandler{
StringBuffer jsonStringBuffer ;
int frontBlankCount = 0;
public MyContentHandler(){
jsonStringBuffer = new StringBuffer();
}
/*
* 接收字符數(shù)據(jù)的通知助析。
* 在DOM中 ch[begin:end] 相當于Text節(jié)點的節(jié)點值(nodeValue)
*/
@Override
public void characters(char[] ch, int begin, int length) throws SAXException {
StringBuffer buffer = new StringBuffer();
for(int i = begin ; i < begin+length ; i++){
switch(ch[i]){
case '\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\':buffer.append("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\");break;
case '\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\r':buffer.append("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\r");break;
case '\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n':buffer.append("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n");break;
case '\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\t':buffer.append("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\t");break;
case '\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"':buffer.append("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"");break;
default : buffer.append(ch[i]);
}
}
System.out.println(this.toBlankString(this.frontBlankCount)+
">>> characters("+length+"): "+buffer.toString());
}
/*
* 接收文檔的結尾的通知。
*/
@Override
public void endDocument() throws SAXException {
System.out.println(this.toBlankString(--this.frontBlankCount)+
">>> end document");
}
/*
* 接收文檔的結尾的通知椅您。
* 參數(shù)意義如下:
* ? ?uri :元素的命名空間
* ? ?localName :元素的本地名稱(不帶前綴)
* ? ?qName :元素的限定名(帶前綴)
*
*/
@Override
public void endElement(String uri,String localName,String qName)
throws SAXException {
System.out.println(this.toBlankString(--this.frontBlankCount)+
">>> end element : "+qName+"("+uri+")");
}
/*
* 結束前綴 URI 范圍的映射外冀。
*/
@Override
public void endPrefixMapping(String prefix) throws SAXException {
System.out.println(this.toBlankString(--this.frontBlankCount)+
">>> end prefix_mapping : "+prefix);
}
/*
* 接收元素內容中可忽略的空白的通知。
* 參數(shù)意義如下:
* ? ? ch : 來自 XML 文檔的字符
* ? ? start : 數(shù)組中的開始位置
* ? ? length : 從數(shù)組中讀取的字符的個數(shù)
*/
@Override
public void ignorableWhitespace(char[] ch, int begin, int length)
throws SAXException {
StringBuffer buffer = new StringBuffer();
for(int i = begin ; i < begin+length ; i++){
switch(ch[i]){
case '\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\':buffer.append("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\");break;
case '\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\r':buffer.append("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\r");break;
case '\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n':buffer.append("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n");break;
case '\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\t':buffer.append("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\t");break;
case '\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"':buffer.append("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"");break;
default : buffer.append(ch[i]);
}
}
System.out.println(this.toBlankString(this.frontBlankCount)+">>> ignorable whitespace("+length+"): "+buffer.toString());
}
/*
* 接收處理指令的通知襟沮。
* 參數(shù)意義如下:
* ? ? target : 處理指令目標
* ? ? data : 處理指令數(shù)據(jù),如果未提供,則為 null开伏。
*/
@Override
public void processingInstruction(String target,String data)
throws SAXException {
System.out.println(this.toBlankString(this.frontBlankCount)+">>> process instruction : (target = \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\""
+target+"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\",data = \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\""+data+"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\")");
}
/*
* 接收用來查找 SAX 文檔事件起源的對象膀跌。
* 參數(shù)意義如下:
* ? ? locator : 可以返回任何 SAX 文檔事件位置的對象
*/
@Override
public void setDocumentLocator(Locator locator) {
System.out.println(this.toBlankString(this.frontBlankCount)+
">>> set document_locator : (lineNumber = "+locator.getLineNumber()
+",columnNumber = "+locator.getColumnNumber()
+",systemId = "+locator.getSystemId()
+",publicId = "+locator.getPublicId()+")");
}
/*
* 接收跳過的實體的通知。
* 參數(shù)意義如下:
* ? ? name : 所跳過的實體的名稱固灵。如果它是參數(shù)實體捅伤,則名稱將以 '%' 開頭,
* ? ? ? ? ? ?如果它是外部 DTD 子集巫玻,則將是字符串 "[dtd]"
*/
@Override
public void skippedEntity(String name) throws SAXException {
System.out.println(this.toBlankString(this.frontBlankCount)+
">>> skipped_entity : "+name);
}
/*
* 接收文檔的開始的通知丛忆。
*/
@Override
public void startDocument() throws SAXException {
System.out.println(this.toBlankString(this.frontBlankCount++)+
">>> start document ");
}
/*
* 接收元素開始的通知。
* 參數(shù)意義如下:
* ? ?uri :元素的命名空間
* ? ?localName :元素的本地名稱(不帶前綴)
* ? ?qName :元素的限定名(帶前綴)
* ? ?atts :元素的屬性集合
*/
@Override
public void startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
System.out.println(this.toBlankString(this.frontBlankCount++)+
">>> start element : "+qName+"("+uri+")");
}
/*
* 開始前綴 URI 名稱空間范圍映射仍秤。
* 此事件的信息對于常規(guī)的命名空間處理并非必需:
* 當 http://xml.org/sax/features/namespaces 功能為 true(默認)時熄诡,
* SAX XML 讀取器將自動替換元素和屬性名稱的前綴。
* 參數(shù)意義如下:
* ? ?prefix :前綴
* ? ?uri :命名空間
*/
@Override
public void startPrefixMapping(String prefix,String uri)
throws SAXException {
System.out.println(this.toBlankString(this.frontBlankCount++)+
">>> start prefix_mapping : xmlns:"+prefix+" = "
+"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\""+uri+"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"");
}
private String toBlankString(int count){
StringBuffer buffer = new StringBuffer();
for(int i = 0;i
buffer.append(" ? ?");
return buffer.toString();
}
}'
2诗力,DTDHandler 接口 :接收與 DTD 相關的事件的通知的處理器接口凰浮。
Java代碼 ?收藏代碼
'import org.xml.sax.DTDHandler;
import org.xml.sax.SAXException;
public class MyDTDHandler implements DTDHandler {
/*
* 接收注釋聲明事件的通知。
* 參數(shù)意義如下:
* ? ? name - 注釋名稱苇本。
* ? ? publicId - 注釋的公共標識符袜茧,如果未提供,則為 null瓣窄。
* ? ? systemId - 注釋的系統(tǒng)標識符笛厦,如果未提供,則為 null俺夕。
*/
@Override
public void notationDecl(String name, String publicId, String systemId)
throws SAXException {
System.out.println(">>> notation declare : (name = "+name
+",systemId = "+publicId
+",publicId = "+systemId+")");
}
/*
* 接收未解析的實體聲明事件的通知裳凸。
* 參數(shù)意義如下:
* ? ? name - 未解析的實體的名稱。
* ? ? publicId - 實體的公共標識符啥么,如果未提供登舞,則為 null。
* ? ? systemId - 實體的系統(tǒng)標識符悬荣。
* ? ? notationName - 相關注釋的名稱菠秒。
*/
@Override
public void unparsedEntityDecl(String name,
String publicId,
String systemId,
String notationName) throws SAXException {
System.out.println(">>> unparsed entity declare : (name = "+name
+",systemId = "+publicId
+",publicId = "+systemId
+",notationName = "+notationName+")");
}
}'
3,EntityResolver 接口 :是用于解析實體的基本接口氯迂。
Java代碼 ?收藏代碼
'import java.io.IOException;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class MyEntityResolver implements EntityResolver {
/*
* 允許應用程序解析外部實體践叠。
* 解析器將在打開任何外部實體(頂級文檔實體除外)前調用此方法
* 參數(shù)意義如下:
* ? ? publicId : 被引用的外部實體的公共標識符,如果未提供嚼蚀,則為 null禁灼。
* ? ? systemId : 被引用的外部實體的系統(tǒng)標識符。
* 返回:
* ? ? 一個描述新輸入源的 InputSource 對象轿曙,或者返回 null弄捕,
* ? ? 以請求解析器打開到系統(tǒng)標識符的常規(guī) URI 連接僻孝。
*/
@Override
public InputSource resolveEntity(String publicId, String systemId)
throws SAXException, IOException {
return null;
}
}
4,ErrorHandler接口 :是錯誤處理程序的基本接口守谓。
Java代碼 ?收藏代碼
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
public class MyErrorHandler implements ErrorHandler {
/*
* 接收可恢復的錯誤的通知
*/
@Override
public void error(SAXParseException e) throws SAXException {
System.err.println("Error ("+e.getLineNumber()+","
+e.getColumnNumber()+") : "+e.getMessage());
}
/*
* 接收不可恢復的錯誤的通知穿铆。
*/
@Override
public void fatalError(SAXParseException e) throws SAXException {
System.err.println("FatalError ("+e.getLineNumber()+","
+e.getColumnNumber()+") : "+e.getMessage());
}
/*
* 接收不可恢復的錯誤的通知。
*/
@Override
public void warning(SAXParseException e) throws SAXException {
System.err.println("Warning ("+e.getLineNumber()+","
+e.getColumnNumber()+") : "+e.getMessage());
}
}
Test 類的主方法打印解析books.xml時的事件信息斋荞。
Java代碼 ?收藏代碼
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
public class Test {
public static void main(String[] args) throws SAXException,
FileNotFoundException, IOException {
//創(chuàng)建處理文檔內容相關事件的處理器
ContentHandler contentHandler = new MyContentHandler();
//創(chuàng)建處理錯誤事件處理器
ErrorHandler errorHandler = new MyErrorHandler();
//創(chuàng)建處理DTD相關事件的處理器
DTDHandler dtdHandler = new MyDTDHandler();
//創(chuàng)建實體解析器
EntityResolver entityResolver = new MyEntityResolver();
//創(chuàng)建一個XML解析器(通過SAX方式讀取解析XML)
XMLReader reader = XMLReaderFactory.createXMLReader();
/*
* 設置解析器的相關特性
* ? ? http://xml.org/sax/features/validation = true 表示開啟驗證特性
* ? ? http://xml.org/sax/features/namespaces = true 表示開啟命名空間特性
*/
reader.setFeature("http://xml.org/sax/features/validation",true);
reader.setFeature("http://xml.org/sax/features/namespaces",true);
//設置XML解析器的處理文檔內容相關事件的處理器
reader.setContentHandler(contentHandler);
//設置XML解析器的處理錯誤事件處理器
reader.setErrorHandler(errorHandler);
//設置XML解析器的處理DTD相關事件的處理器
reader.setDTDHandler(dtdHandler);
//設置XML解析器的實體解析器
reader.setEntityResolver(entityResolver);
//解析books.xml文檔
reader.parse(new InputSource(new FileReader("books.xml")));
}
}'
books.xml 文件的內容如下:
Xml代碼 ?收藏代碼
Thinking in JAVA
Core JAVA2
C++ primer
控制臺輸出如下:
>>> set document_locator : (lineNumber = 1,columnNumber = 1,systemId = null,publicId = null)
>>> start document
Error (2,7) : Document is invalid: no grammar found.
Error (2,7) : Document root element "books", must match DOCTYPE root "null".
>>> start prefix_mapping : xmlns: = "http://test.org/books"
>>> start element : books(http://test.org/books)
>>> characters(2): \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\t
>>> characters(2): \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\t
>>> start element : book(http://test.org/books)
>>> characters(3): \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\t\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\t
>>> start element : name(http://test.org/books)
>>> characters(16): Thinking in JAVA
>>> end element : name(http://test.org/books)
>>> characters(2): \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\t
>>> end element : book(http://test.org/books)
>>> characters(2): \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\t
>>> start element : book(http://test.org/books)
>>> characters(3): \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\t\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\t
>>> start element : name(http://test.org/books)
>>> characters(10): Core JAVA2
>>> end element : name(http://test.org/books)
>>> characters(2): \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\t
>>> end element : book(http://test.org/books)
>>> characters(2): \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\t
>>> start element : book(http://test.org/books)
>>> characters(3): \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\t\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\t
>>> start element : name(http://test.org/books)
>>> characters(10): C++ primer
>>> end element : name(http://test.org/books)
>>> characters(2): \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\t
>>> end element : book(http://test.org/books)
>>> characters(1): \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n
>>> end element : books(http://test.org/books)
>>> end prefix_mapping :
>>> end document ?