XML
什么是XML
可扩展标记语言,标准通用标记语言的子集,简称XML。是一种用于标记电子文件使其具有结构性的标记语言。
在电子计算机中,标记指计算机所能理解的信息符号,通过此种标记,计算机之间可以处理包含各种的信息比如文章等。它可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。
它非常适合万维网传输,提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。是Internet环境中跨平台的、依赖于内容的技术,也是当今处理分布式结构信息的有效工具。
早在1998年,W3C就发布了XML1.0规范,使用它来简化Internet的文档信息传输。
总结一下:
- XML 指可扩展标记语言(EXtensible Markup Language)
- XML 是一种标记语言,很类似 HTML
- XML 的设计宗旨是传输数据,而非显示数据
- XML 标签没有被预定义。您需要自行定义标签。
- XML 被设计为具有自我描述性。
XML 与 HTML 的主要差异
XML 不是 HTML 的替代。
XML 和 HTML 为不同的目的而设计:
- XML 被设计为传输和存储数据,其焦点是数据的内容。
- HTML 被设计用来显示数据,其焦点是数据的外观。
- HTML 旨在显示信息,而 XML 旨在传输信息。
XML 是对 HTML 的补充。
XML 不会替代 HTML,理解这一点很重要。在大多数 web 应用程序中,XML 用于传输数据,而 HTML 用于格式化并显示数据。
对 XML 最好的描述是:
XML 是独立于软件和硬件的信息传输工具。
XML的作用?
xml 的主要作用有:
1、用来保存数据,而且这些数据具有自我描述性
2、它还可以做为项目或者模块的配置文件
3、还可以做为网络传输数据的格式(现在 JSON 为主)。
XML的树结构
XML 使用简单的具有自我描述性的语法:
<?xml version="1.0" encoding="ISO-8859-1"?>
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
第一行是 XML 声明。它定义 XML 的版本 (1.0) 和所使用的编码 (ISO-8859-1 = Latin-1/西欧字符集)。
下一行描述文档的根元素(像在说:“本文档是一个便签”):
<note>
接下来 4 行描述根的 4 个子元素(to, from, heading 以及 body):
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
最后一行定义根元素的结尾:
</note>
从本例可以设想,该 XML 文档包含了 John 给 George 的一张便签。
注意:XML 文档必须包含根元素。该元素是所有其他元素的父元素。
XML 文档中的元素形成了一棵文档树。这棵树从根部开始,并扩展到树的最底端。
所有元素均可拥有子元素:
<root>
<child>
<subchild>.....</subchild>
</child>
</root>
父、子以及同胞等术语用于描述元素之间的关系。父元素拥有子元素。相同层级上的子元素成为同胞(兄弟或姐妹)。
所有元素均可拥有文本内容和属性(类似 HTML 中)。
上图表示下面的 XML 中的一本书:
<bookstore>
<book category="COOKING">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="CHILDREN">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="WEB">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>
例子中的根元素是 。文档中的所有 元素都被包含在 中。
元素有 4 个子元素:
XML的语法
所有 XML 元素都须有关闭标签
在 HTML,经常会看到没有关闭标签的元素:
<p>This is a paragraph
<p>This is another paragraph
在 XML 中,省略关闭标签是非法的。所有元素都必须有关闭标签:
<p>This is a paragraph</p>
<p>This is another paragraph</p>
XML 标签对大小写敏感
XML 元素使用 XML 标签进行定义。
XML 标签对大小写敏感。在 XML 中,标签 与标签 是不同的。
必须使用相同的大小写来编写打开标签和关闭标签:
<Message>这是错误的。</message>
<message>这是正确的。</message>
**注释:**打开标签和关闭标签通常被称为开始标签和结束标签。
XML 必须正确地嵌套
在 HTML 中,常会看到没有正确嵌套的元素:
<b><i>This text is bold and italic</b></i>
在 XML 中,所有元素都必须彼此正确地嵌套:
<b><i>This text is bold and italic</i></b>
在上例中,正确嵌套的意思是:由于 元素是在 元素内打开的,那么它必须在 元素内关闭。XML 文档必须有根元素
XML 文档必须有一个元素是所有其他元素的父元素。该元素称为根元素。
<root>
<child>
<subchild>.....</subchild>
</child>
</root>
XML 的属性值须加引号
与 HTML 类似,XML 也可拥有属性(名称/值的对)。
在 XML 中,XML 的属性值须加引号。请研究下面的两个 XML 文档。第一个是错误的,第二个是正确的:
<note date=08/08/2008>
<to>George</to>
<from>John</from>
</note>
<note date="08/08/2008">
<to>George</to>
<from>John</from>
</note>
在第一个文档中的错误是,note 元素中的 date 属性没有加引号。
实体引用
在 XML 中,一些字符拥有特殊的意义。
如果你把字符 “<” 放在 XML 元素中,会发生错误,这是因为解析器会把它当作新元素的开始。
这样会产生 XML 错误:
<message>if salary < 1000 then</message>
为了避免这个错误,请用实体引用来代替 “<” 字符:
<message>if salary < 1000 then</message>
在 XML 中,有 5 个预定义的实体引用:
< | < | 小于 |
---|---|---|
> | > | 大于 |
& | & | 和号 |
&apos | ’ | 单引号 |
" | " | 引号 |
**注释:**在 XML 中,只有字符 “<” 和 “&” 确实是非法的。大于号是合法的,但是用实体引用来代替它是一个好习惯。
XML 中的注释
在 XML 中编写注释的语法与 HTML 的语法很相似:
<!-- This is a comment -->
在 XML 中,空格会被保留
HTML 会把多个连续的空格字符裁减(合并)为一个:
HTML: Hello my name is David.
输出: Hello my name is David.
在 XML 中,文档中的空格不会被删节。
XML 以 LF 存储换行
在 Windows 应用程序中,换行通常以一对字符来存储:回车符 (CR) 和换行符 (LF)。这对字符与打字机设置新行的动作有相似之处。在 Unix 应用程序中,新行以 LF 字符存储。而 Macintosh 应用程序使用 CR 来存储新行。
读取XML
JUnit是一个Java语言的单元测试框架。它由Kent Beck和Erich Gamma建立,逐渐成为源于Kent Beck的sUnit的xUnit家族中最为成功的一个。 JUnit有它自己的JUnit扩展生态圈。多数Java的开发环境都已经集成了JUnit作为单元测试的工具。
JUnit是由 Erich Gamma 和 Kent Beck 编写的一个回归测试框架(regression testing framework)。Junit测试是程序员测试,即所谓白盒测试,因为程序员知道被测试的软件如何(How)完成功能和完成什么样(What)的功能。Junit是一套框架,继承TestCase类,就可以用Junit进行自动测试了。
在进行读取XML操作之前,我们需要导入以下jar包:hamcrest-core-1.3, junit-4.12
链接:https://pan.baidu.com/s/1U-porA6vFP_yOw1XaVkW8Q
提取码:ayin
将jar包导入之后,创建一个后缀名为.xml的文件,按照xml的语法规则,编辑一个xml文件!
<?xml version="1.0" encoding="UTF-8" ?>
<books>
<book sn="SN1524">
<name>放逐</name>
<author>Ayin</author>
<price>87</price>
</book>
<book sn="SN1587">
<name>时间简史</name>
<author>霍金</author>
<price>125</price>
</book>
</books>
然后创建一个Book类,Book类需要设置与xml标签所对应的变量,并且需要无参、有参构造方法、get/set方法以及toString方法!
public class Book {
private String sn;
private String name;
private BigDecimal price;
private String author;
}
紧接着创建一个测试类,类中写一个测试方法:
@Test
public void test() throws DocumentException {
// 创建一个SaxReader输入流,去读取xml配置文件,生成Document对象
SAXReader saxReader = new SAXReader();
Document read = saxReader.read("src/books.xml");
System.out.println(read);
}
需要注意的是,方法前的@Test不能缺,SAXReader是dom4j提供的一个类对象,可以通过该对象读取指定路径的xml文件!
以下代码实例为xml的解析测试:
@Test
// 读取books.xml文件生成Book类
public void test2() throws DocumentException {
// 读取xml文档
SAXReader reader = new SAXReader();
// 在Junit测试中,相对路径是从模块名开始算的
Document document = reader.read("src/books.xml");
// 通过document的getRootElement()方法获取根元素
Element rootElement = document.getRootElement();
// System.out.println(rootElement);
// 通过根元素获取book标签对象(集合)
List<Element> books = rootElement.elements("book");
// 通过遍历集合来获取book标签下的每一个子元素
for (Element book: books) {
// 通过element()方法获取制定标签名的Element对象
Element name = book.element("name");
// asXML()方法可以将标签对象转换成字符串对象
// System.out.println(name.asXML());
// nameText()方法获取标签的文本内容
String nameText = name.getText();
// elementTest()方法可以直接获取标签对象的文本内容
String price = book.elementText("price");
String author = book.elementText("author");
// attributeValue()方法可以获得标签属性
String sn = book.attributeValue("sn");
System.out.println(new Book(sn, nameText, new BigDecimal(price), author));
}
}
解析XML
早期 JDK 为我们提供了两种 xml 解析技术 DOM 和 Sax 简介(已经过时,但我们需要知道这两种技术)。
dom 解析技术是 W3C 组织制定的,而所有的编程语言都对这个解析技术使用了自己语言的特点进行实现。
Java 对 dom 技术解析标记也做了实现。 sun 公司在 JDK5 版本对 dom 解析技术进行升级:SAX( Simple API for XML ) SAX 解析,它跟 W3C 制定的解析不太一样。
它是以类似事件机制通过回调告诉用户当前正在解析的内容。 它是一行一行的读取 xml 文件进行解析的。不会创建大量的 dom 对象。
所以它在解析 xml 的时候,在内存的使用上。和性能上。都优于 Dom 解析。 第三方的解析: jdom 在 dom 基础上进行了封装 、 dom4j 又对 jdom 进行了封装。
pull 主要用在 Android 手机开发,是在跟 sax 非常类似都是事件机制解析 xml 文件。 这个 Dom4j 它是第三方的解析技术。
我们需要使用第三方给我们提供好的类库才可以解析 xml 文件。
由于 dom4j 它不是 sun 公司的技术,而属于第三方公司的技术,我们需要使用 dom4j 就需要到 dom4j 官网下载 dom4j 的 jar 包。
编程步骤:
-
先加载 xml 文件创建 Document 对象
-
通过 Document 对象拿到根元素对象
-
通过根元素.elelemts(标签名); 可以返回一个集合,这个集合里放着。所有你指定的标签名的元素对象
-
找到你想要修改、删除的子元素,进行相应在的操作
-
保存到硬盘上
以下为需要解析的 books.xml 文件内容:
<?xml version="1.0" encoding="UTF-8"?>
<books>
<book sn="SN12341232">
<name>辟邪剑谱</name>
<price>9.9</price>
<author>班主任</author>
</book>
<book sn="SN12341231">
<name>葵花宝典</name>
<price>99.99</price>
<author>班长</author>
</book>
</books>
解析获取 Document 对象的代码:
先创建 SaxReader 对象。这个对象,用于读取 xml 文件,并创建 Document。
/*
* dom4j 获取 Documet 对象
*/
@Test
public void getDocument() throws DocumentException {
// 要创建一个 Document 对象,需要我们先创建一个 SAXReader 对象
SAXReader reader = new SAXReader();
// 这个对象用于读取 xml 文件,然后返回一个 Document。
Document document = reader.read("src/books.xml");
// 打印到控制台,看看是否创建成功
System.out.println(document);
}
遍历标签、获取所有标签中的内容
需要分四步操作:
-
通过创建 SAXReader 对象。来读取 xml 文件,获取 Document 对象
-
通过 Document 对象。拿到 XML 的根元素对象
-
通过根元素对象。获取所有的 book 标签对象
-
遍历每个 book 标签对象。然后获取到 book 标签对象内的每一个元素,再通过 getText() 方法拿到起始标签和结 束标签之间的文本内容
/*
* 读取 xml 文件中的内容
*/
@Test
public void readXML() throws DocumentException {
// 通过创建 SAXReader 对象。来读取 xml 文件,获取 Document 对象
SAXReader reader = new SAXReader();
Document document = reader.read("src/books.xml");
// 通过 Document 对象。拿到 XML 的根元素对象
Element root = document.getRootElement();
// 打印测试
// Element.asXML() 它将当前元素转换成为 String 对象
// System.out.println( root.asXML() );
// 通过根元素对象。获取所有的 book 标签对象
// Element.elements(标签名)它可以拿到当前元素下的指定的子元素的集合
List<Element> books = root.elements("book");
// 遍历每个 book 标签对象。然后获取到 book 标签对象内的每一个元素,
for (Element book : books) {
// 测试
// System.out.println(book.asXML());
// 拿到 book 下面的 name 元素对象
Element nameElement = book.element("name");
// 拿到 book 下面的 price 元素对象
Element priceElement = book.element("price");
// 拿到 book 下面的 author 元素对象
Element authorElement = book.element("author");
// 再通过 getText() 方法拿到起始标签和结束标签之间的文本内容
System.out.println("书名" + nameElement.getText() + " , 价格:"
+ priceElement.getText() + ", 作者:" + authorElement.getText());
}
}
打印内容: