• JDOM 操作XML


    http://www.cnblogs.com/hoojo/archive/2011/08/11/2134638.html

    可扩展标记语言——eXtensible Markup Language

    用户可以自己定义语言标记,只要有开始和闭合标签即可。

    xsl装饰、修饰xml的显示结果。

    dtd约束xml文件中的标记。

    Ø XML的优点:

        1、xml可以让数据和标记分离。

        2、异质信息互通

        3、机器语言

        4、用交流语言替代html装饰语言

        5、简单易用

        6、可以自定义、可扩展  

    Ø XML和HTML比较

    比较内容

    HTML

    XML

    可扩展性

    不具有扩展性、标记固定

    是元标记语言,可以定义新标记,用户可以自定义标记

    侧重点

    侧重于信息的表现形式为什么格式被关注

    侧重于结构化的描述信息,数据是什么为XML所关注

    语法

    不严格(嵌套、配对)

    严格嵌套、配对,并按照DTD要求输出

    可读性、可维护性

    难于阅读和维护

    结构清晰,便于阅读维护

    数据本身、显示

    数据和显示合为一处

    数据与显示分离

    重用性

    可重用性高

    Ø JDOM操作XML

    JDOM可以很方便的操作XML文档,完成XML内容的创建、修改,已经遍历Document文档中的XML元素,完成查询等。下面我们就用JDOM完成这些功能。

    # 准备

    首先我们要准备jdom相关的jar包

    jdom-jar下载地址:http://www.jdom.org/dist/binary/

    jaxen在jdom的zip压缩包中可以找到。

    Junit是测试用的,可以不添加。但需要用main方法测试。

    Junit-jarhttp://ebr.springsource.com/repository/app/bundle/version/download?name=com.springsource.org.junit&version=4.8.1&type=binary  

    其次,是准备测试工作。部分测试代码:

    package com.hoo.test;
     
    import java.io.File;
    import java.io.IOException;
    import java.util.List;
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    import org.jdom.Attribute;
    import org.jdom.Comment;
    import org.jdom.Document;
    import org.jdom.Element;
    import org.jdom.JDOMException;
    import org.jdom.Namespace;
    import org.jdom.Text;
    import org.jdom.input.SAXBuilder;
    import org.jdom.output.XMLOutputter;
    import org.jdom.xpath.XPath;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
     
    /**
     * <b>function:</b> JDOM操作XML
     * @author hoojo
     * @createDate 2011-8-4 下午12:34:09
     * @file DocumentTest.java
     * @package com.hoo.test
     * @project JDOMTest
     * @blog http://blog.csdn.net/IBM_hoojo
     * @email hoojo_@126.com
     * @version 1.0
     */
    public class DocumentTest {
        
        private XMLOutputter out = null;
        
        @Before
        public void init() {
            //输出文件信息
            out = new XMLOutputter();
        }
        
        @After
        public void destory() {
            if (out != null) {
                out = null;
            }
            System.gc();
        }
        
        /**
         * <b>function:</b>输出Document文档信息
         * @author hoojo
         * @createDate 2011-8-5 下午12:10:27
         * @param doc
         */
        private void print(Document doc) {
            //设置XML文件编码格式
            //out.setFormat(Format.getCompactFormat().setEncoding("gb2132"));
            System.out.println(out.outputString(doc));
        }
        
        private void fail(Object o) {
            if (o != null) {
                System.out.println(o);
            }
        }
    }
     

    # 创建Document

    /**
     * 创建xml元素
     */
    @Test
    public void createDoc() {
        Document doc = null;
        //method 1、创建一个Doc文档,添加一个元素root
        doc = new Document(new Element("root"));
        print(doc);
        
        //method 2、创建一个Doc文档,添加一个元素root,设置root元素的节点文本
        doc = new Document(new Element("root").setText("this is a root el"));
        print(doc);
        
        //method 3、创建一个Doc文档,添加一个元素root,设置root元素的节点文本且添加一个属性id,值为110
        Element root = new Element("root");
        root.setText("this is a root el");
        root.setAttribute("id", "110");
        doc.setRootElement(root);
        fail("method 3: 
    " + out.outputString(doc));
        
        //method 4、创建一个Doc文档,添加一个元素root,设置root元素的节点文本
        doc = new Document();
        doc.addContent(new Element("root").setText("this is a root el"));
        fail("method 4: 
    " + out.outputString(doc));
        
        fail(doc.toString());
    }

    * new Document可以创建一个doc文档

    当给Document传递一个Element参数时,这个Element就是根元素;

    当调用Document的setRootElement方法时,可以设置当前Doc的根元素;

    当调用doc的addContent的时候,添加的元素将会是根元素;

    doc = new Document(new Element("root").setText("this is a root el"));

    上面就创建了一个doc,根元素是root,root节点的内容是this is a root el;

    注意setText方法返回的对象是当前Element,类似是StringBuffer的append方法; 

    * new Element()可以创建一个元素

    如果传递参数那么这个参数将会是元素节点的名称;

    Element的setText方法可以设置元素的文本值;

    Element root = new Element("root");
    root.setText("this is a root el");

    创建一个节点名称为root的元素,文本是this is a root el

    * setAttribute()可以设置某个具体节点的属性值

    root.setAttribute("id", "110");

    给root节点添加一个id,值为110

    * addContent添加注释

    root .addContent(new Comment("注释"));

    在root元素下添加一个注释;

    addContent是向元素中添加内容,而setContent是设置内容;

    * setText设置元素文本内容

    root.setText("this is a root el");
    同样
    root. setContent(new Text("this is text"))
    同样
    root.addContent("this is text");

    下面用上面的这些方法,创建一篇XML文档。文档内容如下:

    /**
        创建一遍xml文档
        <?xml version="1.0" encoding="UTF-8"?>
        <car vin="123fhg5869705iop90">
          <!--Description of a car-->
          <make>Toyota</make>
          <model>Celica</model>
          <year>1997</year>
          <color>green</color>
          <license state="CA">1ABC234</license>
        </car>
     */
    @Test
    public void createXMLDoc() {
        //创建一个car的元素
        Element carEl = new Element("car");
        //创建vin属性,并设置值
        carEl.setAttribute("vin", "123fhg5869705iop90");
        
        //创建注释
        carEl.addContent(new Comment("Description of a car"));
        
        //创建一个make元素,设置文本内容
        carEl.addContent(new Element("make").setText("Toyota"));
        
        //创建一个model元素,添加一个文本元素
        carEl.addContent(new Element("model").setContent(new Text("Celica")));
        
        //创建一个year元素,添加文本内容
        carEl.addContent(new Element("year").addContent("1997"));
        
        //创建一个color元素,文本内容是green
        carEl.addContent(new Element("color").setText("green"));
        
        //创建一个license的元素
        Element licenseEl = new Element("license");
        //为license元素添加文本内容
        licenseEl.addContent("1ABC234");
        //创建一个state的属性,值为CA
        licenseEl.setAttribute("state", "CA");
        //将licenseEl添加到根元素中
        carEl.addContent(licenseEl);
        
        //将car元素设置为根元素
        Document doc = new Document(carEl);
        print(doc);
        /*out = new XMLOutputter();
        try {
            out.output(doc, System.out);
        } catch (IOException e) {
            e.printStackTrace();
        }*/
    }

    方法运行后,所创建的文档和上面注释文档内容相同

    # 读取XML文件的内容

    disk.xml文件内容如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <HD>
        <disk name="C">
            <capacity>8G</capacity>
            <directories>200</directories>
            <files>1580</files>
        </disk>
        <disk name="D">
            <capacity>10G</capacity>
            <directories>500</directories>
            <files>3000</files>
        </disk>
        <disk2 name="E">
            <capacity>11G</capacity>
            <directories>50</directories>
            <files size="200" modifyDate="2011-08-3">
                <file>Java book</file>
                <file>Spring.txt</file>
                <file>strtus.doc</file>
            </files>
        </disk2>
        <files size="220">500</files>
    </HD>

    读取disk文件的内容,代码如下:

    /**
     * <b>function:</b>读取xml文件中的元素
     * @author hoojo
     * @createDate 2011-8-4 下午04:54:17
     */
    @Test
    @SuppressWarnings("unchecked")
    public void readXMLContent() {
        SAXBuilder builder = new SAXBuilder();
        try {
            Document doc = builder.build(new File("file/disk.xml"));
            Element rootEl = doc.getRootElement();
            //获得所有子元素
            List<Element> list = rootEl.getChildren();
            //List<Element> list = rootEl.getChildren("disk");
            for (Element el : list) {
                //获取name属性值
                String name = el.getAttributeValue("name");
                //获取子元素capacity文本值
                String capacity = el.getChildText("capacity");
                //获取子元素directories文本值
                String directories = el.getChildText("directories");
                String files = el.getChildText("files");
                System.out.println("磁盘信息:");
                System.out.println("分区盘符:" + name);
                System.out.println("分区容量:" + capacity);
                System.out.println("目录数:" + directories);
                System.out.println("文件数:" + files);
                System.out.println("-----------------------------------");
            }
        } catch (JDOMException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    * getChildren方法可以获取所有子元素

    * getChildren(elName)可以获取所有名称为elName的子节点

    * getAttributeValue可以获取指定属性的值

    * getChildText可以获取子节点的文本值

    # 递归显示文档信息

    /**
     * 递归返回指定格式的“--”
     */
    private String format(int i) {
        String temp = "";
        if (i > 0) {
            temp += "--";
            i--;
            temp += format(i);
        }
        return temp;
    }
     
    /**
     * <b>function:</b>显示当前节点所有Element的属性信息
     * @author hoojo
     * @createDate 2011-8-4 下午06:10:53
     * @param el
     * @return
     */
    @SuppressWarnings("unchecked")
    private String getAttrInfo(Element el) {
        List<Attribute> attrs = el.getAttributes();
        return getAttrInfo(attrs);
    }
     
    /**
     * <b>function:</b>显示属性信息
     * @author hoojo
     * @createDate 2011-8-9 下午03:52:59
     * @param attrs
     * @return
     */
    private String getAttrInfo(List<Attribute> attrs) {
        StringBuilder info = new StringBuilder();
        for (Attribute attr : attrs) {
            info.append(attr.getName()).append("=").append(attr.getValue()).append(", ");
        }
        if (info.length() > 0) {
            return "[" + info.substring(0, info.length() - 2)+ "]";
        }
        return "";
    }
     
    /**
     * <b>function:</b>递归显示文档节点元素信息
     * @author hoojo
     * @createDate 2011-8-4 下午05:56:34
     * @param i
     * @param list
     */
    @SuppressWarnings("unchecked")
    private void print(int i, List<Element> list) {
        i++;
        for (Element el : list) {
            List<Element> childs = el.getChildren();
            if (childs.size() > 0) {
                fail(format(i) + el.getName() + "  " + getAttrInfo(el));
                print(i, childs);
            } else {
                fail(format(i) + el.getName() + ":" + el.getText() + "  " + getAttrInfo(el));
            }
        }
    }

    调用print(0, root.getChildren());方法就可以看到一篇格式化后输出的文档内容

    #############显示文档信息###############
    --HD
    ----disk [name=C]
    ------capacity:8G
    ------directories:200
    ------files:1580
    ----disk [name=D]
    ------capacity:10G
    ------directories:500
    ------files:3000
    ----disk2 [name=E]
    ------capacity:11G
    ------directories:50
    ------files [size=200, modifyDate=2011-08-3]
    --------file:Java book
    --------file:Spring.txt
    --------file:strtus.doc
    ----files:500 [size=220]

    # XPath查询遍历XML文档

    /**
     * <b>function:</b>用xpath遍历xml信息
     * @author hoojo
     * @createDate 2011-8-4 下午04:56:52
    * xpath参考:http://www.w3school.com.cn/xpath/xpath_functions.asp
     * 
     *     nodeName 选取此节点的所有子节点 
        /    从根节点选取 
        //   从匹配选择的当前节点选择文档中的节点,而不考虑它们的 
        .    选取当前节点 
        ..   选取当前节点的父节点 
        @  选取属性 
        
        * 匹配任何元素节点 
        @* 匹配任何属性节点 
        node() 配任何类型的节点 
        
        ancestor 选取当前节点的所有先辈(父、祖父等) 
        ancestor-or-self 选取当前节点的所有先辈(父、祖父等)以及当前节点本身 
        attribute 选取当前节点的所有属性 
        child 选取当前节点的所有子元素。 
        descendant 选取当前节点的所有后代元素(子、孙等)。 
        descendant-or-self 选取当前节点的所有后代元素(子、孙等)以及当前节点本身。 
        following 选取文档中当前节点的结束标签之后的所有节点。 
        namespace 选取当前节点的所有命名空间节点 
        parent 选取当前节点的父节点。 
        preceding 选取文档中当前节点的开始标签之前的所有节点。 
        preceding-sibling 选取当前节点之前的所有同级节点。 
        self 选取当前节点。
        
        child::book 选取所有属于当前节点的子元素的 book 节点 
        attribute::languane 选取当前节点的 languange 属性 
        child::* 选取当前节点的所有子元素 
        attribute::* 选取当前节点的所有属性 
        child::text() 选取当前节点的所有文本子节点 
        child::node() 选取当前节点的所有子节点 
        descendant::book 选取当前节点的所有 book 后代 
        ancestor::book 选择当前节点的所有 book 先辈
     */
    @SuppressWarnings("unchecked")
    @Test
    public void queryElementByXPath() {
        SAXBuilder builder = new SAXBuilder();
        try {
            Document doc = builder.build(new File("file/disk.xml"));
            List<Element> list = XPath.selectNodes(doc, "/HD/disk");
            for (Element el : list) {
                String name = el.getAttributeValue("name");
                String capacity = el.getChildText("capacity");
                String directories = el.getChildText("directories");
                String files = el.getChildText("files");
                System.out.println("磁盘信息:");
                System.out.println("分区盘符:" + name);
                System.out.println("分区容量:" + capacity);
                System.out.println("目录数:" + directories);
                System.out.print("文件数:" + files);
                
                String capacityText = ((Text) XPath.selectSingleNode(el, "//disk[@name='" + name + "']/capacity/text()")).getTextNormalize();
                System.out.println("#" + capacityText);
                
                System.out.println("-----------------------------------");
            }
            //显示文档信息
            System.out.println("#############显示文档信息###############");
            print(0, doc.getContent());
            
            //获得hd元素
            System.out.println("#############显示HD子元素信息###############");
            Element root = (Element) XPath.selectSingleNode(doc, "/HD");
            //fail(root.getChildren().size());
            print(0, root.getChildren());
            
            //获取hd下所有元素
            System.out.println("#############显示HD子元素信息###############");
            List roots = (List) XPath.selectNodes(doc, "/HD/*");
            //fail(roots.size());
            print(0, roots);
            
            //获得hd下的所有disk元素
            System.out.println("#############显示disk信息###############");
            roots = (List) XPath.selectNodes(doc, "/HD/disk");
            //fail(roots.size());
            print(0, roots);
            
            System.out.println("#############显示disk2信息###############");
            roots = (List) XPath.selectNodes(doc, "/HD/disk2");
            print(0, roots);
            
            System.out.println("#############显示任意路径下的files信息###############");
            roots = (List) XPath.selectNodes(doc, "//files");
            print(0, roots);
            
            System.out.println("#############显示任意路径下的files指定下标的file信息###############");
            roots = (List) XPath.selectNodes(doc, "//files/file[1]");
            print(0, roots);
            
            System.out.println("#############显示任意路径下的files最后的file信息###############");
            roots = (List) XPath.selectNodes(doc, "//files/file[last()]");
            print(0, roots);
            
            System.out.println("#############显示任意路径下的files倒数第二的file信息###############");
            roots = (List) XPath.selectNodes(doc, "//files/file[last() - 1]");
            print(0, roots);
     
            System.out.println("#############显示任意路径下的files的子元素file位置position在第二的file信息###############");
            roots = (List) XPath.selectNodes(doc, "//files/file[position() = 2]");
            //roots = (List) XPath.selectNodes(doc, "//files/file[position() > 2]");
            print(0, roots);
            
            System.out.println("#############显示任意路径下的files第三个file的当前节点的前面所有同级节点信息###############");
            roots = (List) XPath.selectNodes(doc, "//files/file[3]/preceding-sibling::*");
            print(0, roots);
            
            System.out.println("#############显示任意路径下的disk2之前的所有节点信息###############");
            roots = (List) XPath.selectNodes(doc, "//disk2/preceding::*");
            print(0, roots);
            
            System.out.println("#############显示任意路径下的disk2之后的所有节点信息###############");
            roots = (List) XPath.selectNodes(doc, "//disk2/following::*");
            print(0, roots);
            
            System.out.println("#############显示任意路径下的files的所有属性信息###############");
            roots = (List) XPath.selectNodes(doc, "//files/attribute::*");
            fail(getAttrInfo(roots));
            
            System.out.println("#############显示任意路径下的节点是disk属性name=C的信息###############");
            roots = (List) XPath.selectNodes(doc, "//disk[@name='C']");
            print(0, roots);
            
            System.out.println("#############显示任意路径下的节点是disk的子元素的文本中含义5和8节点的信息###############");
            roots = (List) XPath.selectNodes(doc, "//disk/child::*[contains(text(), '8') and contains(text(), '5')]");
            //roots = (List) XPath.selectNodes(doc, "//disk/child::*[contains(text(), '8') or contains(text(), '5')]");
            print(0, roots);
     
            System.out.println("#############显示任意路径下的节点是files且有属性size的信息###############");
            roots = (List) XPath.selectNodes(doc, "//files[@size]");
            print(0, roots);
     
            System.out.println("#############显示HD节点下capacity的值为11G的信息###############");
            //roots = (List) XPath.selectNodes(doc, "/HD/disk/capacity[text()='11G']");
            roots = (List) XPath.selectNodes(doc, "/HD/*/capacity[text()='11G']");
            //roots = (List) XPath.selectNodes(doc, "/*/*/capacity[text()='11G']");
            print(0, roots);
            
            //parent::*表示父节点集合
            System.out.println("#############显示任意路径下的节点是files且属性size有值的父节点的信息###############");
            roots = (List) XPath.selectNodes(doc, "//files[@size='200']/parent::*");
            print(0, roots);
            
            System.out.println("#############显示任意路径下的节点disk的子节点的capacity信息###############");
            roots = (List) XPath.selectNodes(doc, "//disk/child::capacity");
            print(0, roots);
            
            //获取c盘的大小
            System.out.println("获取c盘的大小");
            Text filesText = (Text) XPath.selectSingleNode(doc, "/HD/disk[@name='C']/files/text()");
            System.out.println(filesText.getTextNormalize());
            
            //XPath function
            /**
            string concat (string, string, string*)  联接两个字符串 
            boolean starts-with (string, string)  判断某字符串是否以另一字符串开头 
            boolean contains (string, string)  判断某字符串是否包含另一字符串 
            string substring (string, number, number)  取子字符串 
            number string-length (string)  测字符串长度 
            number sum (node-set)  求和 
            number floor (number)  求小于此数的最大整数值 
            number ceiling (number)  求大于此数最小整数值
            **/ 
     
            System.out.println("获取@size的和大于200的");
            roots = (List) XPath.selectNodes(doc, "//files[sum(@size) > 200]");
            print(0, roots);
     
            System.out.println("查找directories的内容长度小于3的");
            roots = (List) XPath.selectNodes(doc, "//directories[string-length(text()) < 3]");
            print(0, roots);
            
            System.out.println("查找files的内容包含5的");
            roots = (List) XPath.selectNodes(doc, "//files[contains(text(), '5')]");
            print(0, roots);
        } catch (JDOMException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } 
    }

    # 删除元素及其他操作

    /**
     * <b>function:</b>打印doc相关信息
     * @author hoojo
     * @createDate 2011-8-10 下午06:29:01
     */
    @SuppressWarnings("unchecked")
    @Test
    public void printInfo() {
        SAXBuilder builder = new SAXBuilder();
        try {
            //builder.setFeature("user", true);
            //builder.setIgnoringBoundaryWhitespace(true);
            //忽略元素内容的空格
            //builder.setIgnoringElementContentWhitespace(true);
            
            Document doc = builder.build(new File("file/web.xml"));
            fail("baseURI: " + doc.getBaseURI());
            fail("ContentSize: " + doc.getContentSize());
            //System.out.println("getContent: ");
            //print(0, doc.getContent());
            
            fail("getContent index: " + doc.getRootElement().getContent(1));
            fail("getDocType: " + doc.getDocType());
            fail("getParent: " + doc.getRootElement().getContent(1).getParent());
            fail("getProperty: " + doc.getProperty("filter"));
            print(0, XPath.selectNodes(doc, "//*[contains(text(), '#')]"));
            fail("getText: " + ((Element)XPath.selectNodes(doc, "//*[contains(text(), '#')]").get(0)).getText());
            fail("getTextTrim: " + ((Element)XPath.selectNodes(doc, "//*[contains(text(), '#')]").get(0)).getTextTrim());
            fail("getTextNormalize: " + ((Element)XPath.selectNodes(doc, "//*[contains(text(), '#')]").get(0)).getTextNormalize());
            fail("hasRootElement: " + doc.hasRootElement());
            
            //如果文档带有Namespace一定要设置Namespace,不然无法读取内容
            Namespace ns = Namespace.getNamespace("http://java.sun.com/xml/ns/javaee");
            Element servletEl = doc.getRootElement().getChild("servlet", ns);
            fail("servletEl: " + servletEl);
            print(0, servletEl.getChildren());
            
            fail("getChildText: " + servletEl.getChildText("servlet-class", ns));
            fail("getChildTextNormalize: " + servletEl.getChildTextNormalize("servlet-name", ns));
            fail("getChildTextTrim: " + servletEl.getChildTextTrim("servlet-class", ns));
            fail("getName: " + servletEl.getName());
            fail("getNamespacePrefix: " + servletEl.getNamespacePrefix());
            fail("getNamespace: " + servletEl.getNamespace());
            fail("getQualifiedName: " + servletEl.getQualifiedName());
            Element classEl = servletEl.getChild("servlet-class", ns);
            fail("getText: " + classEl.getText());
            fail("getTextNormalize: " + classEl.getTextNormalize());
            fail("getTextTrim: " + classEl.getTextTrim());
            fail("getValue: " + classEl.getValue());
            
            //删除节点
            fail(doc.getRootElement().removeContent(3));
            //print(0, doc.removeContent());
            //print(0, doc.getRootElement().getChildren());
            fail(servletEl.removeChild("servlet-class", ns));
            fail(servletEl.removeChildren("init-param", ns));
            
            print(0, servletEl.getChildren());
        } catch (JDOMException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
  • 相关阅读:
    触摸屏、X11去掉鼠标
    RPM验证与数字签名(Verify/Signature)
    GPG入门
    DIY的RPM包怎么签名呢
    DIY的RPM包怎么签名呢 How to sign your custom RPM package with GPG key
    iOS开发基础知识--碎片40
    iOS开发基础知识--碎片39
    iOS开发基础知识--碎片38
    iOS开发基础知识--碎片37
    iOS开发基础知识--碎片36
  • 原文地址:https://www.cnblogs.com/kungfupanda/p/7232009.html
Copyright © 2020-2023  润新知