0


一文搞懂XML技术

学习目标

一.XML 概述

1 概念

XML(Extensible Markup Language):可扩展标记语言

可扩展:标签都是自定义的。

**2 发展历程 **

HTML 和 XML 都是 W3C(万维网联盟)制定的标准,最开始 HTML 的语法过于松散,于是 W3C 制定了更严格的 XML 语法标准,希望能取代 HTML。但是程序员和浏览器厂商并不喜欢使用 XML,于是现在的 XML 更多的用于配置文件及传输数据等功能。

配置文件:在今后的开发过程当中我们会频繁使用框架(框架:半成品软件),使用框架时,需要写配置文件配置相关的参数,让框架满足我们的开发需求。而我们写的配置文件中就有一种文件类型是 XML。

传输数据:在网络中传输数据时并不能传输 java 对象,所以我们需要将 JAVA 对象转成字符串传输,其中一种方式就是将对象转为 XML 类型的字符串。

**3 xml 和 html 的区别: **

  • xml 语法严格,html 语法松散
  • xml 标签自定义,html 标签预定义

**4 XML 基本语法 **

  • 文件后缀名是.xml
  • 第一行必须是文档声明
  • 有且仅有一个根标签
  • 属性值必须用引号(单双都可)引起来
  • 标签必须正确关闭
  • 标签名区分大小写

**5 XML 组成部分 **

**5.1 文档声明 **

文档声明必须放在第一行,格式为:<?xml 属性列表 ?>

属性列表:

version:版本号(必须)

encoding:编码方式 (不写时默认是utf-8编码)

**5.2 标签: **

XML 中标签名是自定义的,标签名有以下要求:

  • 包含数字、字母、其他字符 (啥字符都行)
  • 不能以数字和标点符号(下划线和$除外)开头
  • 不能包含空格

**5.3 指令(了解) **

指令是结合 css 使用的,但现在 XML 一般不结合 CSS,语法为:

<?xml-stylesheet type="text/css" href="a.css" ?>

**5.4 属性 **

属性值必须用引号(单双都可)引起来

**5.5 文本 **

如果想原样展示文本,需要设置 CDATA 区,格式为:<![CDATA[想原样展示的文本]]>

二.约束

1.什么是约束

约束是一个文件,可以规定 xml 文档的书写规则。我们作为框架的使用者,不需要会写约束文件,只要能够在 xml 中引入约束文档,简单的读懂约束文档即可。XML 有两种约束文件类型:DTD 和 Schema。

2.DTD 约束

DTD 是一种较简单的约束技术

引入:

本地:<!DOCTYPE 根标签名 SYSTEM "dtd 文件的位置">

网络:<!DOCTYPE 根标签名 PUBLIC "dtd 文件的位置" "dtd 文件路径">

示例:

student.dtd:

<!ELEMENT students (student*) >
<!ELEMENT student (name,age,sex)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT sex (#PCDATA)>
<!ATTLIST student number ID #REQUIRED>

解释:

<!ELEMENT students (student*) > 
*代表多个,一个students结点下面有多个student结点,ELEMENT放在最上面代表students是根结点

<!ELEMENT student (name,age,sex)>
一个student结点下可以放一个name结点,一个age结点,一个sex结点,且按此顺序不能乱!

<!ELEMENT name (#PCDATA)>
PCDATA是文本的意思,即name结点里放的是文本,下面的age,sex同理
<!ELEMENT age (#PCDATA)>
<!ELEMENT sex (#PCDATA)>

<!ATTLIST student number ID #REQUIRED>

student结点有个ID类型的number属性 ,且ID不能重复,#REQUIRED代表必须。

按照如上约束写的student.xml:

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE students SYSTEM "student.dtd">
<students>
    <student number="baizhan001">
        <name>懒羊羊</name>
        <age>10</age>
        <sex>男</sex>
    </student>
    <student number="baizhan002">
        <name>美羊羊</name>
        <age>8</age>
        <sex>女</sex>
    </student>
</students>

3.Schema 约束

DTD约束不常用,而Schema(xsd)比较常用。

引入:

(1)写 xml 文档的根标签

(2)引入 xsi 前缀:确定 Schema 文件的版本。

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

(3)引入 Schema 文件

xsi:schemaLocation="Schema 文件定义的命名空间 Schema 文件的具体路径"

(4)为 Schema 约束的标签声明前缀

xmlns:前缀="Schema 文件定义的命名空间"

例如:

xsd文件本质上也是一个xml文件,即
Schema 约束就是用一个xml文件约束另一个xml文件。

enumeration是枚举类型,意思是只有那几个枚举选项可以选择。

\d是数字的意思,所以\d{4}是四位是四位数字的意思。

targetNamespace是域名空间。 

student.xsd:

<?xml version="1.0"?>
<xsd:schema xmlns="http://www.itbaizhan.cn/xml"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        targetNamespace="http://www.itbaizhan.cn/xml" elementFormDefault="qualified">
    <!--students标签-->
    <xsd:element name="students" type="studentsType"/>
    <xsd:complexType name="studentsType">
        <xsd:sequence>
            <!--student标签,students下的student标签最少有0个,最多无上限-->
            <xsd:element name="student" type="studentType" minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="studentType">
        <xsd:sequence>
            <!--student下又有三个标签,分别是name,age,sex-->
            <xsd:element name="name" type="xsd:string"/>
            <xsd:element name="age" type="ageType" />
            <xsd:element name="sex" type="sexType" />
        </xsd:sequence>
        <!--student下又有一个number属性,是必须的-->
        <xsd:attribute name="number" type="numberType" use="required"/>
    </xsd:complexType>
    <!--对sexType类型的约束-->
    <xsd:simpleType name="sexType">
        <!--是个字符串-->
        <xsd:restriction base="xsd:string">
            <!--枚举类型,要么是male,要么是female-->
            <xsd:enumeration value="male"/>
            <xsd:enumeration value="female"/>
        </xsd:restriction>
    </xsd:simpleType>
    <!--对ageType类型的约束-->
    <xsd:simpleType name="ageType">
        <!--是个整数-->
        <xsd:restriction base="xsd:integer">
            <!--最小值是0,最大值是256-->
            <xsd:minInclusive value="0"/>
            <xsd:maxInclusive value="256"/>
        </xsd:restriction>
    </xsd:simpleType>
    <!--对numberType类型的约束-->
    <xsd:simpleType name="numberType">
        <!--是个字符串-->
        <xsd:restriction base="xsd:string">
            <!--4位整数-->
            <xsd:pattern value="baizhan_\d{4}"/>
        </xsd:restriction>
    </xsd:simpleType>
</xsd:schema> 

按照如上约束写的student.xml:

<?xml version="1.0"?>
<a:students
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.itbaizhan.cn/xml student.xsd"
        xmlns:a="http://www.itbaizhan.cn/xml">
    <!--前缀的作用就是当配置文件多了,前缀可以解决标签重名的问题-->
    <a:student number="baizhan_0001">
        <a:name>喜羊羊</a:name>
        <a:age>10</a:age>
        <a:sex>male</a:sex>
    </a:student>

</a:students>

三.XML解析

1.XML 解析思想

XML 解析即读写 XML 文档中(我们想提取)的数据。框架的开发者通过 XML 解析读取框架使用者配置的参数信息,开发者也可以通过 XML 解析读取网络传来的数据。

DOM:将标记语言文档一次性加载进内存,在内存中形成一颗 dom 树

  • 优点:操作方便,可以对文档进行 CRUD (增删改查)的所有操作
  • 缺点:占内存

SAX:逐行读取,基于事件驱动的。

  • 优点:不占内存,一般用于手机 APP 开发中读取 XML
  • 缺点:只能读取,不能增删改

Java开发中DOM用的比较多,SAX在手机APP中用的比较多。

DOM比较占内存,因为每个结点都要的生成一个Java对象;而SAX是一行一行读取,故只存一行的数据对象,所以不占内存。

2 常见解析器

JAXP:SUN 公司提供的解析器,支持 DOM 和 SAX 两种思想

DOM4J:一款非常优秀的解析器 ,主要支持DOM思想

Jsoup:

Jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据。

PULL:Android 操作系统内置的解析器,支持 SAX 思想

2.Jsoup 解析器

(1)快速入门

步骤:

(1) 导入 jar 包

在工程下新建一个lib目录,将jsoup-1.11.2.jar放进去,右键Add as Library,然后

Level选择Module Library

(2) 加载 XML 文档进内存,获取 DOM 树对象 Document

(3) 获取对应的标签 Element 对象

(4) 获取数据

bug:

获取绝地路径时遇到的一个bug,报了找不到系统指定文件的异常,我看了下我的路径中有个文件名称是Idea 2019,而中间的空格却被解析成了%20

解决办法,参考这篇文章

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.File;
import java.io.IOException;

public class Demo1 {
    //获取XML中所有的学生姓名
    public static void main(String[] args) throws IOException {
        /*
        (2) 加载 XML 文档进内存,获取 DOM 树对象 Document
        2.1找到XML文档的绝对路径
        利用类加载器,通过项目中文件的相对路径找到硬盘中的绝对路径
        */
        //类加载器
        ClassLoader classLoader=Demo1.class.getClassLoader();
        //获得绝对路径
        //用replace将因路径中有空格而出现的%20还原为原来的空格
       String path=classLoader.getResource("com/baizhan/xml/xsd/student.xml").getPath().replace("%20"," ");
        //System.out.println(path);

        //2.2根据XML文档的路径,把XML文档加载进内存,并解析成Dom树对象
        Document document= Jsoup.parse(new File(path),"utf-8");
        //输出的文件内容是html文档,因为jsoup最开始是解析html文档的,所以解析式把document对象封装成html文档
        //System.out.println(document);

        /*
        (3) 获取对应的标签 Element 对象
        方法和js差不多
        */
        //Elements是Element的一个集合
        //根据标签名获得标签时,加了前缀不要忘记写前缀
        Elements name=document.getElementsByTag("a:name");
        //(4) 获取数据
        for (Element element:name){
            String text=element.text();
            System.out.println(text);
        }
    }
}

(2)常用对象

Jsoup:解析 xml 或 html,形成 dom 树对象。

常用方法:

一个解析方法,三个重载

static Document parse(File in, String charsetName):解析本地文件

static Document parse(String html):解析 html 或 xml 字符串

static Document parse(URL url, int timeoutMillis):解析网页源文件

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

import java.io.File;
import java.io.IOException;
import java.net.URL;

public class Demo2 {
    public static void main(String[] args) throws IOException {
        //解析本地文件
        //获得绝对路径
//        String path=Demo2.class.getClassLoader().getResource(
//                "com/baizhan/xml/xsd/student.xsd").getPath().replace("%20"," ");
//        Document document= Jsoup.parse(new File(path),"utf-8");
//        System.out.println(document);

        //解析字符串
//        Document document1=Jsoup.parse("<a:student number=\"baizhan_0001\">\n" +
//                "        <a:name>喜羊羊</a:name>\n" +
//                "        <a:age>10</a:age>\n" +
//                "        <a:sex>male</a:sex>\n" +
//                "    </a:student>\n" +
//                "    <a:student number=\"baizhan_0002\">\n" +
//                "        <a:name>美羊羊</a:name>\n" +
//                "        <a:age>15</a:age>\n" +
//                "        <a:sex>female</a:sex>\n" +
//                "    </a:student>");
//        System.out.println(document1);

        //解析网络资源
        //第一个参数是访问的网络地址,第二个参数是最大等待时间,超过这个时间就默认是访问超时
        Document document=Jsoup.parse(new URL("http://www.baidu.com"),5000);//5s
        System.out.println(document);
    }
}

**Document:xml 的 dom 树对象 **

常用方法:

Element getElementById(String id):根据 id 获取元素

Elements getElementsByTag(String tagName):根据标签名获取元素

Elements getElementsByAttribute(String key):根据属性获取元素

Elements getElementsByAttributeValue(String key,String value):根据属性名=属性值获取元素。

Elements select(Sting cssQuery):根据选择器选取元素。

student.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<students>
    <student number="baizhan_0001">
        <name>喜羊羊</name>
        <age id="a1">10</age>
        <sex class="hh">male</sex>
    </student>
    <student number="baizhan_0002">
        <name>美羊羊</name>
        <age>8</age>
        <sex>female</sex>
    </student>
</students>

Demo3.java :

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.File;
import java.io.IOException;

public class Demo3 {
    public static void main(String[] args) throws IOException {
        String path=Demo3.class.getClassLoader().getResource(
                "com/baizhan/xml/jsoup/student.xml").getPath().replace("%20"," ");
        Document document= Jsoup.parse(new File(path),"utf-8");

        //根据 id 获取元素
        Element element1=document.getElementById("a1");
        System.out.println(element1.text());
        System.out.println("-----------------------");
        //根据标签名获取元素
        Elements elements=document.getElementsByTag("age");
        for (Element element:elements){
            System.out.println(element.text());
        }
        System.out.println("-----------------------");
        //根据属性获取元素
        Elements elements1=document.getElementsByAttribute("number");
        for (Element element:elements1){
            System.out.println(element);
        }
        System.out.println("-----------------------");
        //根据属性名 =属性值获取元素
        Elements elements2=document.getElementsByAttributeValue("number","baizhan_0001");
        for (Element element:elements2){
            System.out.println(element);
        }
        System.out.println("------------------------------------------");
        //根据选择器选取元素(速度最快)
        //css中根据id来选
        Elements elements3=document.select("#a1");
        //text()就是标签内的值
        System.out.println(elements3.text());
        System.out.println("-----------------------");
        //css中根据class来选
        Elements elements4=document.select(".hh");
        System.out.println(elements4);
        System.out.println("-----------------------");
        //css中根据标签名来选
        Elements elements5=document.select("name");
        System.out.println(elements5);
    }
}

Element: 元素对象

常用方法:

String text():获取元素包含的纯文本。

String html():获取元素包含的带标签的文本。

String attr(String attributeKey):获取元素的属性值。

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.File;
import java.io.IOException;

public class Demo4 {
    public static void main(String[] args) throws IOException {
        String path=Demo4.class.getClassLoader().getResource(
                "com/baizhan/xml/jsoup/student.xml").getPath().replace("%20"," ");
        Document document= Jsoup.parse(new File(path),"utf-8");
        Elements elements=document.getElementsByAttributeValue("number","baizhan_0001");
        for (Element element:elements){
            //获取元素包含的纯文本
            System.out.println(element.text());
            System.out.println("------------------------");
            //获取元素包含的带标签的文本
            System.out.println(element.html());
            System.out.println("------------------------");
            //获取元素的属性值。
            System.out.println(element.attr("number"));
        }
    }
}

**3 XPath 解析 **

点击这里可学习XPath规则

XPath 即为 XML 路径语言,它是一种用来确定标记语言文档中某部分位置的语言。

使用方法:

  1. 导入 Xpath 的 jar 包

将JsoupXpath-0.3.2.jar放进去,右键Add as Library,然后Level选择Module Library

  1. 获取 Document 对象

  2. 将 Document 对象转为 JXDocument 对象

  3. JXDocument 调用 selN(String xpath),获取 List<JXNode>对象。

  4. 遍历 List<JXNode>,调用 JXNode 的 getElement(),转为 Element 对象。

  5. 处理 Element 对象。

import cn.wanghaomiao.xpath.exception.XpathSyntaxErrorException;
import cn.wanghaomiao.xpath.model.JXDocument;
import cn.wanghaomiao.xpath.model.JXNode;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

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

public class XPathDemo {
    public static void main(String[] args) throws IOException, XpathSyntaxErrorException {
        //2. 获取 Document 对象
        String path=XPathDemo.class.getClassLoader().getResource(
                "com/baizhan/xml/jsoup/student.xml").getPath().replace("%20"," ");
        Document document= Jsoup.parse(new File(path),"utf-8");
        // 3. 将 Document 对象转为 JXDocument 对象
        JXDocument jxDocument=new JXDocument(document);
        // 4. cn.wanghaomiao.xpath.model.JXDocument 调用 selN(String xpath),获取 List<JXNode>对象。
        //获取所有的name标签,XPath的具体规则去W3C上去看
        //List<JXNode> jxNodes=jxDocument.selN("//name");
        //找到属性number为baizhan_0002的student的标签元素
        //List<JXNode> jxNodes=jxDocument.selN("//student[@number='baizhan_0002']");
        //想拿到baizhan_0001的年龄,找到属性number为baizhan_0001的student的标签元素下的age标签
        List<JXNode> jxNodes=jxDocument.selN("//student[@number='baizhan_0001']/age");
        // 5. 遍历 List<JXNode>,调用 JXNode 的 getElement(),转为 Element 对象。
        for (JXNode jxNode:jxNodes){
            Element element=jxNode.getElement();
            // 6. 处理 Element 对象。
            System.out.println(element.text());
        }
    }
}
标签: JavaEE XML XPath

本文转载自: https://blog.csdn.net/weixin_44593822/article/details/122766100
版权归原作者 深海鱼肝油ya 所有, 如有侵权,请联系我们删除。

“一文搞懂XML技术”的评论:

还没有评论