在项目中队xml的解析和生成几乎每个程序员都要遇到。既然如此,对这个不熟悉就说不过去了,打好基础吧。
现在学习如何对xml解析和怎样生成xml。
首先,写一个xml,作为我们研究的样本。
XmlMessage.xml
UTF-8
MALL
Welcome
all you guys
100010
唐诗300首
21元
135本
100012
宋词
15元
121本
Java是面向对象编程的,所以第一步,你肯定想到了,解析后的内容要放在一个变量里。
这样在需要时就直接对变量进行操作了。
那么对应这个xml,我们应该对变量配置那些属性呢?
其实,这个要根据你的业务来定了。比如,在这个xml中,
这部分是必然有的,
也是必然有的,唯一就是那个
可有可无,也可由多个。
针对这样的业务,我们就把必有的属性都配置一个属性,多个或没有的就配置成一个容器(比如List)。
这个看你的业务了,如果里面的属性变化太大,则可以具体细分成多个对象定义成一个总的对象。
总之,要把对象的属性和xml中定义的一一对应就可以。
针对这个xml,我这样定义:
XmlMessage
package org.xml.bean;
import java.util.ArrayList;
import java.util.List;
public class XmlMessage {
private String charset;
private String system;
private String word;
private String people;
private List array=new ArrayList();
private String transaction;
public String getCharset() {
return charset;
}
public void setCharset(String charset) {
this.charset = charset;
}
public String getSystem() {
return system;
}
public void setSystem(String system) {
this.system = system;
}
public String getWord() {
return word;
}
public void setWord(String word) {
this.word = word;
}
public String getPeople() {
return people;
}
public void setPeople(String people) {
this.people = people;
}
public List getArray() {
return array;
}
public void setArray(List array) {
this.array = array;
}
public String getTransaction() {
return transaction;
}
public void setTransaction(String transaction) {
this.transaction = transaction;
}
}
Book
package org.xml.bean;
public class Book {
private String bookId;
private String bookName;
private String bookPrice;
private String bookQuantity;
public String getBookId() {
return bookId;
}
public void setBookId(String bookId) {
this.bookId = bookId;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getBookPrice() {
return bookPrice;
}
public void setBookPrice(String bookPrice) {
this.bookPrice = bookPrice;
}
public String getBookQuantity() {
return bookQuantity;
}
public void setBookQuantity(String bookQuantity) {
this.bookQuantity = bookQuantity;
}
}
在开始之前,先写一个打印对象的方法,只要能打印出对象的属性和值就可以。一般可以使用toString()方法,
但是我建议写成json格式的,应为在web层页面需要处理对象的时候,使用json很方便。这里只是为了打印。
JsonUtil
package org.xml.util;
import net.sf.json.JSONObject;
public class JsonUtil{
public static String objectToJson(Object obj){
String result="";
if(obj!=null){
try{
result=JSONObject.fromObject(obj).toString();
}catch(Exception ee){
ee.printStackTrace();
}
}
return result;
}
public static void main(String[] arg) throws Exception{
}
}
对于解析xml,首选当然是dom4j。
写一个工具类
Dom4jXmlUtil
package org.xml.util;
import java.io.File;
import java.io.InputStream;
import java.io.StringReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.DOMReader;
import org.dom4j.io.SAXReader;
import org.xml.bean.Book;
import org.xml.bean.XmlMessage;
import org.xml.sax.InputSource;
public class Dom4jXmlUtil {
public Dom4jXmlUtil() {}
public static SAXReader createSAXReader() {
return new SAXReader();
}
public static DOMReader createDOMReader() {
return new DOMReader();
}
public static Document read(InputStream is) {
try {
return createSAXReader().read(is);
} catch (DocumentException e) {
throw new RuntimeException(e);
}
}
public static Document read(File file) {
try {
return createSAXReader().read(file);
} catch (DocumentException e) {
throw new RuntimeException(e);
}
}
public static Document read(InputSource is) {
try {
return createSAXReader().read(is);
} catch (DocumentException e) {
throw new RuntimeException(e);
}
}
public static Document read(String xmlString) {
return read(new InputSource(new StringReader(xmlString)));
}
public static Document read(URL url) {
try {
return createSAXReader().read(url);
} catch (DocumentException e) {
throw new RuntimeException(e);
}
}
public static Document read(org.w3c.dom.Document doc) {
return createDOMReader().read(doc);
}
/**
* 解析xml到对象XmlMessage
* @param document
*/
public static XmlMessage parserXmlToSignMessage(Document document){
XmlMessage xmlMessage = new XmlMessage();
List array=new ArrayList();
if(document!=null){
String xmlText = document.asXML();
//System.out.println("xmlText:\r\n"+xmlText);
}
try {
Element root =document.getRootElement();
if(root.getName()!=null){//
if(root.getName().trim().equals("transaction")){
//属性
if(root.attribute("name")!=null){
String attrValue=root.attribute("name").getText();//例如:BuyBooks
xmlMessage.setTransaction(attrValue);
}
}
}
for(Iterator i = root.elementIterator(); i.hasNext();){
Element element = (Element) i.next();
if("header".equals(element.getName())){//遍历
/*
UTF-8
MALL
*/
for(Iterator j = element.elementIterator(); j.hasNext();){
Element node = (Element) j.next();
String tagName=node.getName();//例:title
String tagValue=node.getText();//例:UTF-8
//属性值获取
if(node.attribute("name")!=null){
String attrName=node.attribute("name").getName();//name
String attrValue=node.attribute("name").getText();//charset
//业务
if(attrValue.trim().equals("charset")){
xmlMessage.setCharset(tagValue);
}
if(attrValue.trim().equals("system")){
xmlMessage.setSystem(tagValue);
}
}
}// end for
}else if("body".equals(element.getName())){//遍历body
/*
...
*/
for(Iterator j2 = element.elementIterator(); j2.hasNext();){
/*
Welcome
all you guys
*/
Element node2 = (Element) j2.next();
String tagName2=node2.getName();//例:field
String tagValue2=node2.getText();//例:Welcome
if(tagName2.trim().equals("field")){//field标签
//属性
if(node2.attribute("attr")!=null){
String attrName2=node2.attribute("attr").getName();//例:attr
String attrValue2=node2.attribute("attr").getText();//例:word
//业务
if(attrValue2.trim().equals("word")){
xmlMessage.setWord(tagValue2);
}
if(attrValue2.trim().equals("people")){
xmlMessage.setPeople(tagValue2);
}
}// end if 属性
}else if(tagName2.trim().equals("array")){//标签
/*
100010
唐诗300首
21元
135本
*/
Book book=new Book();
for(Iterator j3 = node2.elementIterator(); j3.hasNext();){
Element node3 = (Element) j3.next();
String tagName3=node3.getName();//例:book
String tagValue3=node3.getText();//例:100010
if(tagName3.trim().equals("book")){//book标签
//属性
if(node3.attribute("key")!=null){
String attrName3=node3.attribute("key").getName();//例:key
String attrValue3=node3.attribute("key").getText();//例:bookId
//业务
if(attrValue3.trim().equals("bookId")){
book.setBookId(tagValue3);
}
if(attrValue3.trim().equals("bookName")){
book.setBookName(tagValue3);
}
if(attrValue3.trim().equals("bookPrice")){
book.setBookPrice(tagValue3);
}
if(attrValue3.trim().equals("bookQuantity")){
book.setBookQuantity(tagValue3);
}
}// end if 属性
}
}
array.add(book);
}//end //array标签
xmlMessage.setArray(array);
}//end for //遍历body
}
}
}catch (Exception e) {
e.printStackTrace();
}
return xmlMessage;
}
/**
* 生成xml字符串,使用StringBuffer
* @param xmlMessage
* @return
*/
public static String createXmlByString(XmlMessage xmlMessage){
StringBuffer buf=new StringBuffer("");;
if(xmlMessage==null){
}else{
buf.append("");
String transaction=(xmlMessage.getTransaction()==null)?"":xmlMessage.getTransaction().trim();
buf.append("");
buf.append("");
String charset=(xmlMessage.getCharset()==null)?"":xmlMessage.getCharset().trim();
buf.append(""+charset+" ");
String system=(xmlMessage.getSystem()==null)?"":xmlMessage.getSystem().trim();
buf.append(""+system+" ");
buf.append(" ");
buf.append("");
String word=(xmlMessage.getWord()==null)?"":xmlMessage.getWord().trim();
buf.append(""+word+" ");
String people=(xmlMessage.getPeople()==null)?"":xmlMessage.getPeople().trim();
buf.append(""+people+" ");
if(xmlMessage.getArray()!=null){
List array=xmlMessage.getArray();
for(int i=0;i");
String bookId=(bk.getBookId()==null)?"":bk.getBookId().trim();
buf.append(""+bookId+" ");
String bookName=(bk.getBookName()==null)?"":bk.getBookName().trim();
buf.append(""+bookName+" ");
String bookPrice=(bk.getBookPrice()==null)?"":bk.getBookPrice().trim();
buf.append(""+bookPrice+" ");
String bookQuantity=(bk.getBookQuantity()==null)?"":bk.getBookQuantity().trim();
buf.append(""+bookQuantity+" ");
buf.append(" ");
}
}//end if
buf.append("");
buf.append(" ");
}
return buf.toString();
}
/**
* 生成xml字符串,使用dom4j生成
* @param xmlMessage
* @return
*/
public static String createXmlByDom4j(XmlMessage xmlMessage){
String xml="";
Document document = DocumentHelper.createDocument();
Element root = document.addElement("transaction");
String transaction=(xmlMessage.getTransaction()==null)?"":xmlMessage.getTransaction().trim();
root.addAttribute("name", transaction);
Element element_header = root.addElement("header");
//gbk
Element element_title_charset = element_header.addElement("title");
String charset=(xmlMessage.getCharset()==null)?"":xmlMessage.getCharset().trim();
element_title_charset.addAttribute("name","charset");
element_title_charset.addText(charset);
//MALL
Element element_title_system = element_header.addElement("title");
String system=(xmlMessage.getSystem()==null)?"":xmlMessage.getSystem().trim();
element_title_system.addAttribute("name","system");
element_title_system.addText(system);
//
Element element_body = root.addElement("body");
//Welcome
Element element_field_word = element_body.addElement("field");
String word=(xmlMessage.getWord()==null)?"":xmlMessage.getWord().trim();
element_field_word.addAttribute("attr","word");
element_field_word.addText(word);
//all you guys
Element element_field_people = element_body.addElement("field");
String people=(xmlMessage.getPeople()==null)?"":xmlMessage.getPeople().trim();
element_field_people.addAttribute("attr","people");
element_field_people.addText(people);
//
// 100010
// 唐诗300首
// 21元
// 135本
//
if(xmlMessage.getArray()!=null){
List array=xmlMessage.getArray();
for(int i=0;i
Element element_array = element_body.addElement("array");
//100010
Element element_array_bookId = element_array.addElement("book");
String bookId=(bk.getBookId()==null)?"":bk.getBookId().trim();
element_array_bookId.addAttribute("key","bookId");
element_array_bookId.addText(bookId);
//唐诗300首
Element element_array_bookName = element_array.addElement("book");
String bookName=(bk.getBookName()==null)?"":bk.getBookName().trim();
element_array_bookName.addAttribute("key","bookName");
element_array_bookName.addText(bookName);
//21元
Element element_array_bookPrice = element_array.addElement("book");
String bookPrice=(bk.getBookPrice()==null)?"":bk.getBookPrice().trim();
element_array_bookPrice.addAttribute("key","bookPrice");
element_array_bookPrice.addText(bookPrice);
//135本
Element element_array_bookQuantity = element_array.addElement("book");
String bookQuantity=(bk.getBookQuantity()==null)?"":bk.getBookQuantity().trim();
element_array_bookQuantity.addAttribute("key","bookQuantity");
element_array_bookQuantity.addText(bookQuantity);
}
}//end if
xml=document.asXML();//生成字符串
return xml;
}
public static void main(String[] args){
//解析功能
//测试1,解析xml,结果放入一个对象中
// File file=new File(Dom4jXmlUtil.class.getClassLoader().getResource("org/xml/file/XmlMessage.xml").getPath());
// System.out.println("filepath:"+file.getPath());
//
// Document document=Dom4jXmlUtil.read(file);
// XmlMessage xmlMessage=Dom4jXmlUtil.parserXmlToSignMessage(document);
// if(xmlMessage!=null){
// System.out.println("json_xmlMessage:\r\n"+JsonUtil.objectToJson(xmlMessage));
//
// }
//生成功能
//测试2,使用生成xml字符串,使用StringBuffer
// XmlMessage obj=VelocityUtil.getOneXmlMessage();//生成一个对象,并赋值,供测试使用
// String resXml=Dom4jXmlUtil.createXmlByString(obj);
// System.out.println(resXml);
//测试3,生成xml字符串,使用dom4j生成
XmlMessage obj2=VelocityUtil.getOneXmlMessage();//生成一个对象,并赋值,供测试使用
String resXmlDom4j=Dom4jXmlUtil.createXmlByDom4j(obj2);
System.out.println("resXmlDom4j:\r\n"+resXmlDom4j);
}
}
/*
测试1打印;
filepath:D:\ChinaDevelopmentBankJBPM\workSpace\frame\webapp\WEB-INF\classes\org\xml\file\XmlMessage.xml
json_xmlMessage:
{"array":[{"bookId":"100010","bookName":"唐诗300首","bookPrice":"21元","bookQuantity":"135本"},{"bookId":"100012","bookName":"宋词","bookPrice":"15元","bookQuantity":"121本"}],"charset":"UTF-8","people":"all you guys","system":"MALL","transaction":"BuyBooks","word":"Welcome"}
把json美化后看看结构和数据字段是不是对应:
{
"array":[
{"bookId":"100010","bookName":"唐诗300首","bookPrice":"21元","bookQuantity":"135本"},
{"bookId":"100012","bookName":"宋词","bookPrice":"15元","bookQuantity":"121本"}
],
"charset":"UTF-8",
"people":"all you guys",
"system":"MALL",
"transaction":"BuyBooks",
"word":"Welcome"
}
//测试2打印
gbk taobao hello 张三 11 三国演义 50元 0 22 西游记 55元 10
测试3打印;
resXmlDom4j:
gbk taobao hello 张三 11 三国演义 50元 0 22 西游记 55元 10
*/
里面需要有个类VelocityUtil
package org.xml.util;
import java.io.File;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.dom4j.Document;
import org.xml.bean.Book;
import org.xml.bean.XmlMessage;
public class VelocityUtil {
/**
* 生成xml字符串,使用Velocity模板
* @param xmlMessage
* @param file_resource_loader_path
* @param templateFile
* @return
*/
public String getXmlFromVmByVelocity(XmlMessage xmlMessage,String file_resource_loader_path,String templateFile) {
String resultXml="";
try {
//引擎设置
Properties prop = new Properties();
prop.setProperty(Velocity.INPUT_ENCODING, "UTF-8"); //设置输入输出编码类型
prop.setProperty(Velocity.OUTPUT_ENCODING, "UTF-8");
//指定一个绝对路径作为模版路径.例如 D:/MyProject/my-workSpace/Mytest/bin/org/test
prop.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, file_resource_loader_path);
VelocityEngine velocityEngine = new VelocityEngine();
velocityEngine.init(prop);
System.out.println("模板路径--"+velocityEngine.getProperty(Velocity.FILE_RESOURCE_LOADER_PATH));
VelocityContext context = new VelocityContext();
context.put("xmlMessage", xmlMessage);//放入对象
//如果有其他的属性,也可以取出来直接放进去,这和session取值放值类似
// if(xmlMessage.getArray()!=null){
// context.put("array", xmlMessage.getArray());
// }
Template template = null;//模版
try {
template = velocityEngine.getTemplate(templateFile,"UTF-8");//非单例。注意设置编码,避免中文乱码
} catch (ResourceNotFoundException e1) {
System.out.println("Velocity error,ResourceNotFoundException:"
+ templateFile);
} catch (ParseErrorException e2) {
System.out.println("Velocity error,ParseErrorException:"
+ templateFile + ":" + e2);
}
StringWriter strWirter=new StringWriter();
if (template != null){
template.merge(context, strWirter);//解析
resultXml=strWirter.getBuffer().toString();//生成结果返回
}
} catch (Exception e) {
System.out.println(e);
}
return resultXml;
}
public static XmlMessage getOneXmlMessage(){
XmlMessage xml=new XmlMessage();
xml.setCharset("gbk");
xml.setPeople("张三");
xml.setSystem("taobao");
xml.setTransaction("查询");
xml.setWord("hello");
List array=new ArrayList();
Book bk1=new Book();
Book bk2=new Book();
bk1.setBookId("11");
bk1.setBookName("三国演义");
bk1.setBookPrice("50元");
bk1.setBookQuantity("0");
bk2.setBookId("22");
bk2.setBookName("西游记");
bk2.setBookPrice("55元");
bk2.setBookQuantity("10");
array.add(bk1);
array.add(bk2);
xml.setArray(array);
return xml;
}
public static void main(String[] args) {
//生成功能
VelocityUtil v2 = new VelocityUtil();
String basepath=VelocityUtil.class.getClassLoader().getResource("").getPath();
System.out.println(basepath);
XmlMessage xml=getOneXmlMessage();
String res=v2.getXmlFromVmByVelocity(xml,basepath, "org/xml/file/XmlMessage.vm");
System.out.println("haha,成功\r\n"+res);
}
}
/*打印:
/D:/ChinaDevelopmentBankJBPM/workSpace/frame/webapp/WEB-INF/classes/
模板路径--/D:/ChinaDevelopmentBankJBPM/workSpace/frame/webapp/WEB-INF/classes/
haha,成功
gbk
taobao
hello
张三
11
三国演义
50元
0
22
西游记
55元
10
*/
$!xmlMessage.getCharset()
$!xmlMessage.getSystem()
$!xmlMessage.getWord()
$!xmlMessage.getPeople()
#foreach( $book in $xmlMessage.getArray() )
$!book.getBookId()
$!book.getBookName()
$!book.getBookPrice()
$!book.getBookQuantity()
#end
一下把所有代码都给出了,现在开始讲解。
对于解析xml,我就不再细说了,dom4j就是把xml转化成一个Document,进行内容和属性的读取,只是对于api不熟悉的话,
慢慢尝试一下,就知道怎么取值的了。
对于生成想xml,我知道3中方法:
一,拼写字符串。就是把变量的属性经过判断最后拼装成一个完整的xml字符串。
二,使用Velocity生成。
对于Velocity是什么,怎么用我就不说了。
这个Veolicty有自己的一套解析模板语言(逻辑很简单),它解析vm格式的文件。
我们可以定义好模板vm,把需要填充的值都使用模板定义的语言定义好,Velocity会解析并填充。
最后把整个vm文件中的字符返回。这个思想就是模板的思想(和jsp类似道理)。
使用这个生成xml,好处就是我们只要定义好模板就可以了,并且模板可以多变,需求变化,我们只需要改模板就可以。
一个方法写好,可以定义多个模板,来是实现多种需求。如果使用第一种方法,就需要写很多if...else。。。判断语句了。
三,使用dom4j来生成xml。
这个很好理解了,dom4j生成就xml就好比画一棵树。它的结构清晰,从根节点一点点往下加节点就可以。
只是这个逻辑也需要很多判断,代码比第一种方法显得稍笨拙一些。大多数人很熟悉字符串操作,所以大多数人
都是用第一种方法。