不同应用程序之间的通信
不同平台间的通信
不同平台间数据的共享
<?xml version =" 1.0" encoding =" UTF-8" ?>
<bookstore >
<book id =" 1" >
<name >冰与火之歌</name >
<author >乔治马丁</author >
<year >2014</year >
<price >89</price >
</book >
<book id =" 2" >
<name >安徒生童话</name >
<year >2004</year >
<price >77</price >
<language >English</language >
</book >
</bookstore >
DocumentBuilderFactory dbf = DocumentBuilderFactory .newInstance ();
try {
DocumentBuilder db = dbf .newDocumentBuilder ();
Document document = db .parse ("src/main/resources/books.xml" );
// ...
} catch (ParserConfigurationException | SAXException | IOException e ) {
e .printStackTrace ();
}
System .out .println ("DOM解析开始" );
NodeList bookList = document .getElementsByTagName ("book" );
for (int i = 0 ; i < bookList .getLength (); i ++) {
Node bookNode = bookList .item (i );
NamedNodeMap attrs = bookNode .getAttributes ();
System .out .println ("第" + (i + 1 ) + "本书共有" + attrs .getLength () + "个属性" );
// ...
NodeList childList = bookNode .getChildNodes ();
System .out .println ("第" + (i + 1 ) + "本书共有" + childList .getLength () + "个子节点" );
// ...
}
System .out .println ("DOM解析结束" );
Element
nodeName -> element name
nodeValue -> null
Attribute
nodeName -> 属性名称
nodeValue -> 属性值
Text
nodeName -> #text
nodeValue -> 节点内容
public interface Node {
public static final short ELEMENT_NODE = 1 ;
public static final short ATTRIBUTE_NODE = 2 ;
public static final short TEXT_NODE = 3 ;
// ...
}
for (int j = 0 ; j < attrs .getLength (); j ++) {
Node attrNode = attrs .item (j );
System .out .println ("第" + (j + 1 ) + "个属性的" +
"属性名:" + attrNode .getNodeName ()
+ ",属性值:" + attrNode .getNodeValue ());
}
Element bookElement = (Element ) bookList .item (i );
System .out .println ("属性名:id,属性值:" + bookElement .getAttribute ("id" ));
for (int j = 0 ; j < childList .getLength (); j ++) {
Node childNode = childList .item (j );
if (childNode != null && childNode .getNodeType () == Node .ELEMENT_NODE ) {
System .out .println ("第" + (j + 1 ) + "个子节点的" +
"节点名:" + childNode .getNodeName ()
+ ",子节点值:" + childNode .getFirstChild ().getNodeValue ());
}
}
DOM解析开始
一共有2本书
第1本书共有1个属性
第1个属性的属性名 :id ,属性值 :1
属性名 :id ,属性值 :1
第1本书共有9个子节点
第2个子节点的节点名 :name ,子节点值 :冰与火之歌
第4个子节点的节点名 :author ,子节点值 :乔治马丁
第6个子节点的节点名 :year ,子节点值 :2014
第8个子节点的节点名 :price ,子节点值 :89
第2本书共有1个属性
第1个属性的属性名 :id ,属性值 :2
属性名 :id ,属性值 :2
第2本书共有9个子节点
第2个子节点的节点名 :name ,子节点值 :安徒生童话
第4个子节点的节点名 :year ,子节点值 :2004
第6个子节点的节点名 :price ,子节点值 :77
第8个子节点的节点名 :language ,子节点值 :English
DOM解析结束
SAXParserFactory spf = SAXParserFactory .newInstance ();
try {
SAXParser saxParser = spf .newSAXParser ();
SaxParserHandler handler = new SaxParserHandler ();
saxParser .parse ("src/main/resources/books.xml" , handler );
} catch (ParserConfigurationException | SAXException | IOException e ) {
e .printStackTrace ();
}
static class SaxParserHandler extends DefaultHandler {
int bookstoreIndex = 0 ;
int bookIndex = 0 ;
int childIndex = 0 ;
// ...
}
@ Override
public void startDocument () throws SAXException {
super .startDocument ();
System .out .println ("SAX解析开始" );
}
@ Override
public void endDocument () throws SAXException {
super .endDocument ();
System .out .println ("SAX解析结束" );
}
@ Override
public void startElement (String uri , String localName , String qName ,
Attributes attributes )
throws SAXException {
super .startElement (uri , localName , qName , attributes );
if ("bookstore" .equals (qName )) {
bookstoreIndex ++;
bookIndex = 0 ;
} else if ("book" .equals (qName )) {
bookIndex ++;
childIndex = 0 ;
System .out .println ("第" + bookIndex + "本书共有" + attributes .getLength () + "个属性" );
for (int i = 0 ; i < attributes .getLength (); i ++) {
System .out .println ("第" + (i + 1 ) + "个属性的" +
"属性名:" + attributes .getQName (i )
+ ",属性值:" + attributes .getValue (i ));
}
System .out .println ("属性名:id,属性值:" + attributes .getValue ("id" ));
} else {
childIndex ++;
System .out .print ("第" + childIndex + "个子节点名:" + qName );
}
}
@ Override
public void endElement (String uri , String localName , String qName )
throws SAXException {
super .endElement (uri , localName , qName );
if ("bookstore" .equals (qName )) {
System .out .println ("一共有" + bookIndex + "本书" );
} else if ("book" .equals (qName )) {
System .out .println ("第" + bookIndex + "本书共有" + childIndex + "个子节点" );
}
}
@ Override
public void characters (char [] ch , int start , int length ) throws SAXException {
super .characters (ch , start , length );
String value = new String (ch , start , length );
if (!"" .equals (value .trim ())) {
System .out .println (",节点值:" + value );
}
}
SAX解析开始
第1本书共有1个属性
第1个属性的属性名 :id ,属性值 :1
属性名 :id ,属性值 :1
第1个子节点的节点名 :name ,节点值 :冰与火之歌
第2个子节点的节点名 :author ,节点值 :乔治马丁
第3个子节点的节点名 :year ,节点值 :2014
第4个子节点的节点名 :price ,节点值 :89
第1本书共有4个子节点
第2本书共有1个属性
第1个属性的属性名 :id ,属性值 :2
属性名 :id ,属性值 :2
第1个子节点的节点名 :name ,节点值 :安徒生童话
第2个子节点的节点名 :year ,节点值 :2004
第3个子节点的节点名 :price ,节点值 :77
第4个子节点的节点名 :language ,节点值 :English
第2本书共有4个子节点
一共有2本书
SAX解析结束
public class Book {
private String id ;
private String name ;
private String author ;
private String year ;
private String price ;
private String language ;
// ...
}
static class SaxParserHandler extends DefaultHandler {
List <Book > bookList = new ArrayList <>();
int bookIndex = 0 ;
Book book = null ;
String currentValue = null ;
// ...
}
@ Override
public void startElement (String uri , String localName , String qName ,
Attributes attributes )
throws SAXException {
super .startElement (uri , localName , qName , attributes );
if ("book" .equals (qName )) {
bookIndex ++;
book = new Book ();
for (int i = 0 ; i < attributes .getLength (); i ++) {
if ("id" .equals (attributes .getQName (i ))) {
book .setId (attributes .getValue (i ));
}
}
}
}
@ Override
public void endElement (String uri , String localName , String qName )
throws SAXException {
super .endElement (uri , localName , qName );
if ("book" .equals (qName )) {
bookList .add (book );
book = null ;
} else if ("name" .equals (qName )) {
book .setName (currentValue );
} else if ("author" .equals (qName )) {
book .setAuthor (currentValue );
} else if ("year" .equals (qName )) {
book .setYear (currentValue );
} else if ("price" .equals (qName )) {
book .setPrice (currentValue );
} else if ("language" .equals (qName )) {
book .setLanguage (currentValue );
}
}
@ Override
public void characters (char [] ch , int start , int length ) throws SAXException {
super .characters (ch , start , length );
currentValue = new String (ch , start , length );
}
Book {id ='1' , name ='冰与火之歌' , author ='乔治马丁' , year ='2014' , price ='89' , language ='null' }
Book {id ='2' , name ='安徒生童话' , author ='null' , year ='2004' , price ='77' , language ='English' }
2.3. 应用 DOM4J 及 JDOM 方式解析 XML
SAXBuilder saxBuilder = new SAXBuilder ();
InputStream in ;
try {
in = new FileInputStream ("src/main/resources/books.xml" );
InputStreamReader isr = new InputStreamReader (in , StandardCharsets .UTF_8 );
Document document = saxBuilder .build (isr );
Element rootElement = document .getRootElement ();
List <Element > bookList = rootElement .getChildren ();
// ...
} catch (JDOMException | IOException e ) {
e .printStackTrace ();
}
System .out .println ("JDOM解析开始" );
System .out .println ("一共有" + bookList .size () + "本书" );
for (Element book : bookList ) {
List <Attribute > attributeList = book .getAttributes ();
System .out .println ("第" + (bookList .indexOf (book ) + 1 ) + "本书共有"
+ attributeList .size () + "个属性" );
// ...
List <Element > childList = book .getChildren ();
System .out .println ("第" + (bookList .indexOf (book ) + 1 ) + "本书共有"
+ childList .size () + "个子节点" );
// ...
}
System .out .println ("JDOM解析结束" );
List <Attribute > attributeList = book .getAttributes ();
System .out .println ("第" + (bookList .indexOf (book ) + 1 ) + "本书共有"
+ attributeList .size () + "个属性" );
for (Attribute attr : attributeList ) {
System .out .println ("第" + (attributeList .indexOf (attr ) + 1 ) + "个属性的" +
"属性名:" + attr .getName ()
+ ",属性值:" + attr .getValue ());
}
System .out .println ("属性名:id,属性值:" + book .getAttributeValue ("id" ));
for (Element child : childList ) {
System .out .println ("第" + (childList .indexOf (child ) + 1 ) + "个子节点的" +
"节点名:" + child .getName ()
+ ",子节点值:" + child .getValue ());
}
JDOM解析开始
一共有2本书
第1本书共有1个属性
第1个属性的属性名 :id ,属性值 :1
属性名 :id ,属性值 :1
第1本书共有4个子节点
第1个子节点的节点名 :name ,子节点值 :冰与火之歌
第2个子节点的节点名 :author ,子节点值 :乔治马丁
第3个子节点的节点名 :year ,子节点值 :2014
第4个子节点的节点名 :price ,子节点值 :89
第2本书共有1个属性
第1个属性的属性名 :id ,属性值 :2
属性名 :id ,属性值 :2
第2本书共有4个子节点
第1个子节点的节点名 :name ,子节点值 :安徒生童话
第2个子节点的节点名 :year ,子节点值 :2004
第3个子节点的节点名 :price ,子节点值 :77
第4个子节点的节点名 :language ,子节点值 :English
JDOM解析结束
SAXBuilder saxBuilder = new SAXBuilder ();
InputStream in ;
List <Book > bookEntityList = new ArrayList <>();
Book bookEntity = null ;
try {
in = new FileInputStream ("src/main/resources/books.xml" );
Document document = saxBuilder .build (in );
Element rootElement = document .getRootElement ();
List <Element > bookList = rootElement .getChildren ();
for (Element book : bookList ) {
bookEntity = new Book ();
List <Attribute > attributeList = book .getAttributes ();
for (Attribute attr : attributeList ) {
if ("id" .equals (attr .getName ())) {
bookEntity .setId (attr .getValue ());
}
}
List <Element > childList = book .getChildren ();
for (Element child : childList ) {
if ("name" .equals (child .getName ())) {
bookEntity .setName (child .getValue ());
} else if ("author" .equals (child .getName ())) {
bookEntity .setAuthor (child .getValue ());
} else if ("year" .equals (child .getName ())) {
bookEntity .setYear (child .getValue ());
} else if ("price" .equals (child .getName ())) {
bookEntity .setPrice (child .getValue ());
} else if ("language" .equals (child .getName ())) {
bookEntity .setLanguage (child .getValue ());
}
}
bookEntityList .add (bookEntity );
}
} catch (JDOMException | IOException e ) {
e .printStackTrace ();
}
for (Book book : bookEntityList ) {
System .out .println (book );
}
<?xml version =" 1.0" encoding =" ISO-8859-1" ?>
<bookstore >
<book id =" 1" >
<name >冰与火之歌</name >
<author >乔治马丁</author >
<year >2014</year >
<price >89</price >
</book >
<book id =" 2" >
<name >安徒生童话</name >
<year >2004</year >
<price >77</price >
<language >English</language >
</book >
</bookstore >
in = new FileInputStream ("src/main/resources/books2.xml" );
InputStreamReader isr = new InputStreamReader (in , StandardCharsets .UTF_8 );
Document document = saxBuilder .build (isr );
SAXReader reader = new SAXReader ();
int bookIndex = 0 ;
int attributeIndex ;
int childIndex ;
try {
Document document = reader .read (new File ("src/main/resources/books.xml" ));
Element bookStore = document .getRootElement ();
Iterator iterator = bookStore .elementIterator ();
// ...
} catch (DocumentException e ) {
e .printStackTrace ();
}
System .out .println ("DOM4J解析开始" );
while (iterator .hasNext ()) {
bookIndex ++;
attributeIndex = 0 ;
childIndex = 0 ;
Element book = (Element ) iterator .next ();
List <Attribute > bookAttrs = book .attributes ();
// ...
System .out .println ("第" + bookIndex + "本书共有" + attributeIndex + "个属性" );
Iterator iterator2 = book .elementIterator ();
// ...
System .out .println ("第" + bookIndex + "本书共有" + childIndex + "个子节点" );
}
System .out .println ("一共有" + bookIndex + "本书" );
System .out .println ("DOM4J解析结束" );
for (Attribute attr : bookAttrs ) {
attributeIndex ++;
System .out .println ("属性名:" + attr .getName ()
+ ",属性值:" + attr .getValue ());
}
while (iterator2 .hasNext ()) {
childIndex ++;
Element bookChild = (Element ) iterator2 .next ();
System .out .println ("节点名:" + bookChild .getName ()
+ ",节点值:" + bookChild .getStringValue ());
}
DOM4J解析开始
属性名 :id ,属性值 :1
第1本书共有1个属性
节点名 :name ,节点值 :冰与火之歌
节点名 :author ,节点值 :乔治马丁
节点名 :year ,节点值 :2014
节点名 :price ,节点值 :89
第1本书共有4个子节点
属性名 :id ,属性值 :2
第2本书共有1个属性
节点名 :name ,节点值 :安徒生童话
节点名 :year ,节点值 :2004
节点名 :price ,节点值 :77
节点名 :language ,节点值 :English
第2本书共有4个子节点
一共有2本书
DOM4J解析结束
优点
形成了树结构,只管好理解,代码更易编写
解析过程中树结构保留在内存中,方便修改
缺点
当 XML 文件较大时,对内存耗费比较大
容易影响解析性能,造成内存溢出
优点
采用时间驱动模式,对内存耗费比较小
适用于只需要处理 XML 中数据时
缺点
不易编码
很难同时访问同一个 XML 中多处不同数据
仅使用具体类而不使用接口
API 大量使用了 Collection 类
JDOM 的一种智能分支,它合并了许多超出基本 XML 文档表示的功能
DOM4J 使用接口和抽象基本类方法,是一个优秀的 Java XML API
具有性能优异、灵活性好、功能强大、极端易用的特点
是一个开放源代码的软件
DocumentBuilder getDocumentBuilder () {
DocumentBuilderFactory dbf = DocumentBuilderFactory .newInstance ();
DocumentBuilder db = null ;
try {
db = dbf .newDocumentBuilder ();
} catch (ParserConfigurationException e ) {
e .printStackTrace ();
}
return db ;
}
Transformer getTransformer () {
TransformerFactory tff = TransformerFactory .newInstance ();
Transformer tf = null ;
try {
tf = tff .newTransformer ();
tf .setOutputProperty (OutputKeys .INDENT , "yes" );
} catch (TransformerConfigurationException e ) {
e .printStackTrace ();
}
return tf ;
}
public void createXml () {
Document document = getDocumentBuilder ().newDocument ();
document .setXmlStandalone (true );
Element bookstore = document .createElement ("bookstore" );
Element book = document .createElement ("book" );
book .setAttribute ("id" , "1" );
Element name = document .createElement ("name" );
name .setTextContent ("小王子" );
book .appendChild (name );
bookstore .appendChild (book );
document .appendChild (bookstore );
Transformer tf = getTransformer ();
try {
tf .transform (new DOMSource (document ), new StreamResult (
new File ("src/main/resources/books3.xml" )
));
} catch (TransformerException e ) {
e .printStackTrace ();
}
}
TransformerHandler getTransformerHandler () {
SAXTransformerFactory tff = (SAXTransformerFactory ) SAXTransformerFactory .newInstance ();
TransformerHandler handler = null ;
try {
handler = tff .newTransformerHandler ();
} catch (TransformerConfigurationException e ) {
e .printStackTrace ();
}
return handler ;
}
List <Book > bookList = parseXml ();
TransformerHandler handler = getTransformerHandler ();
Transformer tf = handler .getTransformer ();
tf .setOutputProperty (OutputKeys .ENCODING , "UTF-8" );
tf .setOutputProperty (OutputKeys .INDENT , "yes" );
try {
File f = new File ("src/main/resources/books4.xml" );
if (!f .exists ()) {
f .createNewFile ();
}
Result result = new StreamResult (new FileOutputStream (f ));
handler .setResult (result );
handler .startDocument ();
AttributesImpl attr = new AttributesImpl ();
handler .startElement ("" , "" , "bookstore" , attr );
for (Book book : bookList ) {
attr .clear ();
attr .addAttribute ("" , "" , "id" , "" , "1" );
handler .startElement ("" , "" , "book" , attr );
// ...
handler .endElement ("" , "" , "book" );
}
handler .endElement ("" , "" , "bookstore" );
handler .endDocument ();
} catch (SAXException | IOException e ) {
e .printStackTrace ();
}
if (book .getAuthor () != null && !"" .equals (book .getAuthor ().trim ())) {
attr .clear ();
handler .startElement ("" , "" , "author" , attr );
handler .characters (book .getAuthor ().toCharArray (), 0 , book .getAuthor ().length ());
handler .endElement ("" , "" , "author" );
}
Element rss = new Element ("rss" );
rss .setAttribute ("version" , "2.0" );
Document document = new Document (rss );
Element channel = new Element ("channel" );
rss .addContent (channel );
Element title = new Element ("title" );
title .setText ("国内最新新闻" );
channel .addContent (title );
Element title2 = new Element ("title2" );
title2 .setText ("<尖括号会自动转义>" );
channel .addContent (title2 );
Format format = Format .getCompactFormat ();
format .setIndent ("" );
format .setEncoding ("GBK" );
XMLOutputter output = new XMLOutputter (format );
try {
output .output (document , new FileOutputStream ("src/main/resources/rssNews1.xml" ));
} catch (IOException e ) {
e .printStackTrace ();
}
3.4. 通过 DOM4J 方式生成 XML 文档
Document document = DocumentHelper .createDocument ();
Element rss = document .addElement ("rss" );
rss .addAttribute ("version" , "2.0" );
Element channel = rss .addElement ("channel" );
Element title = channel .addElement ("title" );
title .setText ("国内最新新闻" );
Element title2 = channel .addElement ("title2" );
title2 .setText ("<尖括号不会自动转义>" );
OutputFormat format = OutputFormat .createPrettyPrint ();
format .setEncoding ("GBK" );
File file = new File ("src/main/resources/rssNews2.xml" );
try {
XMLWriter writer = new XMLWriter (new FileOutputStream (file ), format );
writer .setEscapeText (false );
writer .write (document );
writer .close ();
} catch (IOException e ) {
e .printStackTrace ();
}
DOM:基于 tree
SAX:基于事件
JDOM 和 DOM4J:基于底层 API