XML入门

XML入门

主要内容

博客源码:
https://download.csdn.net/download/ayangann915/11109791

  • XML概述
    • XML基本概念、应用场景和优势
  • XML文档规则
    • 元素命名、元素间嵌套、什么是空元素
  • 命名空间(同名的属性的处理)
  • Xpath语言(XML可以通过Xpath很快寻找相应属性)
  • 操作XML文档的几种方式
    • DOM和SAX方式
  • SAX操作XML文档

XML概述

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

允许开发者自由定义标签,可以将标签和内容有效分离

XML不再侧重于数据如何展示,而是更多地关注数据如何存储和传输

XML的应用场景

1.XML把数据从HTML分离出来(修改底层数据html不用改变)

2.简化数据共享

3.简化数据的传输

4.简化平台的变更

XML的优势

1.简单易用的标记语言

2.严格的格式

3.数据逻辑和显示逻辑分离

html注重于显示,xml着重于数据存储

例:编写一个xml文档,存储图书信息:

书名作者价格
Java思想ed79.00
Spring指南ann89.00
<?xml version=1.0 encoding="utf-8" standalone="yes"?>
<书籍列表>
	<计算机书籍>
		<书名>Java思想</书名>
		<作者>ed</作者>
		<价格>79.00</价格>
	</计算机书籍>	
	<计算机书籍>
		<书名>Spring指南</书名>
		<作者>ann</作者>
		<价格>89.00</价格>
	</计算机书籍>	
	<!-- 空元素 -->
	<名著 书名=“三国” 价格=“0”/>
</书籍列表>

XML文档规则

XML整体结构

1.有且只有一个根元素

2.元素必须合理结束

3.元素之间必须合理嵌套

4.元素的属性必须有值

XML声明
<?xml version="1.0" encoding="GB2312" standalone="yes”?>
字符集

1.简体中文:GBK或GB2312

2.繁体中文:BIG5

3.西欧字符:ISO8859-1

4.通用的国际编码:Unicode

5.针对Unicode的可变长度字符编码:UTF8

XML元素的基本规则

1.合法标签名

  • XML元素由开始标签和结束标签组成,结束标签比开始标签多一条斜线

  • XML文档区分大小写。因此,开始标签和结束标签名必须绝对相同,大小写也要完全一致

    XML文档对于标签名有如下要求:

    • 标签名可以字母(包括非西欧字符)、数字、下画线(__)、中画线(—)、冒号 (:)和点号(.)组成,但不能以数字、中画线和点号开头

    • 标签名不能包括<、>、,、$等符号

    • 标签名中尽量不要出现英文冒号“:”,除非是在使用名字空间

    • 标签名不能以字符“xml”( 或者 XML、Xml等任意大小写组合开始)

    • 标签名不能包含空格

2.嵌套子元素

  • XML允许无限深度嵌套子元素,只要保证元素之间合理嵌套即可
  • XML元素可以嵌套多个重名的子元素,这多个元素之间是有序的

3.空元素

  • XML允许使用空元素语法,空元素不可接受子元素,也不可接受字符串内容
  • 空元素和内容为空的元素并不相同
  • 空元素只是不能包含子元素,也不能包含字符串内容,但完全可以接受属性,而且可以接受任意多个属性
字符数据

开始标签和结束标签之间的文本可以是任何Unicode字符,并且其间的任何字符都将忠实 地传递给XML处理程序

如果文本字符串中包含一些特殊的字符,例如尖括号(<)或and符号(&),由于这些符 号在XML文档中都有特殊的含义,因此直接在XML元素中使用该字符串将引起文档混乱

处理:

1.使用实体引用

为了正确处理XML文档中的特殊字符,XML允许使用实体来表示这些特殊字符。

XML预置了5个实体引用,如表:

实体引用所工表符号说明
&lt;<小于符号
&gt;>大于符号
&amp;&and符号
&apos;英文单引号
&quot;英文双引号
<比较符>1+1&lt;3</比较符>

2.使用CDATA标记

在特殊标记CDATA下,所有的特殊字符,甚至是有效的元素都将被当成简单字符处理

实体引用也会失去作用,变成纯文本

语法:

<![CDATA[文本内容]]>
<比较符><![CDATA[1+1<3]]></比较符>

<比较符><![CDATA[1+1&lt;3]]></比较符><!--&lt;被当作纯文本-->
注释

XML文档还可加入解释用的字符数据,这些解释用的字符串不会被XML解 析器处理.这些解释用的文本称为注释

语法:

<!--注释字符串-->

XML注释需要注意的地方:

  1. 不要把注释放在标签之内,否则,该文档将不是一个格式良好的XML文档
  2. 不要把注释放在XML声明之前,XML声明应该永远处于XML文档的第一行
  3. 不要在注释中使用双中画线(–)
W3C对于属性的使用建议
  • 属性通常提供属于数据组成部分的信息,如果属性值里包含的信息属于该实体本身,则应该使用子元素来指定该信息,因此,W3C推荐尽量使用子元素, 而避免使用属性
换行处理

目前主流的操作系统,主要有3种换行符:

1.Windows平台:回车符(CR)和换行符(LF)的组合存储换行

2.UNIX和Linux平台:以换行符(LF)存储换行

3.Macintosh平台:以回车符(CR)存储换行

XML统一换行符(LF)存储换行

XML文档分类
  1. 格式不良好的XML文档
  • 完全没有遵守XML文档基本规则的XML文档
  1. 格式良好但无效的XML文档
  • 遵守了XML文档基本规则,但没有使用DTD或Schema定义语义约束的 XML文档
  • 使用DTD或Schema定义了语义约束,但没有遵守DTD或Schema所定义的语义约束的XML文档
  1. 有效的XML文档
  • 遵守了XML文档基本规则,并使用DTD或Schema定义了语义约束,而且 也完全遵守了DTD或Schema所定义的语义约束的XML文档

    “!DOCTYPE”

XML命名空间

为什么使用命名空间
  • 在同一份XML文档中可能出现多个同名的元素和属性——这多个同名的元 素和属性具有不同的含义和作用,但如果我们不从语法上提供区别,则XML处理 器无法区分它们
使用命名空间

语法:

xmlns[:prefix]=“命名空间字符串”

给元素指定空间,指明属于哪个

命名空间的特征:

  • 名字很长 (命名空间往往是一个绝对的URL地址)

  • 名字里往往包含英文冒号、斜线等特殊字符

如下:下面的书籍名称和作者名称都是name标签,就无法区别name

<计算机书籍>
		<name>Java思想</name>
		<作者>
			<name>ed</name>
		</作者>
		<价格>79.00</价格>
	</计算机书籍>	

所以我们要使用命名空间:

<计算机书籍 xmlns:muke="http://www.muke.com">
		<muke:name>Java思想</muke:name> <!--muke的name,限定了位置-->
		<作者 xmlns:author="http://xinhua.com">
			<author:name>ed</author:name>
		</作者>
		<价格>79.00</价格>
	</计算机书籍>	
属性使用命名空间
  • 通常情况下,由于属性是属于某个元素的,因此很自然地认为属性总是属于它所在元素所处的命名空间,一般无须专门为属性指定命名空间

XPath语言

XPath概念
  • XPath语言是一门专门用于在XML文档中查找信息的语言,其他XML程序可利用XPath在XML文档中对元素和属性进行导航

为什么要查找标签和属性呢?

  • XML文档使用来存储数据的,需要将数据提取出来使用,所以通过查找标签和属性进一步获取数据
XPath节点
节点类型说明
XML文档根节点XML文档的根称为文档节点或根节点
元素节点一个元素的开始标签、结束标签,以及开始标签和结束标签之间的全部内容整体称为元素节点
属性节点元素的每个属性都是属性节点属性节点包括属性名和属性值两个部分。 XPath认为属性节点必须依附于元素节点
XML节点XML文档里 包含的部分就是注释,注释对应的就是注释节点
命名空间节点命名空间节点代表XML文档中的xmlns:prefix属性
文本节点XML元素中间的字符数据,包括CDATA段中的字符数据
XPath基本概念
  • 基本值(或称原子值)

    • 基本值专门用于表示简单的数据值,例如整数值、字符串等。我们可以基本值当成没有父节点且没有子节点的节点
    • 项是XPath2.0提出的一个术语,一个项代表一个节点或基本值
  • 节点集和序列

    • 在某些情况下,XPath表达式可以表示多个节点,多个节点组合在一起在XPath1.0里称 为节点集
    • XPath2.0提出一个序列的概念,XPath2.0的序列可以代表一个普通的项,也可以代表节

点集

节点关系
  • 父节点

  • 子节点

  • 兄弟节点

  • 祖先节点

  • 后代节点

相对路径和绝对路径

XPath同样支持相对路径和绝对路径。对于XPath而言,绝对路径以斜线(/)开头,而相 对路径则不会以斜线(/)开的

例如:

绝对:/list/book/name:该路径总是匹配list元素内的book元素之内的name子元素

相对:list/book/name:该路径到底匹配哪个或哪些节点是不确定的

XPath基础语法

XPath使用路径表达式来定位XML文档中的节点或节点集,每个Xpath表达式总由多个 步(step)组成,多个步之间用斜线分隔

例如:

/list/book/name

XPath中步的完整语法格式如下:

轴::节点测试[限定谓语]

:XPath的步使用轴来定义所选节点与当前节点之间的结构关系

ancestor祖先节点
ancestor-or-seft祖先节点并包含自身
attribute选择节点的所有属性
child选取当前节点的所有子节点
parent选取当前节点的父节点
descendant当前节点的所有后代节点
descendant-or-self当前节点的所有后代节点并包含自身
self发前了点自身
following-sibling选择当前节点的兄弟节点

节点测试

节点测试用于从指定轴所匹配的节点集中选出特定的节点

轴名称含义实例
nodename从指南轴匹配的所有节点中选出具有nodename 的节点child::book
node()选择指定轴匹配的所有类型节点child::node()
text()选择指定轴匹配的所有文本在型节点child::text()
comment()选择指定轴匹配的所有注释节点descendant:commet()
*通配符,不进地任何过滤child:?

限定谓语

限定谓语是一个boolean表达式,或者可以转换为boolean值的表达式, 用于进一步提炼所选的节点集。限定谓语应该放在括号中

语法:

child::book[1]或child::book[position()=1]

简化写法

  • 省略child轴,例如:website/muke等同于child::website/child::muke

  • 使用@符号代替attribute轴,例如:book[@isbn=“123456”]等同于 child::book[attribute::isbn=“123456”]

  • 使用//代表后代表节点,例如://book等同于/descendant-orself::node()/child::book

  • 使用一个点代表当前节点 ,例如:./book等同于self::node()/child::book

  • 使用两个点代表上一级节点,例如:…/book等同于parent::node()/child::book

XPath运算符

算术运算符

运算符含义
+
-
*
div
mod求余

比较运算符

运算符含义
=等于
!=不等于
<小于
<=小于或等于
>大于
>=大于或等于

逻辑运算符

运算符含义
or
and

组合多个路径的运算符

XPath还提供了一个“|”运算符,可用于组合多个路径表达式,通过“|” 运算符,可以一次选取若干个路径

例如:book[position()=1] | name[position()=last()]

节点相关的常见函数
名称说明
fn:position()返回当前正在被处理的节点在父节点中的index值
fn:last()返回当前正在被处理的节点列表中项的数目
fn:name()返回当前节点的名称或指定节点集中第一个节点的名称
fn:root()通常返回文档根节点
fn:node-name(node)返回node节点名称

使用SAX读写XML文档

XML文档解析方式
  • DOM:Document Object Model:即文档对象模型,它是由W3C推荐的 处理XML文档的规范

  • SAX:Simple API for XML,它并不是W3C推荐的标准,但却是整个XML行业的事实规范

XML文档解析原理

XML文档———>XML解析器———>解析结果

JAXP概述
  • Java解析XML文档的API称为JAXP,它的全称是Java API for XML。
  • JAXP往往作为JDK的一部分发布,但它仅仅是一些API接口,并未提供真正的实现,因此实际使用过程中还需要具体的解析实现。
  • JAXP只是允许应用程序在不同的XML解析器之间切换

(应用程序使用JAXP通过不同的解析器解析XML文档)

JAXP提供的与解析相关的类
  • DocumentBuilderFactory:获取DOM解析工厂类

  • DocumentBuilder:DOM解析器标准接口

  • SAXParserFactory:获取SAX解析器的工厂类

  • SAXParser:SAX解析器的标准接口

JAXP的SAX支持
  • SAX的处理机制

    • SAX采用事件机制的方式来解析XML文档,这是一种快速读写XML数据的方式。
    • 使用SAX解析器对XML文档进行解析时,会触发一系列事件,这些事件 将被相应的事件监听器监听,从而触发相应的事件处理方法,应用程序通过 这些事件处理方法实现对XML文档的访问
  • SAX解析XML文档的流程

    XML源———>SAX解析器———>事件(事件监听器)———>输出

  • SAX解析XML文档的流程

    • 使用SAX机制解析XML文档时,SAX解析器负责在XML文档中”行走 ”, 每当遇到文档开始、元素开始、文本、元素结束和文档结束时,都将负责向外发送事件,而程序员则负责提供事件监听器来监听这些事件并通过事件获取XML文档信息
  • JAXP为SAX解析器提供2组API:

    • XMLReaderXMLReaderFactory:XMLReaderFactory工厂类的 **createXMLReader()**静态方法用于创建XMLReader

    • SAXParserSAXParserFactory:SAXParserFactory工厂类的**newSAXParser()**实 例方法用于创建SAXParser

  • XMLReader解析XML文档的方法:

    • void parse(InputSource input):解析InputSource输入源中的XML文档

    • void parse(String systemId):解析系统URI(磁盘文件是URI的一种)所代表的 XML文档

  • SAXParser解析XML文档的方法:

    • void parse(File f,DefaultHandler dh):使用指定的dh作为监听器监听SAX解析事件, 解析f文件所代表的XML文档

    • void parse(InputSource is,DefaultHandler dh):使用指定的dh作为监听器监听 SAX解析事件,解析is输入源中的XML文档

    • void parse(InputStream is,DefaultHandler dh):使用指定的dh作为监听器监听 SAX事件,解析is输入流中的XML文档

    • void parse(String uri,DefaultHandler dh):使用指定的dh作为监听器监听SAX事 件,解析URI所代表的XML文档

  • SAX解析事件

    • ContentHandler:监听XML文档内容处理事件的监听器

    • DTDHandler:监听DTD处理事件的监听器

    • EntityResolver:监听实体处理事件的监听器

    • ErrorHandler:监听解析错误的监听器

  • JAXP提供了一个DefaultHandler类,这个类实现了上述4个监听器接口, 并为监听器接口中所包含的方法提供了空实现

  • SAX解析XML文档

    <?xml version=1.0 encoding="utf-8" standalone="yes"?>
    <书籍列表>
    	<计算机书籍>
    		<书名>Java思想</书名>
    		<作者>ed</作者>
    		<价格>79.00</价格>
    	</计算机书籍>	
    	<计算机书籍>
    		<书名>Spring指南</书名>
    		<作者>ann</作者>
    		<价格>89.00</价格>
    	</计算机书籍>	
    </书籍列表>
    
    • 实现思路:

    1、在工程中引入Xerces-J具体解析器实现类jar包

    2、自定义事件监听器继承自DefaultHandler

    3、通过SAXParseFactory的newInstance()方法创建SAX解析器工厂对象

    4、通过SAXParseFactory对象的newSAXParser()方法创建SAXPasrer对象

    5、调用SAXParser对象的parse()方法解析XML文档

  • SAX生成XML文档

    • 实现思路

    1、创建保存xml的结果流对象

    2、获取sax生产工厂对象实例

    3、获取sax生产处理者对象实例

    4、获取sax生产器

    5、生产文档及文档中的元素

SAX解析XML文档案例实现:
实现思路:

1、在工程中引入Xerces-J具体解析器实现类jar包

2、自定义事件监听器继承自DefaultHandler

3、通过SAXParseFactory的newInstance()方法创建SAX解析器工厂对象

4、通过SAXParseFactory对象的newSAXParser()方法创建SAXPasrer对象

5、调用SAXParser对象的parse()方法解析XML文档

实现过程:

DefaultHandler事件监听器:

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class ParseHandler extends DefaultHandler {
    //定义一个变量保存当前正在处理的tag
    private String currentTag;

    //解析文档开始时触发方法
    @Override
    public void startDocument() throws SAXException {
        super.startDocument();
        System.out.println("解析文档开始");
    }

    //解析文档结束时触发该方法
    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
        System.out.println("解析文档end");
    }

    //解析元素开始时触发方法
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        super.startElement(uri, localName, qName, attributes);
        System.out.println("开始处理元素:"+qName);
        currentTag=qName;
        if (attributes.getLength()>0){
            System.out.println("<"+currentTag+">元素属性如下:");
            for(int i=0;i<attributes.getLength();i++){
                System.out.println(attributes.getQName(i)+"-->"+attributes.getValue(i));
            }
        }
    }

    //解析元素结束时触发方法
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        super.endElement(uri, localName, qName);
        System.out.println("处理元素结束:"+qName);
    }


    //每当处理文本数据时将触发该方法
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        super.characters(ch, start, length);
        String content=new String(ch,start,length);
        //长度大于0则有文本
        if(content.length()>0){
            System.out.println("<"+currentTag+">元素的值:"+content.trim());
        }
    }


    public static void main(String[] args) {

    }
}

SAX解析器:

import org.xml.sax.SAXException;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.IOException;

public class SAXParse {
    public static void main(String[] args) {
        //创建SAX解析器工厂
        SAXParserFactory saxParserFactory=SAXParserFactory.newInstance();
        //创建SAX解析器
        try {
            SAXParser saxParse=saxParserFactory.newSAXParser();

            //开始解析文档
            saxParse.parse("parse.xml",new ParseHandler());
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

解析结果:

解析文档开始
开始处理元素:书籍列表
<书籍列表>元素的值:
开始处理元素:计算机书籍
<计算机书籍>元素的值:
开始处理元素:书名
<书名>元素的值:Java思想
处理元素结束:书名
<书名>元素的值:
开始处理元素:作者
<作者>元素的值:ed
处理元素结束:作者
<作者>元素的值:
开始处理元素:价格
<价格>元素的值:79.00
处理元素结束:价格
<价格>元素的值:
处理元素结束:计算机书籍
<价格>元素的值:
开始处理元素:计算机书籍
<计算机书籍>元素的值:
开始处理元素:书名
<书名>元素的值:Spring指南
处理元素结束:书名
<书名>元素的值:
开始处理元素:作者
<作者>元素的值:ann
处理元素结束:作者
<作者>元素的值:
开始处理元素:价格
<价格>元素的值:89.00
处理元素结束:价格
<价格>元素的值:
处理元素结束:计算机书籍
<价格>元素的值:
<价格>元素的值:
<价格>元素的值:
处理元素结束:书籍列表
解析文档end
SAX生成XML文档案例实现:
实现思路:

1、创建保存xml的结果流对象

2、获取sax生产工厂对象实例

3、获取sax生产处理者对象实例

4、获取sax生产器

5、生产文档及文档中的元素

实现过程:
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import java.io.File;

public class buildXML {
    public static void main(String[] args) {
        //创建保存xml结果流的对象
        Result resultXML=new StreamResult(new File("result.xml"));
        //获取sax生成工厂实例
        SAXTransformerFactory saxTransformerFactory= (SAXTransformerFactory) SAXTransformerFactory.newInstance();
        //获取sax生成处理者对象实例
        try {
            TransformerHandler transformerHandler=saxTransformerFactory.newTransformerHandler();
            transformerHandler.setResult(resultXML);
            //获取sax生成器
            Transformer transformer=transformerHandler.getTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT,"yes");//允许生成额外的空格,no则是不生成
            //编码形式默认utf-8
            //生成文档开始
            transformerHandler.startDocument();
            AttributesImpl attributes=new AttributesImpl();
            //添加属性用add方法,attributes.add()
            transformerHandler.startElement("","","书籍列表",attributes);
            transformerHandler.startElement("","","计算机书籍",attributes);

            transformerHandler.startElement("","","书名",attributes);
            transformerHandler.characters("java思想".toCharArray(),0,"java思想".length());
            transformerHandler.endElement("","","书名");

            transformerHandler.startElement("","","作者",attributes);
            transformerHandler.characters("ed".toCharArray(),0,"ed".length());
            transformerHandler.endElement("","","作者");

            transformerHandler.startElement("","","价格",attributes);
            transformerHandler.characters("79.00".toCharArray(),0,"79.00".length());
            transformerHandler.endElement("","","价格");

            transformerHandler.endElement("","","计算机书籍");
            transformerHandler.startElement("","","计算机书籍",attributes);

            transformerHandler.startElement("","","书名",attributes);
            transformerHandler.characters("Spring编程".toCharArray(),0,"Spring编程".length());
            transformerHandler.endElement("","","书名");

            transformerHandler.endElement("","","计算机书籍");
            transformerHandler.endElement("","","书籍列表");

            transformerHandler.endDocument();//文档生成结束


        } catch (TransformerConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        }
    }
}

结果:生成xml文档,内容都在一行里,默认是utf-8字符编码方式

<?xml version="1.0" encoding="UTF-8"?><书籍列表><计算机书籍><书名>java思想</书名><作者>ed</作者><价格>79.00</价格></计算机书籍><计算机书籍><书名>Spring编程</书名></计算机书籍></书籍列表>

源码下载参见:
https://download.csdn.net/my/uploads

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值