XML技术学习

简介

XML 指可扩展标记语言(Extensible Markup Language),被设计用来传输和存储数据。目前主要的作用是:

  1. 描述带关系的数据(作为软件的配置文件):包含于被包含的关系
  2. 作为数据的载体(存储数据,小型的“数据库”)

树结构

XML 文档必须包含根元素,根元素是所有其他元素的父元素。

XML 文档中的元素形成了一棵文档树,这棵树从根部开始,并扩展到树的最底端。

所有元素均可拥有子元素:

<root>
  <child>
    <subchild>.....</subchild>
  </child>
</root>

父、子以及同胞等术语用于描述元素之间的关系。父元素拥有子元素。

相同层级上的子元素互为同胞(兄弟或姐妹)。

所有元素均可拥有文本内容和属性(类似 HTML 中)

XML语法

xml文件以xml后缀名结尾

xml文件需要使用xml解析器去解析。浏览器内置了xml解析器。

标签:

<student>内容</student><!--开始标签 标签体内容 结束标签--><!--开始标签 标签体内容 结束标签-->
  1. </student>或<student></student>空标签。没有标签体内容
  2. xml标签名区分大小写
  3. xml标签一定要正确配对
  4. xml标签名中间不能使用空格
  5. xml标签名不能以数字开头
  6. 在一个xml文档中,有且仅有一个根标签

属性:

语法: <student name="eric">student</student>

注意:

  1. 属性值必须以引号包含,不能省略,也不能单双引号混用!!!
  2. 一个标签内可以有多个属性,但不能出现重复的属性名!!!

注释:

语法:<!-- xml注释 -->

文档声明:

语法:<?xml version="1.0" encoding="utf-8"?>

    version:xml的版本号

    encoding:解析xml时查询的码表(解码过程中查询的码表)

注意:

  1. 如果在eclipse工具中开发xml文件,保存xml文件时自动按文档声明的encoding来保存文件。
  2. 如果使用记事本工具修改xml文件,注意保存xml文件按照文档声明的encoding的码表来保存。

转义字符:

在xml中内置了一些特殊字符,这些特殊字符不能直接被浏览器原样输出。如果希望把这些特殊字符按照原样输出到浏览器,需要对这些特殊字符进行转义,转义之后的字符就叫转义字符。

特殊字符转义字符含义
<&gt;小于
>&lt;大于
&&amp;
'&apos;单引号
"&quot;引号

XML命名规则

XML 元素必须遵循以下命名规则:

  1. 名称可以含字母、数字以及其他的字符
  2. 名称不能以数字或者标点符号开始
  3. 名称不能以字符 “xml”(或者 XML、Xml)开始
  4. 名称不能包含空格

最佳命名习惯:

使名称具有描述性。一个单词不足以描述时,使用下划线连接单词命名。同时名称应当比较简短,比如:<book_title>,而不是:<the_title_of_the_book>
避免 "-" 字符。如果按照这样的方式进行命名:"first-name",一些软件会认为你需要提取第一个单词。
避免 "." 字符。如果按照这样的方式进行命名:"first.name",一些软件会认为 "name" 是对象 "first" 的属性。
避免 ":" 字符。冒号会被转换为命名空间来使用。
实用的经验:使用数据库的名称规则来命名 XML 文档中的元素。(XML 文档经常有一个对应的数据库,其中的字段会对应 XML 文档中的元素。)

CDATA块

CDATA 部分由 "<![CDATA[" 开始,由 "]]>" 结束:

作用: 可以让一些需要进行包含特殊字符的内容统一进行原样输出

处理指令

在HTML中,会告诉xml解析如何解析xml文档
案例: <?xml-stylesheet type="text/css" href="1.css"?> 告诉xml解析该xml文档引用了哪个css文件,可以使用xml-stylesheet指令指示

把多个连续的空格合并为一个,但是XML会保留所有的空格在 XML 中,空格会被保留

XML解析

引入

xml文件除了给开发者看,更多的情况使用程序读取xml文件的内容。这叫做xml解析

XML解析方式(原理不同)

DOM解析

原理:xml解析器一次性把整个xml文档加载进内存,然后在内存中构建一颗Document的对象树,通过Document对象,得到树上的节点对象,通过节点对象访问(操作)到xml文档的内容。

SAX解析

原理:加载一点,解析一点,处理一点,对内存要求不高!!!(基于事件)

XML解析工具

DOM解析原理:

  1. JAXP (oracle-Sun公司官方)
  2. JDOM工具(非官方)
  3. Dom4J工具(非官方)(三大框架默认读取xml的工具就是Dom4j)

.......

SAX解析原理:

    Sax解析工具(oracle-sun公司官方)

Dom4j工具

非官方,不在jdk中,需要导入jar包

使用步骤:

  1. 导入dom4j的核心包。 dom4j-1.6.1.jar

  2. 编写Dom4j读取xml文件代码

    public static void main(String[] args) {
    	try {
    		//1.创建一个xml解析器对象
    		SAXReader reader = new SAXReader();
    		//2.读取xml文档,返回Document对象
    		Document doc = reader.read(new File("./src/contact.xml"));
    	} catch (DocumentException e) {
    		e.printStackTrace();
    		throw new RuntimeException(e);
    	}
    }

Dom4j读取xml文件

    节点:

Iterator    Element.nodeIterator();    //获取当前标签节点下的所有子标签
 标签:
Element Document.getRootElement();  //获取xml文档的根标签 
                 
Element  ELement.element("标签名") //指定名称的第一个子标签

Iterator<Element>Element.elementIterator("标签名");// 指定名称的所有子标签

List<Element> Element.elements(); //获取所有子标签

    属性:

String   Element.attributeValue("属性名") //获取指定名称的属性值

Attribute   Element.attribute("属性名");//获取指定名称的属性对象      

Attribute.getName()  //获取属性名称

Attibute.getValue()  //获取属性值

List<Attribute>         Element.attributes();  //获取所有属性对象

Iterator<Attribute>          Element.attibuteIterator(); //获取所有属性对象

    文本: 

Element.getText();  //获取当前标签的文本

Element.elementText("标签名") //获取当前标签的指定名称的子标签的文本内容

Dom4j修改xml文件

    写出内容到xml文档

XMLWriter writer = new XMLWriter(OutputStream, OutputForamt)
wirter.write(Document);

    修改xml文档的API

        增加:

DocumentHelper.createDocument()  增加文档
addElement("名称")  增加标签
addAttribute("名称",“值”)  增加属性

        修改:

Attribute.setValue("值")  修改属性值
Element.addAtribute("同名的属性名","值")  修改同名的属性值
Element.setText("内容")  修改文本内容

        删除:

Element.detach();  删除标签  
Attribute.detach();  删除属性

xPath技术

引入:

当使用dom4j查询比较深层次结构的节点(标签、属性、文本)比较麻烦!xPath主要是用于快速获取所需的节点对象。

在dom4j中如何使用xPath技术

  1. 导入xPath支持jar包 。  jaxen-1.1-beta-6.jar

  2. 使用xpath方法

List<Node>  selectNodes("xpath表达式");   //查询多个节点对象

Node       selectSingleNode("xpath表达式");  //查询一个节点对象
 xPath语法
表达式名称描述
/绝对路径表示从xml的跟位置开始或子元素(一个层次结构)
//相对路径表示不分任何层次结构的选择元素
*通配符表示匹配所有元素
[]条件表示选择什么条件下的元素
@属性表示选择属性节点
and关系表示条件与关系(等价于&&)
text()文本表示选择文本内容

SAX解析

dom解析是面向对象的,一次性把xml文档加载进内存,构建出document树,容易理解,但是不适合读取大容量的xml文件,容易导致内存溢出。而sax解析是基于事件的,加载一点,读取一点,处理一点,对内存的要求较低。

SAX解析工具 -  Sun公司提供的。内置在jdk中。org.xml.sax.*

核心的API:

    SAXParser类: 用于读取和解析xml文件对象

    parse(File f, DefaultHandler dh)方法:解析xml文件

        参数一: File:表示 读取的xml文件。

        参数二: DefaultHandler: SAX事件处理程序。使用DefaultHandler的子类

例如:

{
    //1.创建SAXParser对象 

    SAXParser parser=SAXParserFactory.newInstance().newSAXParser();

    //2.调用parse方法

    parser.parse(new File("./src/contact.xml"), new MyDefaultHandler());

}     
MyDefaultHandler:继承DefaultHandler类,在调用parse方法时创建并传入              DefaultHandler类的API:
  void startDocument()  :  在读到文档开始时调用 
  void endDocument()  :在读到文档结束时调用 
  void startElement(String uri,String localName,String qName,Attributes attributes) : 读到开始标签时调用    
  void endElement(String uri, String localName, String qName)   :读到结束标签时调用
  void characters(char[] ch, int start, int length) :读到文本内容时调用

案例:使用Sax解析contact.xml得到contact列表

Contact.java

package xml.sax;

public class Contact {
	private String id;
	private String name;
	private String age;
	private String tel;
	private String email;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getAge() {
		return age;
	}
	public void setAge(String age) {
		this.age = age;
	}
	public String getTel() {
		return tel;
	}
	public void setTel(String tel) {
		this.tel = tel;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	@Override
	public String toString() {
		return "Contact [id=" + id + ", name=" + name + ", age=" + age + ", tel=" + tel + ", email=" + email + "]";
	}
	
}

contact.xml

<?xml version="1.0" encoding="UTF-8"?>
<contacts>
	<contact id="001">
		<name>张三</name>
		<age>21</age>
		<tel>12345678901</tel>
		<email>12345678@qq.com</email>
	</contact>
	<contact id="002">
		<name>李四</name>
		<age>28</age>
		<tel>12345678902</tel>
		<email>12345672@qq.com</email>
	</contact>
</contacts>

MyDefaultHandler.java

package xml.sax;

import java.util.ArrayList;
import java.util.List;

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

public class MyDefaultHandler extends DefaultHandler {
	//存储contact对象
	private List<Contact> list = new ArrayList<Contact>();
	
	public List<Contact> getList(){
		return list;
	}
	
	//存储一个contact对象
	private Contact contact;
	
	//存储当前读到的标签名称
	String curTag;
	@Override
	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
		curTag = qName;
		if("contact".equals(qName)) {
			contact = new Contact();
			contact.setId(attributes.getValue("id"));
		}
	}
	
	@Override
	public void characters(char[] ch, int start, int length) throws SAXException {
		String content = new String(ch, start, length);
		if("name".equals(curTag)) {
			contact.setName(content);
		}
		if("age".equals(curTag)) {
			contact.setAge(content);
		}
		if("email".equals(curTag)) {
			contact.setEmail(content);
		}
		if("tel".equals(curTag)) {
			contact.setTel(content);
		}
	}
	
	@Override
	public void endElement(String uri, String localName, String qName) throws SAXException {
		//设置为空时为了避免将空格换行设置到对象的属性中
		curTag = null;
		if("contact".equals(qName)) {
			list.add(contact);
		}
	}
}

Main.java

package xml.sax;

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

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;

public class Main {
	public static void main(String[] args) {
		SAXParser parser;
		try {
			parser = SAXParserFactory.newInstance().newSAXParser();
			MyDefaultHandler handler = new MyDefaultHandler();
			parser.parse(new File("./src/contact.xml"), handler);
			List<Contact> list = handler.getList();
			for(Contact contact : list) {
				System.out.println(contact);
			}
			/**
			 * 输出:
			 * Contact [id=001, name=张三, age=21, tel=12345678901, email=12345678@qq.com]
			 * Contact [id=002, name=李四, age=28, tel=12345678902, email=12345672@qq.com]
			 */
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
}

XML约束

引入

XML语法:规范的xml文件的基本编写规则(w3c组织制定的)

XML约束:规范xml文件数据内容格式的编写规则。(由开发者自行定义)

DTD约束

导入dtd方式

    1.内部导入

<!DOCTYPE note [

  <!ELEMENT note(to,from,heading,body)>

  <!ELEMENTto      (#PCDATA)>

  <!ELEMENTfrom    (#PCDATA)>

  <!ELEMENTheading (#PCDATA)>

  <!ELEMENTbody    (#PCDATA)>

]>

    2.外部导入

    本地文件系统:

<!DOCTYPE note SYSTEM "note.dtd">

    公共的外部导入

<!DOCTYPE 根元素 PUBLIC "http://gz.itcast.cn/itcast.dtd">

DTD语法

约束标签

<!ELEMENT 元素名称 类别>  或 <!ELEMENT 元素名称 (元素内容)>

类别:

  1. 空标签:Empty.表示元素一定是空元素
  2. 普通字符串:(#PCDATA)。表示元素的内容一定是普通字符串(不能含有子标签)
  3. 任何内容:ANY。表示元素的内容可以使任意内容(包括子标签)

(元素内容):

顺序问题:

<!ELEMENT 元素名称 (子元素名称 1,子元素名称 2,.....)>

    按顺序出现子标签

次数问题:

  1. 标签:必须且只出现1次
  2. 标签+:至少出现1次
  3. 标签*:0或n次
  4. 标签?:0或1次

约束属性

<!ATTLIST 元素名称 属性名称 属性类型 默认值>

默认值:

    #REQUIRED 属性值是必需的

    #IMPLIED 属性不是必需的

    #FIXED value 属性不是必需的,但属性值是固定的

属性类型:控制属性值的

  1.   CDATA :表示普通字符串
  2. (en1|en2|..): 表示一定是人选其中的一个值
  3. ID:表示在一个xml文档中该属性值必须唯一。值不能以数字开头

Schema约束

名称空间:告诉xml文档的哪个元素被哪个schema文档约束。在一个xml文档中,不同的标签可以被不同的schema的约束。

未完待续... 

  1. 一个名称空间受到schema文档约束的情况
  2. 多个名称空间受到多个schema文档约束的情况
  3. 默认名称空间的情况
  4. 没有名称空间的情况

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值