简介
XML 指可扩展标记语言(Extensible Markup Language),被设计用来传输和存储数据。目前主要的作用是:
- 描述带关系的数据(作为软件的配置文件):包含于被包含的关系
- 作为数据的载体(存储数据,小型的“数据库”)
树结构
XML 文档必须包含根元素,根元素是所有其他元素的父元素。
XML 文档中的元素形成了一棵文档树,这棵树从根部开始,并扩展到树的最底端。
所有元素均可拥有子元素:
<root>
<child>
<subchild>.....</subchild>
</child>
</root>
父、子以及同胞等术语用于描述元素之间的关系。父元素拥有子元素。
相同层级上的子元素互为同胞(兄弟或姐妹)。
所有元素均可拥有文本内容和属性(类似 HTML 中)
XML语法
xml文件以xml后缀名结尾
xml文件需要使用xml解析器去解析。浏览器内置了xml解析器。
标签:
<student>内容</student><!--开始标签 标签体内容 结束标签--> <!--开始标签 标签体内容 结束标签--> |
- </student>或<student></student>空标签。没有标签体内容
- xml标签名区分大小写
- xml标签一定要正确配对
- xml标签名中间不能使用空格
- xml标签名不能以数字开头
- 在一个xml文档中,有且仅有一个根标签
属性:
语法: <student name="eric">student</student>
注意:
- 属性值必须以引号包含,不能省略,也不能单双引号混用!!!
- 一个标签内可以有多个属性,但不能出现重复的属性名!!!
注释:
语法:<!-- xml注释 -->
文档声明:
语法:<?xml version="1.0" encoding="utf-8"?>
version:xml的版本号
encoding:解析xml时查询的码表(解码过程中查询的码表)
注意:
- 如果在eclipse工具中开发xml文件,保存xml文件时自动按文档声明的encoding来保存文件。
- 如果使用记事本工具修改xml文件,注意保存xml文件按照文档声明的encoding的码表来保存。
转义字符:
在xml中内置了一些特殊字符,这些特殊字符不能直接被浏览器原样输出。如果希望把这些特殊字符按照原样输出到浏览器,需要对这些特殊字符进行转义,转义之后的字符就叫转义字符。
特殊字符 | 转义字符 | 含义 |
< | > | 小于 |
> | < | 大于 |
& | & | 和 |
' | ' | 单引号 |
" | " | 引号 |
XML命名规则
XML 元素必须遵循以下命名规则:
- 名称可以含字母、数字以及其他的字符
- 名称不能以数字或者标点符号开始
- 名称不能以字符 “xml”(或者 XML、Xml)开始
- 名称不能包含空格
最佳命名习惯:
使名称具有描述性。一个单词不足以描述时,使用下划线连接单词命名。同时名称应当比较简短,比如:<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解析原理:
- JAXP (oracle-Sun公司官方)
- JDOM工具(非官方)
- Dom4J工具(非官方)(三大框架默认读取xml的工具就是Dom4j)
.......
SAX解析原理:
Sax解析工具(oracle-sun公司官方)
Dom4j工具
非官方,不在jdk中,需要导入jar包
使用步骤:
-
导入dom4j的核心包。 dom4j-1.6.1.jar
-
编写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技术
-
导入xPath支持jar包 。 jaxen-1.1-beta-6.jar
-
使用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 元素名称 (元素内容)> |
类别:
- 空标签:Empty.表示元素一定是空元素
- 普通字符串:(#PCDATA)。表示元素的内容一定是普通字符串(不能含有子标签)
- 任何内容:ANY。表示元素的内容可以使任意内容(包括子标签)
(元素内容):
顺序问题:
<!ELEMENT 元素名称 (子元素名称 1,子元素名称 2,.....)> |
按顺序出现子标签
次数问题:
- 标签:必须且只出现1次
- 标签+:至少出现1次
- 标签*:0或n次
- 标签?:0或1次
约束属性
<!ATTLIST 元素名称 属性名称 属性类型 默认值> |
默认值:
#REQUIRED 属性值是必需的
#IMPLIED 属性不是必需的
#FIXED value 属性不是必需的,但属性值是固定的
属性类型:控制属性值的
- CDATA :表示普通字符串
- (en1|en2|..): 表示一定是人选其中的一个值
- ID:表示在一个xml文档中该属性值必须唯一。值不能以数字开头
Schema约束
名称空间:告诉xml文档的哪个元素被哪个schema文档约束。在一个xml文档中,不同的标签可以被不同的schema的约束。
未完待续...
- 一个名称空间受到schema文档约束的情况
- 多个名称空间受到多个schema文档约束的情况
- 默认名称空间的情况
- 没有名称空间的情况