可扩展标记语言XML笔记

一、概述

  • 可扩展标记语言(Extensible Markup Language)
  • .XML文件是保存XML数据的一种方式,XML数据也可以以其他的方式存在(如在内存中构建XML数据),不要将XML语言狭隘地理解为XML文件
    • XML通常指的是具有特定格式的字符串
  • 特点
    • XML具有平台无关性,是一门独立的标记语言
      • 不同操作系统都可以打开XML文件(与操作系统的无关性)
      • 不同的编程语言解析同一份XML文件的结果都是一样的(与编程语言的无关性)
      • XML文件独立存在也是有意义的
    • XML具有自我描述性
      • 文件首行就是XML文档声明
  • 作用
    • 可用于网络数据传输
    • 可用于数据存储
    • 可用于配置文件的编写

二、XML的语法格式

1. XML文档声明

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

2、标记(元素/标签/节点)

XML文档,由一个个的标记组成.
        语法:
                开始标记(开放标记): <标记名称>
                结束标记(闭合标记): </标记名称>
                标记名称: 自定义名称,必须遵循以下命名规则:
                        1.名称可以含字母、数字以及其他的字符
                        2.名称不能以数字或者标点符号开始
                        3.名称不能以字符 “xml”(或者 XML、Xml)开始
                        4.名称不能包含空格,不能包含冒号(:)
                        5.名称区分大小写
                标记内容: 开始标记与结束标记之间 ,是标记的内容.
                        例如 ,我们通过标记, 描述一个人名:
                                <name>张三</name>

3、一个XML文档中, 必须有且且仅允许有一个根标记

正例:
<names>
    <name>张三</name>
    <name>李四</name>
</names>
反例:
<name>李四</name>
<name>麻子</name>

4、标记可以嵌套,但是不允许交叉

正例:
<person>
    <name>李四</name>
    <age>18</age>
</person>
反例:
<person>
    <name>李四<age></name>
    18</age>
</person>

5、标记的层级称呼 (子标记, 父标记 , 兄弟标记, 后代标记 ,祖先标记)

例如:
<persons>
    <person>
        <name>李四</name>
        <length>180cm</length>
    </person>
    <person>
        <name>李四</name>
        <length>200cm</length>
    </person>
</persons>

name是person的子标记.也是person的后代标记
name是persons的后代标记
name是length的兄弟标记
person是name的父标记
persons是name的祖先标记

6、标记名称允许重复

7、标记除了开始和结束 , 还有属性

  • 标记中的属性, 在标记开始时 描述, 由属性名和属性值 组成
  • 格式
    • 在开始标记中, 描述属性可以包含0-n个属性, 每一个属性是一个键值对!
      属性名不允许重复 , 键与值之间使用等号连接, 多个属性之间使用空格分割.
      属性值 必须被引号引住
  • 举例
<persons>
    <person id="10001" groupid="1">
        <name>李四</name>
        <age>18</age>
    </person>
    <person id="10002" groupid="1">
        <name>李四</name>
        <age>20</age>
    </person>
</persons>

8、注释

  • 注释不能写在文档的文档声明前

  • 注释不能嵌套注释

  • 格式

    • 注释开始:<!--

    • 注释结束:-->

9、语法进阶之CDATA(了解)

  • CDATA 是不应该由 XML 解析器解析的文本数据
    • 像 "<" 和 "&" 字符在 XML 元素中都是非法的
      • "<" 会产生错误,因为解析器会把该字符解释为新元素的开始
      • "&" 会产生错误,因为解析器会把该字符解释为字符实体的开始
    • 某些文本,比如 JavaScript 代码,包含大量 "<" 或 "&" 字符。为了避免错误,可以将脚本代码定义为 CDATA
    • CDATA 部分中的所有内容都会被解析器忽略
    • CDATA 部分由 "<![CDATA[" 开始,由 "]]>" 结束

三、java解析XML的方式

1、面试题

问题:java中有几种XML解析方式?分别是什么?有什么样的优缺点?

回答:

  • 四种,但本质是两种,即SAX解析和DOM解析

1、SAX解析

  • 解析的方式是事件驱动机制
  • SAX解析器会逐行读取XML文件解析,每当解析到一个标签的开始/结束/内容/属性时,触发事件
    • 我们可以编写程序在这些事件发生时,进行相应的处理
  • 优点
    • 分析能够立即开始,而不是等待所有的数据加载完毕后再处理
    • 逐行加载,也就是内存中永远只会有一行的数据,能够节省内存,有助于解析大于系统内存的文档
    • 有时候不必解析整个文档,它可以在某个条件得到满足时停止解析
  • 缺点
    • 单向解析,无法定位文档层次,无法同时访问同一文档的不同部分数据
      • 因为SAX是逐行解析,解析到n行时,n-1行已经被释放了,无法再对其进行操作
    • 无法得知事件发生时元素的层次,只能自己维护节点的父子关系
    • 只读解析方式,无法修改XML文档的内容

2、DOM解析

  • 是用与平台和语言无关的方式表示XML文档的官方w3c标准,分析该结构通常需要加载整个文档,并在内存中建立文档树模型。程序员可以通过操作文档树,来完成数据的获取、修改、删除等
  • 优点
    • 文档在内存中加载,允许对数据和结构做出更改
    • 访问是双向的,可以在任何时候在树中双向解析数据
  • 缺点
    • 文档全部加载在内存中,消耗资源大(可忽略,因为XML文件实际上并不会很大,所以DOM相当于没有缺点,经常使用该方法解析XML文件)

3、JDOM解析

  • 目的是成为java特定文档模型,它简化与XML的交互,并且比使用DOM实现更快。由于是第一个java特定模型,JDOM一直得到大力推广和促进
  • JDOM文档声明其目的是“使用20%或更少的经历解决80%或更多java/XML问题”
  • 优点
    • 使用具体类而不是接口,简化了DOM的API
    • 大量使用了java集合类,方便java开发人员操作
  • 缺点
    • 没有较好的灵活性
    • 性能不是那么优异

4、DOM4J解析

  • 它是JDOM的一种智能分支,合并了许多超出基本XML文档表示的功能,包括集成的XPath支持、XML、Schema支持以及用于大文档或流化文档的基于事件的处理。
  • 它还提供了构建文档表示的选项,是一个非常优秀的Java XML API,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件,如今可以看到越来越多的java软件都在使用DOM4J来读写XML
    • 目前许多开源项目中大量采用DOM4J,例如Hibernate

四、java生成XML

  • 导包
    • 这三个包下面解析XML的例子也会用到

  •  步骤和方法解析

1、通过文档帮助器 (DocumentHelper) , 创建空的文档对象

Document doc = DocumentHelper.createDocument();

2、通过文档对象, 向其中添加根节点

Element root = doc.addElement("根节点名称");

3、通过根节点对象root , 丰富我们的子节点

Element e = root.addElement("元素名称");

4、创建一个文件输出流 ,用于存储XML文件

FileOutputStream fos = new FileOutputStream("要存储的位置");

5、将文件输出流, 转换为XML文档输出流

XMLWriter xw = new XMLWriter(fos);

6、写出文档

xw.write(doc);

7、释放资源

xw.close();
  • 举例
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.XMLWriter;

import java.io.FileOutputStream;
import java.io.IOException;

public class demo1 {
    public static void main(String[] args) throws IOException {
        //通过文档帮助器创建一个空的文档对象
        Document document = DocumentHelper.createDocument();
        //创建一个根结点
        Element books = document.addElement("books");
        //在根结点下继续创建节点
        for (int i=0;i<3;i++){
            //创建book节点
            Element book = books.addElement("book" + i);
            //向book节点添加id属性
            book.addAttribute("id",i+"");
            //向book节点添加两个子节点
            Element name = book.addElement("name");
            Element info = book.addElement("info");
            //设置子节点的内容
            name.setText("金苹果"+i);
            info.setText("金苹果的故事"+i);
        }
        //创建文件的输出流
        FileOutputStream fos = new FileOutputStream("books.xml");
        //将文件输出流转换为XML文档输出流
        XMLWriter xmlWriter = new XMLWriter(fos);
        //写出xml文档
        xmlWriter.write(books);
        //关闭流
        fos.close();

    }
}
  • 生成的xml文档展示

 

 五、DOM4J解析XML文档

1、步骤

1、引入dom4j.jar文件

2、创建一个指向XML文件的输入流

FileInputStream fis = new FileInputStream("xml文件的地址");

3、创建一个XML读取工具对象

SAXReader sr = new SAXReader();

4、使用读取工具对象, 读取XML文档的输入流 , 并得到文档对象

Document doc = sr.read(fis);

5、通过文档对象, 获取XML文档中的根元素对象

Element root = doc.getRootElement();

2、文档对象Document的常用API

文档对象指的是加载到内存的整个XML文档

  • 通过文档对象,获取XML文档中的根元素对象
Element root = doc.getRootElement();
  • 添加根结点
Element root = doc.addElement("根节点名称");

3、元素对象Element常用API

元素对象指的是XML文档中的单个节点

  • 获取节点名称
String getName();
  • 获取节点内容
String getText();
  • 设置节点内容
String setText();
  • 根据子节点的名称,获取匹配名称的第一个子节点对象
Element element(String 子节点名称);
  • 获取所有的子节点对象
List<Element> elements();
  • 获取节点的属性值
String attributeValue(String 属性名称);
  • 获取子节点的内容
String elementText(String 子节点名称);
  • 添加子节点
Element addElement(String 子节点名称);
  • 添加属性
void addAttribute(String 属性名,String 属性值);

4、举例:解析本地文件

  • 以读取刚刚创建的books.xml为例
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

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

public class demo2 {
    public static void main(String[] args) throws IOException, DocumentException {
        //1、创建一个XML文件的输入流
        FileInputStream fis = new FileInputStream("books.xml");
        //2、创建一个XML文件的读取工具对象
        SAXReader reader = new SAXReader();
        //3、读取XML文件并获取文档对象
        Document document = reader.read(fis);
        //4、通过文档对象获取根结点
        Element rootElement = document.getRootElement();
        //5、通过根节点获取所有子节点
        List<Element> elements = rootElement.elements();
        //6、循环遍历节点数据
        for (Element e : elements){
            //获取属性id值
            String id = e.attributeValue("id");
            //获取子节点name的内容
            String name = e.element("name").getText();
            //获取子节点info的内容
            String info = e.element("info").getText();
            System.out.println("id="+id+",name="+name+",info="+info);
        }
        //7、关闭流
        fis.close();
    }
}
  • 运行结果

 5、举例:解析网络文件案例

  • 网址

http://apis.juhe.cn/mobile/get?phone=18375072028&dtype=xml&key=9f3923e8f87f1ea50ed4ec8c39cc9253

  • 网址的效果

  •  解析这个网址XML内容的代码
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

public class demo3 {
    public static void main(String[] args) throws IOException, DocumentException {
        String phone = "18375072028";
        //1. 获取到XML资源的输入流
        URL url = new URL("http://apis.juhe.cn/mobile/get?phone=" + phone + "&dtype=xml&key=9f3923e8f87f1ea50ed4ec8c39cc9253");
        URLConnection conn = url.openConnection();
        InputStream is = conn.getInputStream();
        //2. 创建一个XML读取对象
        SAXReader sr = new SAXReader();
        //3. 通过读取对象 读取XML数据,并返回文档对象
        Document doc = sr.read(is);
        //4. 获取根节点
        Element root = doc.getRootElement();
        //5. 解析内容
        String code = root.elementText("resultcode");
        if ("200".equals(code)) {
            Element result = root.element("result");
            String province = result.elementText("province");
            String city = result.elementText("city");
            if (province.equals(city)) {
                System.out.println("手机号码归属地为:" + city);
            } else {
                System.out.println("手机号码归属地为:" + province + " " + city);
            }
        } else {
            System.out.println("请输入正确的手机号码");
        }
    }
}
  • 运行效果

 六、DOM4J-XPATH解析XML

1、路径表达式

  • 通过路径快速查找一个或一组元素
  • 路径表达式

/ :从根节点开始查找

// :从发起查找的结点位置,查找后代节点(常用)

. : 查找当前节点

.. : 查找父节点

@ : 选择属性

        属性使用方式:

                [@属性名='值']

                [@属性名>'值']

                [@属性名<'值']

                [@属性名!='值']

  • 举例
    • 查找book属性的id为1的节点,获取该节点的name值
    • 路径://book[@id='1']//name

2、使用步骤

  • 通过Node类的两个方法来完成查找
    • Node是Document与Element的父接口
  • 方法1
    • 根据路径表达式,查找匹配的单个节点
Element e = selectSingleNode("路径表达式");
  • 方法2
    • 根据路径表达式,查找匹配的所有节点
List<Element> es = selectNodes("路径表达式");

3、举例

  • 还是以上一节解析网络上的XML文件为例
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

public class demo4 {
    public static void main(String[] args) throws IOException, DocumentException {
        String phone = "18313935565";
        //1. 获取到XML资源的输入流
        URL url = new URL("http://apis.juhe.cn/mobile/get?phone="+phone+"&dtype=xml&key=9f3923e8f87f1ea50ed4ec8c39cc9253");
        URLConnection conn = url.openConnection();
        InputStream is = conn.getInputStream();
        //2. 创建一个XML读取对象
        SAXReader sr = new SAXReader();
        //3. 通过读取对象 读取XML数据,并返回文档对象
        Document doc = sr.read(is);
        Node node = doc.selectSingleNode("//company");
        System.out.println("运营商:"+node.getText());
        is.close();
    }
}
  • 运行效果

Guess you like

Origin blog.csdn.net/future_god_qr/article/details/121266116