Java SE核心API(15) —— XML语法及其解析

版权声明:本文为博主原创文章,遵循GPL开源协议精神,转载请注明出处。 https://blog.csdn.net/Robot__Man/article/details/80918982

一、XML语法

1.1、XML用途

  XML指可扩展标记语言(Extensible Markup Language),是独立于软件和硬件的信息传输工具。XML应用于Web开发的许多方面,常用于简化数据的存储、传输和共享。

1.2、XML基本语法

1.2.1 XML处理指令

  XML处理指令,简称PI(processing instruction),处理指令用来指示解析引擎如何解析XML文档内容。

<?xml version="1.0" encoding="UTF-8"?>

  在XML中,所有的处理指令都以<?开始,?>结束。<?后面紧跟的是处理指令的名称。XML处理指令要求指定一个version属性。并允许指定可选的standalone和encoding,其中standalone是指是否允许使用外部声明,可设置为yes或no。yes是指定不使用外部声明,no为使用。encoding是指作者使用的字符编码格式,有UTF-8,GBK,gb2312等。

1.2.2 元素和属性

  XML文档包含XML元素。XML元素指的是从(且包括)开始标签直到(且包括)结束标签的部分。元素可包含其他元素、文本或者两者的混合物。元素也可以拥有属性。
  XML元素可以在开始标签中包含属性,属性(Attribute)提供关于元素的额外(附加)信息。属性通常提供不属于数据组成部分的信息,但是对需要处理这个元素的应用程序来说却很重要。
  XML属性必须加引号,属性值必须被引号包围,不过单引号和双引号均可使用。如果属性值本身包含引号,那么有必要使用单引号包围它,或者可以使用实体引用。

<datasource id="db_oracle">
...
</datasource>
1.2.3 大小写敏感

  XML对大小写是敏感的,这一点不像HTML。

1.2.4 元素必须有关闭标签

  XML要求每个元素必须由起始标签和关闭标签组成。关闭标签与起始标签的名字相同,写法上多一个”/”。
  另外,XML要求所有元素必须正确的嵌套。

1.2.5 必须有根元素

  XML要求必须有根元素,所谓根元素就是不被其他元素包围。并且根元素只能有一个。

1.2.6 实体引用

  实体可以是常用的短语,键盘字符,文件,数据库记录或任何包含数据的项。在XML中,有时实体内包含一些字符,如& < > ” ‘等。这些均需要对其进行转义,否则会对XML解释器生成错误。

实体引用 字符 说明
&lt ; < 小于
&gt ; > 大于
&amp ; & 与字符(和字符)
&apos ; 单引号
&quot ; 双引号

  (上表中实体引用字段,分号和前一个字符间实际应无空格,这里为显示,加了一空格。)

1.2.7 CDATA段

  格式:<![CDATA[文本内容]]>,特殊标签中的实体引用都被忽略,所有内容被当成一整块文本数据对待。


二、XML解析

2.1 XML解析方式

2.1.1 SAX解析方式

  SAX(simple API for XML)是一种XML解析的替代方法。相比于DOM,SAX是一种速度更快,更有效的方法。它逐行扫描文档,一边扫描一边解析。而且相比于DOM,SAX可以在解析文档的任意时刻停止解析。
  优点:解析可以立即开始,速度快,没有内存压力。
  缺点:不能对节点做修改。

2.1.2 DOM解析方式

  DOM(Document Object Model),即文档对象模型,是W3C组织推荐的处理XML的一种方式。
  DOM解析器在解析XML文档时,会把文档中的所有元素,按照其出现的层次关系,解析成一个个Node对象(节点)。
  优点:把XML文件在内存中构造树形结构,可以遍历和修改节点。
  缺点:如果文件比较大,内存有压力,解析的时间会比较长。

2.2 读XML

2.2.1 SAXReader读取XML文档

  可以创建SAXRead而对象来读取XML文档,而使用SAXReader需要导入dom4j的jar包,这里用1.6.1版本。
  dom4j是一个Java的XML API,类似于jdom,用来读写XML文件的。dom4j是一个非常优秀Java XML API,具有性能优异、功能强大和易用的特点,同时它也是一个开放源代码的软件。

2.2.2 Document的getRootElement方法

  Document对象是一颗文档树的根,可为我们提供对文档数据最初(或最顶层)的访问入口。
  Element对象表示XML文档中的元素。元素可包含属性、其他元素或文本。如果元素含有文本,则在文本节点中表示该文本。
  Element getRootElement()用于获取根元素。

  Attribute对象用于描述一个元素中的某个属性信息。

  关于Element和Attribute的一些方法就不再赘述啦,直接在程序里面说明。

  后面的代码都需要建一个maven工程,要先下载安装maven,并配置好,并导入需要的jar包,关于maven的使用这里也不再赘述啦。

package day12;
/**
 * 该类用于表示xml文档中的一个员工信息
 * @author Administrator
 *
 */
public class Emp {
    private int id;
    private String name;
    private int age;
    private String gender;
    private int salary;

    public Emp() {

    }

    public Emp(int id, String name, int age, String gender, int salary) {
        super();
        this.id = id;
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.salary = salary;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public int getSalary() {
        return salary;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }

    public String toString() {
        return id+","+name+","+age+","+gender+","+salary;
    }
}
package day12;

import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

/**
 * 使用DOM解析xml文档
 * @author Administrator
 *
 */
public class ParseXmlDemo {
    public static void main(String[] args) {
        /*
         *解析emplist.xml文档,将所有的员工信息读取出来并转换为若干Emp实例,
         *存入一个List集合中。 
         *
         *解析XML的流程:
         *1、创建SAXReader;
         *2、使用SAXReader读取XML文档并返回Document对象;
         *   这一步就是DOM解析耗时耗资源的体现,因为DOM会将XML文档全部读取并
         *   以一个Document对象形式存于内存。
         *   Document对象用于描述解析的XML文档内容。
         *3、根据Document对象获取根元素;
         *4、按照xml的结构从根元素中开始逐级获取子元素以达到遍历xml的目的。
         */
        try {
            SAXReader reader = new SAXReader();
            Document doc = reader.read(new FileInputStream("emplist.xml"));

            /*
             * Element的每一个实例用于表示xml文档中的一个元素(一对标签)
             * 这里获取的相当于是emplist.xml文档中的<list>标签
             */
            Element root = doc.getRootElement();
            /*
             * Element提供了获取元素的相关方法:
             * 
             * List elements()
             * 获取当前标签下的所有子标签
             * 
             * List elements(String name)
             * 获取当前标签下所有同名子标签
             * 
             * Element element(String name)
             * 获取指定名字的子标签
             * 
             * Attribute attribute(String name)
             * 获取指定名字的属性
             *
             * String getName()
             * 获取当前标签的名字
             * 
             *String getText()
             *获取当前标签中的文本(前标签和后标签中间的文本信息,前提是确实为文本而
             *不是子标签)
             */
            List<Emp> emplist = new ArrayList<Emp>();

            /*
             * 获取根标签<list>下面的所有子标签<emp>
             */
            List<Element> elements = root.elements();

            /*
             * 遍历所有<emp>标签并解析出该员工相关信息并以一个Emp实例
             * 保存,然后将其存入empList集合
             */
            for(Element empEle:elements) {
                //获取名字
                Element nameEle = empEle.element("name");
                String name = nameEle.getTextTrim();
                //获取年龄
                int age = Integer.parseInt(empEle.elementTextTrim("age"));
                //获取性别
                String gender = empEle.elementTextTrim("gender");
                //获取薪资
                int salary = Integer.parseInt(empEle.elementTextTrim("salary"));

                /*
                 * 获取emp标签中的id属性
                 * Attribute的每一个实例用于表示一个属性信息,常用方法:
                 * String getName()获取当前属性名
                 * String getValue()获取当前属性值
                 */
                Attribute attr = empEle.attribute("id");
                int id = Integer.parseInt(attr.getValue());

                Emp emp = new Emp(id,name,age,gender,salary);
                emplist.add(emp);
            }
            System.out.println("解析完毕!");
            System.out.println("共"+emplist.size()+"个员工!");
            for (Emp emp:emplist) {
                System.out.println(emp);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2.3 写XML

  通过dom4j写出XML的第一步是创建文档对象Documemt。创建Document对象的方式是通过DocumentHelper的静态方法createDocument来获取的。
  static Document createDocument(),创建一个Document对象并返回。

  创建好Document对象后,先添加根元素,然后再向根元素中追加新的子元素,并添加属性或文本等,最后写出生成XML文档。

package day12;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;

/**
 * 使用DOM生成XML文档
 * @author Administrator
 *
 */
public class WriteXmlDemo {
    public static void main(String[] args) {
        List<Emp> emplist = new ArrayList<Emp>();

        emplist.add(new Emp(1,"张三",22,"男",3000));
        emplist.add(new Emp(2,"李四",23,"女",4000));
        emplist.add(new Emp(3,"王五",24,"男",5000));
        emplist.add(new Emp(4,"赵六",25,"女",6000));
        emplist.add(new Emp(5,"钱七",26,"男",7000));

        /*
         * 将emplist集合中的员工信息保存到myemp.xml文档中。
         * 
         * 写出XML文档的大致步骤:
         * 1、创建一个Docunment对象表示一个空白的xml文档。
         * 2、向Document对象中添加根元素。
         * 3、按照应当生成的xml文档的格式逐级向根元素中添加子元素以形成xml文档格式。
         * 4、创建XmlWriter
         * 5、通过XmlWriter将Document写出。
         */
        XMLWriter  writer = null;
        try {
            //1
            Document document = DocumentHelper.createDocument();

            /*
             * 2、添加根标签<list>
             * Document提供了添加根元素的方法
             * 
             * Element addElement(String name)
             * 该方法可以向当前文档中添加给定名字的根元素,并将添加进去的该元素
             * 以一个Element实例返回,以便于对该元素继续操作。
             * 需要注意,该方法只能调用一次,因为一个文档中只能有一个根元素。
             */
            Element root = document.addElement("list");

            /*
             * 将empList集合中的每个员工信息以一个<emp>标签的形式保存到<list>标签中
             */
            for (Emp emp:emplist) {
                /*
                 * Element提供了相关方法:
                 * 
                 * Element addElement(String name)
                 * 向当前标签中添加给定名字的子标签并将其返回,以便继续操作。
                 * 
                 * Element addText(String text)
                 * 向当前标签中添加文本信息,返回值为当前标签。
                 * 
                 * Element addAttribute(String name,String value)
                 * 向当前标签中添加属性,返回值为当前标签。
                 */
                //向根标签<list>中添加子标签<emp>
                Element empEle = root.addElement("emp");

                //向<emp>标签中添加<name>标签
                Element nameEle = empEle.addElement("name");
                nameEle.addText(emp.getName());

                empEle.addElement("age").addText(emp.getAge()+"");

                empEle.addElement("gender").addText(emp.getGender());

                empEle.addElement("salary").addText(emp.getSalary()+"");

                //添加属性
                empEle.addAttribute("id", emp.getId()+"");
            }

            FileOutputStream fos = new FileOutputStream("myemp.xml");
            writer = new XMLWriter(fos,OutputFormat.createPrettyPrint());

            writer.write(document);
            System.out.println("写出完毕!");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

2.4 XPath

2.4.1 路径表达式

  XPath是一门在XML文档中查找信息的语言。XPath可用来在XML文档中对元素和属性进行遍历。
  由于我们单纯使用DOM定位节点时,大部分时间需要一层一层的处理,如果有了XPath,定位节点将变得很轻松。他可以根据路径、属性,甚至是条件进行节点的检索。
  XPath使用路径表达式在XML文档中进行导航。
  XPath包含一个标准函数库,XPath是XSLT中的主要元素,XPath是一个W3C标准。

  斜杠(/)作为路径内部的分割符。
  同一个节点有绝对路径和相对路径两种写法,绝对路径必须用“/”起首,后面紧跟根节点;相对路径则不适用“/”起首。“.”表示当前节点,“..”表示当前节点的父节点。

  nodename(节点名称):表示选择该节点的所有子节点。
  “/”:表示选择根节点。
  “//”:表示选择任意位置的某个节点。
  “@”:表示选择某个属性。

2.4.2 谓语条件

  谓语条件,就是对路径表达式的附加条件。所有的条件,都写在方括号”[]”中,表示对节点进行进一步的帅选。

  /bookstore/book[1]:表示选择bookstore的第一个book子元素。
  /bookstore/book[last()]:表示选择bookstore的倒数第二个book子元素。
  /bookstore/book[last()-1]:表示选择bookstore的倒数第二个book子元素。
  /bookstore/book[position()<3]:表示选择bookstore的前两个book子元素。
  //title[@lang]:表示选择所有具有lang属性的title节点。
  //title[@lang=’eng’]:表示选择所有lang属性的值等于“eng”的title节点。
  /bookstore/book[price]:表示选择bookstore的book子元素,且被选中的book元素必须带有price子元素。
  /bookstore/book[price>35.00]:表示选择bookstore的book子元素,且被选中的book元素的price子元素值必须大于35。
  /bookstore/book[price>35.00]/title:表示在上例结果集中,选择title子元素。
  /bookstore/book/price[.>35.00]:表示选择值大于35的“/bookstore/book”的price子元素。

2.4.3 通配符

  “*”表示匹配任何元素节点。
  “@”表示匹配任何属性值。
  node()表示匹配任何类型的节点。

  /bookstore/*:鄙视选择bookstore的所有元素子节点。
  //title[@*]:表示选择所有带有属性的title元素。

2.4.4 Dom4j对XPath的支持

  采用XPath查找需要导入jaxen的jar包,我们用的是1.1.4的版本。
  Document提供了一个对XPath检索的方法:List selectNodes(String XPath),传入XPath路径,获取相应的信息。

package day12;

import java.io.FileInputStream;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

/**
 * 使用XPath检索XML数据
 * @author Administrator
 *
 */
public class XPathDemo {
    public static void main(String[] args) {
        try {
            SAXReader reader = new SAXReader();
            Document doc = reader.read(new FileInputStream("myemp.xml"));
            /*
             * Document支持使用xpath检索数据,前提是必须引入jaxen这个jar包
             */
            String xpath="/list/emp/name";
            List<Element> list = doc.selectNodes(xpath);

            for (Element ele:list) {
                System.out.println(ele.getName() + ":" + ele.getText());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

猜你喜欢

转载自blog.csdn.net/Robot__Man/article/details/80918982