1.XML概述
XML是指可扩展标记语言(eXtensible Markup Language),它是一种标记语言,很类似HTML。它被设计的宗旨是传输数据,而非显示数据。XML标签没有被预定义,需要用户自行定义标签。
XML处理生活中具有相关联系的数据,描述具有关系的数据,是一种通用的数据交换格式
用于解析执行或者显示的程序称为Parser(解析器)
常见应用:
XML技术除用于保存有关系的数据之外,它还经常用作软件配置文件,以描述程序模块之间的关系。
在一个软件系统中,通过XML配置文件可以提高系统的灵活性。即程序的行为是通过XML文件来配置的,而不是硬编码。
2.XML语法
文档声明
<?xml version=”1.0” ?>
声明文档必须写在第一行第一列
用encoding属性说明文档所使用的字符编码。保存在磁盘上的文件编码要与声明的编码一致。
<?xml version=“1.0” encoding=”GB2312”?>
用standalone属性说明文档是否独立,即是否依赖其他文档。
<?xml version=“1.0” standalone=”yes”?>
元素
也可以叫做标签,一个正确的标签包括开始标签和结束标签。
包含标签主体:<mytag>some content</mytag>
不含标签主体:<mytag/>
标签可以嵌套,但必须正确嵌套,而且一个xml文件有且仅有一个根标签,其他的标签都是这个标签的子标签或者孙标签
XML中出现的所有换行与空格字符,都会当作标签内容来处理
元素名称命名规范:
区分大小写,例如,<P>和<p>是两个不同的标记。
不能以数字或"_" (下划线)开头。
不能以xml(或XML、或Xml 等)开头。
不能包含空格。
名称中间不能包含冒号(:)。
属性
一个元素可以有多个属性,每个属性的值都要用引号引起来
<mytag name=”value” …/>
命名规范跟元素相同
属性是不允许重复的
注释
<!--这是注释-->
注释不能嵌套
CDATA区 、特殊字符
转义字符:
CDATA是Character Data的缩写
作用:把标签当做普通文本内容;
语法:<![CDATA[内容]]>
写法提示:先写一对尖括号,再写一对方括号,再写一对方括号,再依次从最外层括号里面向内部添加内容:! CATAT 内容
XML语法规则总结
所有 XML 元素都须有关闭标签
XML 标签对大小写敏感
XML 必须正确地嵌套顺序
XML 文档必须有根元素(只有一个)
XML 的属性值须加引号
特殊字符必须转义 --- CDATA
XML 中的空格、回车换行会解析时被保留
3.XML约束之DTD
XML约束:约束文档定义了在XML中允许出现的元素名称、属性及元素出现的顺序等等
格式良好的XML:遵循XML语法的XML
有效的XML:遵循约束文档的XML
编写DTD的步骤:
1.xml文档中需要出现哪些标签、个数是多少?6个
<!ELEMENT 元素名称 元素类型>
2.查询xml元素中,类型是什么.
简单or复杂
3.需要在xml中引入dtd.
Xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE persons SYSTEM "persons.dtd">
<persons>
<person>
<name>张三</name>
<age>25</age>
<money>300</money>
</person>
<person>
<name>李四</name>
<age>38</age>
<money>600</money>
</person>
</persons>
DTD文件:
<!ELEMENT persons (person+)>
<!ELEMENT person (name,age,money)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT money (#PCDATA)>
4.DTD语法
元素的定义
语法:<!ELEMENT 元素名称 元素类型>
元素的类型:
#PCDATA:可解析的字符数据
子元素:
EMPTY: 空元素
ANY:任意元素
子元素的次数
+:一次或多次
*:零次或多次
?:零次或一次
子元素的顺序
,: 子元素出现必须按照顺序.
|: 子元素出现是或的关系.
属性的定义: attribute--属性
语法:<!ATTLIST 元素名称 属性名称 属性类型 属性约束>
* <!ATTLIST 书 出版社 CDATA #REQUIRED>
属性类型:
CDATA:字符数据(字符串)
枚举:枚举类型
ID:标识是唯一
属性约束:
#REQUIRED:属性必须出现.
#IMPLIED:属性是可选的.
#FIXED:属性采用固定值.
默认值:
实体的定义
语法:<!ENTITY 实体名称 实体值>
<!ENTITY bookname "葵花宝典">
使用JAXP解析开发包的DOM解析XML
/**
* JAXP的方式解析XML
*
* @author Administrator
*
*/
public class JAXPTest {
@Test
/**
* 单元测试的方法:必须是public void 方法名 () 方法中不能有参数.
* 1.对xml进行查询。获得第一本书的作者节点<作者>春哥</作者>
*/
public void demo1() throws Exception {
/**
* 1.创建解析器工厂 2.由解析器工厂 来 创建解析器 3.通过解析器解析XML文档. --- Document
* 4.通过Document对象获得想去操作的节点.
*/
// 创建解析器工厂.
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 由工厂创建解析器
DocumentBuilder builder = factory.newDocumentBuilder();
// 解析XML。
Document document = builder.parse("src/book.xml");
// 通过Document对象获得想去操作的节点.、
NodeList nodeList = document.getElementsByTagName("作者");
Node node = nodeList.item(1);
String value = node.getTextContent();
System.out.println(value);
}
/**
* 2.在第一本书的下面 添加一个作者节点 <作者>曾哥</作者>
* * 1.创建解析器工厂
* 2.由解析器工厂 来 创建解析器
* 3.通过解析器解析XML文档. --- Document
* 4.创建一个节点<作者> 添加文本内容 曾哥. 5.找到第一本书的节点。 6.给书的节点
* 添加一个子节点.
*
*/
@Test
public void demo2() throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse("src/book.xml");
// 创建一个作者节点:
Element author = document.createElement("作者");
// 设置内容
author.setTextContent("曾哥");
// 找到第一本书
Node node = document.getElementsByTagName("书").item(0);
// 项第一本书下 添加一个节点.
node.appendChild(author);
// 回写XML --- 将内存中的树形结构 写回到 XML中 (了解)
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult(
"src/book.xml"));
}
/**
* 3.在指定的位置添加节点。在<作者>春哥</作者>之前添加一个 <作者>汪峰</作者>
*/
@Test
public void demo3() throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse("src/book.xml");
// 创建一个节点 给节点 添加一个文本内容
Element author = document.createElement("作者");
author.setTextContent("汪峰");
// 先找到 春哥的 作者的节点。
Node node = document.getElementsByTagName("作者").item(0);
// 找到其父节点
node.getParentNode().insertBefore(author, node);
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult(
"src/book.xml"));
}
/**
* 4.修改文本内容.<作者>汪峰</作者> 改成 <作者>章子怡</作者>
*/
@Test
public void demo4()throws Exception{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse("src/book.xml");
// 找到汪峰节点.
Node node = document.getElementsByTagName("作者").item(0);
node.setTextContent("章子怡");
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult(
"src/book.xml"));
}
/**
* 5.删除章子怡的作者节点.
*/
@Test
public void demo5()throws Exception{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse("src/book.xml");
// 找到汪峰节点.
Node node = document.getElementsByTagName("作者").item(0);
node.getParentNode().removeChild(node);
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult(
"src/book.xml"));
}
/**
* 扩展: 遍历所有的节点名称
*/
@Test
public void demo6()throws Exception{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse("src/book.xml");
// 调用list的方法
list(document);
}
private void list(Node node) {
// 判断Node是否是Element类型的
if(node.getNodeType() == Node.ELEMENT_NODE){
System.out.println(node.getNodeName());
}
// 获得所有的孩子节点
NodeList nodeList = node.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
Node n = nodeList.item(i);
// 递归
list(n);
}
}
/**
* 7.操作节点的属性.获得第一本书的出版社.
*/
@Test
public void demo7()throws Exception{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse("src/book.xml");
// 找到了第一本书
Node node = document.getElementsByTagName("书").item(0);
// 如果父类没有这个方法 可以 转成 子类对象.
Element element = null;
if(node.getNodeType() == Node.ELEMENT_NODE){
element = (Element) node;
}
System.out.println(element.getAttribute("出版社"));
}
}
5.SAX解析
在使用 DOM 解析 XML 文档时,需要读取整个 XML 文档,在内存中构架代表整个 DOM 树的Doucment对象,从而再对XML文档进行操作。此种情况下,如果 XML 文档特别大,就会消耗计算机的大量内存,并且容易导致内存溢出。SAX解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才会文档进行操作。
步骤:
使用SAXParserFactory创建SAX解析工厂
SAXParserFactory spf = SAXParserFactory.newInstance();
通过SAX解析工厂得到解析器对象
SAXParser sp = spf.newSAXParser();
通过解析器对象解析xml文件
xmlReader.parse("book.xml“,new XMLContentHandler());
这里的XMLContentHandler 继承 DefaultHandler
使用JAXP解析开发包的SAX解析XML
public class SAXTest {
@Test
public void demo1() throws Exception {
/**
* 1.创建解析器工厂
* 2、由工厂创建解析器
* 3.解析xml文档。 --- 绑定一个处理器
*/
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
// 解析xml --- 绑定处理器
parser.parse("src/book.xml", new MyDefaultHandler());
}
}
class MyDefaultHandler extends DefaultHandler {
private boolean flag = false;
private int idx = 1;
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if ("作者".equals(qName)) {
flag = true;
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if (flag && idx == 2) {
System.out.println(new String(ch, start, length));
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if ("作者".equals(qName)) {
flag = false;
idx++;
}
}
}
6.dom4j解析xml
DOM4j中,获得Document对象的方式有三种:1.读取XML文件,获得document对象
SAXReader reader = new SAXReader();
Document document = reader.read(new File("input.xml"));
2.解析XML形式的文本,得到document对象.
String text = "<members></members>";
Document document = DocumentHelper.parseText(text);
3.主动创建document对象.
Document document = DocumentHelper.createDocument()
//创建根节点
Element root = document.addElement("members");
将文档写入XML文件:
1.文档中全为英文,不设置编码,直接写入的形式.
XMLWriter writer = new XMLWriter(new FileWriter("output.xml")); writer.write(document);
writer.close();
2.文档中含有中文,设置编码格式写入的形式. OutputFormat format = OutputFormat.createPrettyPrint();
// 指定XML编码
format.setEncoding("GBK");
XMLWriter writer = new XMLWriter(newFileWriter("output.xml"),format);
writer.write(document);
writer.close();
Dom4j指定位置插入节点
1.得到插入位置的节点列表(list)
2.调用list.add(index,elemnent),由index决定element的插入位置。
Element元素可以通过DocumentHelper对象得到。示例代码:
Element aaa = DocumentHelper.createElement("aaa");
aaa.setText("aaa");
List list = root.element("书").elements();
list.add(1, aaa);
//更新document
....
public class Dom4JTest {
@Test
/**
* 1.查询 <作者>曾哥</作者> 节点.
*/
public void demo1() throws Exception {
// 创建解析器
SAXReader reader = new SAXReader();
// 解析XML
Document document = reader.read("src/book.xml");
// 获得跟节点
Element root = document.getRootElement();
Element author = (Element) root.element("书").elements("作者").get(0);
System.out.println(author.getText());
}
/**
* 2.修改<作者>曾哥</作者> 改为 峰哥
*/
@Test
public void demo2() throws Exception {
SAXReader reader = new SAXReader();
Document document = reader.read("src/book.xml");
Element root = document.getRootElement();
// 找到具体的节点 修改
Element author = (Element) root.element("书").elements("作者").get(1);
author.setText("峰哥");
// 回写XML
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("UTF-8");
XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),
format);
writer.write(document);
writer.close();
}
/**
* 3.添加一个节点。
*/
@Test
public void demo3() throws Exception {
SAXReader reader = new SAXReader();
Document document = reader.read("src/book.xml");
Element root = document.getRootElement();
// 添加节点
// 找到第一本书
root.element("书").addElement("作者").setText("张艺谋");
// 回写XML
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("UTF-8");
XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),
format);
writer.write(document);
writer.close();
}
/**
* 4.在指定的位置插入 创建元素: DocumentHelper.createElement("元素").setText();
* 找到第一个书.Element book = root.element("书") List list = book.elements();
* list.add();
*/
/**
* 5.删除 <作者>张艺谋</作者>
*/
@Test
public void demo5() throws Exception {
SAXReader reader = new SAXReader();
Document document = reader.read("src/book.xml");
Element root = document.getRootElement();
Element author = (Element) root.element("书").elements("作者").get(2);
author.getParent().remove(author);
// 回写XML
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("UTF-8");
XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),
format);
writer.write(document);
writer.close();
}
@Test
public void demo6()throws Exception {
SAXReader reader = new SAXReader();
Document document = reader.read("src/book.xml");
// 获得的是多个节点
// document.selectNodes(arg0)
// 获得一个节点
//document.selectSingleNode();
// 查找书下的所有的作者节点
/*List<Element> list = document.selectNodes("//作者");
for (Element element : list) {
System.out.println(element.getText());
}*/
Node node = document.selectSingleNode("//书[@id='b1']");
}
}