解析xml和生成xml(使用dom4j和velocity)

来源:互联网 发布:淘宝上正品球鞋店 编辑:程序博客网 时间:2024/06/05 00:41

在项目中队xml的解析和生成几乎每个程序员都要遇到。既然如此,对这个不熟悉就说不过去了,打好基础吧。

现在学习如何对xml解析和怎样生成xml。

首先,写一个xml,作为我们研究的样本。

XmlMessage.xml

<?xml version="1.0" encoding="UTF-8"?><transaction name="BuyBooks"><header><title name="charset">UTF-8</title><title name="system">MALL</title></header><body><field attr="word">Welcome</field><field attr="people">all you guys</field><array>    <book key="bookId">100010</book>    <book key="bookName">唐诗300首</book>    <book key="bookPrice">21元</book>    <book key="bookQuantity">135本</book></array><array>    <book key="bookId">100012</book>    <book key="bookName">宋词</book>    <book key="bookPrice">15元</book>    <book key="bookQuantity">121本</book></array></body></transaction>

好,现在我们就把这个作为研究的样本来看看怎解析它。

Java是面向对象编程的,所以第一步,你肯定想到了,解析后的内容要放在一个变量里。

这样在需要时就直接对变量进行操作了。

那么对应这个xml,我们应该对变量配置那些属性呢?

其实,这个要根据你的业务来定了。比如,在这个xml中,

<header>
<title name="charset">UTF-8</title>
<title name="system">MALL</title>
</header>

这部分是必然有的,

<field attr="word">Welcome</field>
<field attr="people">all you guys</field>

也是必然有的,唯一就是那个

<array>
   <book key="bookId">100010</book>
   <book key="bookName">唐诗300首</book>
   <book key="bookPrice">21元</book>
   <book key="bookQuantity">135本</book>
</array>

可有可无,也可由多个。

针对这样的业务,我们就把必有的属性都配置一个属性,多个或没有的就配置成一个容器(比如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<Book> array=new ArrayList<Book>();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<Book> getArray() {return array;}public void setArray(List<Book> 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<Book> array=new ArrayList<Book>();    if(document!=null){    String xmlText = document.asXML();    //System.out.println("xmlText:\r\n"+xmlText);    }    try {    Element root =document.getRootElement();    if(root.getName()!=null){//<transaction name="BuyBooks">    if(root.getName().trim().equals("transaction")){    //属性if(root.attribute("name")!=null){String attrValue=root.attribute("name").getText();//例如:BuyBooksxmlMessage.setTransaction(attrValue);}    }        }    for(Iterator i = root.elementIterator(); i.hasNext();){       Element element = (Element) i.next();        if("header".equals(element.getName())){//遍历<header>    /*<header><title name="charset">UTF-8</title><title name="system">MALL</title></header>      */    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    /*<body>...</body>     */        for(Iterator j2 = element.elementIterator(); j2.hasNext();){         /*    <field attr="word">Welcome</field><field attr="people">all you guys</field>         */        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")){//<array>标签                /*    <array>    <book key="bookId">100010</book>    <book key="bookName">唐诗300首</book>    <book key="bookPrice">21元</book>    <book key="bookQuantity">135本</book></array>         */                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("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");    String transaction=(xmlMessage.getTransaction()==null)?"":xmlMessage.getTransaction().trim();    buf.append("<transaction name=\""+transaction+"\">");    buf.append("<header>");    String charset=(xmlMessage.getCharset()==null)?"":xmlMessage.getCharset().trim();    buf.append("<title name=\"charset\">"+charset+"</title>");    String system=(xmlMessage.getSystem()==null)?"":xmlMessage.getSystem().trim();    buf.append("<title name=\"system\">"+system+"</title>");    buf.append("</header>");    buf.append("<body>");    String word=(xmlMessage.getWord()==null)?"":xmlMessage.getWord().trim();    buf.append("<field attr=\"word\">"+word+"</field>");    String people=(xmlMessage.getPeople()==null)?"":xmlMessage.getPeople().trim();    buf.append("<field attr=\"people\">"+people+"</field>");        if(xmlMessage.getArray()!=null){    List<Book> array=xmlMessage.getArray();    for(int i=0;i<array.size();i++){    Book bk=array.get(i);    buf.append("<array>");            String bookId=(bk.getBookId()==null)?"":bk.getBookId().trim();        buf.append("<book key=\"bookId\">"+bookId+"</book>");        String bookName=(bk.getBookName()==null)?"":bk.getBookName().trim();        buf.append("<book key=\"bookName\">"+bookName+"</book>");        String bookPrice=(bk.getBookPrice()==null)?"":bk.getBookPrice().trim();        buf.append("<book key=\"bookPrice\">"+bookPrice+"</book>");        String bookQuantity=(bk.getBookQuantity()==null)?"":bk.getBookQuantity().trim();        buf.append("<book key=\"bookQuantity\">"+bookQuantity+"</book>");            buf.append("</array>");    }    }//end if        buf.append("</body>");    buf.append("</transaction>");        }        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");                //<title name="charset">gbk</title>        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);                //<title name="system">MALL</title>        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);                //<body>        Element element_body = root.addElement("body");                //<field attr="word">Welcome</field>        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);                //<field attr="people">all you guys</field>        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);        //        <array>//    <book key="bookId">100010</book>//    <book key="bookName">唐诗300首</book>//    <book key="bookPrice">21元</book>//    <book key="bookQuantity">135本</book>//</array>        if(xmlMessage.getArray()!=null){List<Book> array=xmlMessage.getArray();for(int i=0;i<array.size();i++){Book bk=array.get(i);//<array>        Element element_array = element_body.addElement("array");                //<book key="bookId">100010</book>        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);                //<book key="bookName">唐诗300首</book>        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);                //<book key="bookPrice">21元</book>        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);                //<book key="bookQuantity">135本</book>        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.xmljson_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打印  <?xml version="1.0" encoding="UTF-8"?><transaction name="查询"><header><title name="charset">gbk</title><title name="system">taobao</title></header><body><field attr="word">hello</field><field attr="people">张三</field><array><book key="bookId">11</book><book key="bookName">三国演义</book><book key="bookPrice">50元</book><book key="bookQuantity">0</book></array><array><book key="bookId">22</book><book key="bookName">西游记</book><book key="bookPrice">55元</book><book key="bookQuantity">10</book></array></body></transaction>测试3打印;resXmlDom4j:<?xml version="1.0" encoding="UTF-8"?><transaction name="查询"><header><title name="charset">gbk</title><title name="system">taobao</title></header><body><field attr="word">hello</field><field attr="people">张三</field><array><book key="bookId">11</book><book key="bookName">三国演义</book><book key="bookPrice">50元</book><book key="bookQuantity">0</book></array><array><book key="bookId">22</book><book key="bookName">西游记</book><book key="bookPrice">55元</book><book key="bookQuantity">10</book></array></body></transaction>*/

对于上面我已经把打印结果页写上去了。

里面需要有个类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<Book> array=new ArrayList<Book>();    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,成功<?xml version="1.0" encoding="UTF-8"?><transaction name="查询"><header><title name="charset">gbk</title><title name="system">taobao</title></header><body><field attr="word">hello</field><field attr="people">张三</field><array>                      <book key="bookId">11</book>            <book key="bookName">三国演义</book>            <book key="bookPrice">50元</book>            <book key="bookQuantity">0</book></array><array>                      <book key="bookId">22</book>            <book key="bookName">西游记</book>            <book key="bookPrice">55元</book>            <book key="bookQuantity">10</book></array></body></transaction> */

VelocityUtil需要一个文件 XmlMessage.vm

<?xml version="1.0" encoding="UTF-8"?><transaction name="$!xmlMessage.getTransaction()"><header><title name="charset">$!xmlMessage.getCharset()</title><title name="system">$!xmlMessage.getSystem()</title></header><body><field attr="word">$!xmlMessage.getWord()</field><field attr="people">$!xmlMessage.getPeople()</field>#foreach( $book in $xmlMessage.getArray() )<array>                      <book key="bookId">$!book.getBookId()</book>            <book key="bookName">$!book.getBookName()</book>            <book key="bookPrice">$!book.getBookPrice()</book>            <book key="bookQuantity">$!book.getBookQuantity()</book></array>#end</body></transaction>


一下把所有代码都给出了,现在开始讲解。

对于解析xml,我就不再细说了,dom4j就是把xml转化成一个Document,进行内容和属性的读取,只是对于api不熟悉的话,

慢慢尝试一下,就知道怎么取值的了。


对于生成想xml,我知道3中方法:

一,拼写字符串。就是把变量的属性经过判断最后拼装成一个完整的xml字符串。

二,使用Velocity生成。

对于Velocity是什么,怎么用我就不说了。

这个Veolicty有自己的一套解析模板语言(逻辑很简单),它解析vm格式的文件。

我们可以定义好模板vm,把需要填充的值都使用模板定义的语言定义好,Velocity会解析并填充。

最后把整个vm文件中的字符返回。这个思想就是模板的思想(和jsp类似道理)。

使用这个生成xml,好处就是我们只要定义好模板就可以了,并且模板可以多变,需求变化,我们只需要改模板就可以。

一个方法写好,可以定义多个模板,来是实现多种需求。如果使用第一种方法,就需要写很多if...else。。。判断语句了。

三,使用dom4j来生成xml。

这个很好理解了,dom4j生成就xml就好比画一棵树。它的结构清晰,从根节点一点点往下加节点就可以。

只是这个逻辑也需要很多判断,代码比第一种方法显得稍笨拙一些。大多数人很熟悉字符串操作,所以大多数人

都是用第一种方法。