本节思维导图
XML学习
XML的简介
XML:可扩展标记语言(Extensible Markup Language)
它被设计用来传输和存储数据。
HTML被设计用来显示数据。
html里面的标签都是预定义好的,xml里的标签没有被预定义,需要自己定义标签。
是w3c组织发布的。
xml不是html的代替,而是html的扩充。
xml的应用
主要用于数据的读写操作。
文件配置。(比如我们程序连接数据库,如果数据库的名称和账号密码被放在代码中,那么连接其他数据库时,就需要更改代码,而我们直接使用配置文件更利于维护)
xml的文档声明
xml文件的后缀名为.xml
xml文件第一行必须有文档声明(写了文档声明之后,表示可以写xml的内容)
文档声明的格式:<?xml version="1.0" encoding="gbk"?>
version:xml的版本
encoding:编码
xml的元素定义
xml文档也是树形结构。
xml必须有且只有一个根标签
xml标签必须是成对的。
xml标签区分大小写。
xml标签不能以数字和下划线开头
xml标签不能以字符xml(XML,Xml)开头
xml标签不能包含空格
xml元素的属性值必须加引号
xml的注释格式:<!-- xml注释-->
例子:
<?xml version="1.0" encoding="gbk"?>
<!--个人信息-->
<person>
<name>张三</name>
<age>20岁</age>
</person>
xml的特殊字符:
< 代替<
> 代替>
&代替&
'代替'(单引号)
"代替"(双引号)
xml文件的CDATA区:
所有xml文档都会被解析器解析。
只有CDATA区中的文本会被解析器忽略。
比如我们标签中有<a>a>b && c<b</a>
这时候其中的>,&,<都会被解析。
如果放入CDATA区中,解析器就会忽略CDATA区中的所有内容。
格式:<![CDATA[ 内容 ]]>
xml约束
当我们的xml文件只用来表示一类数据时,不符合条件的数据将要筛选掉,所以需要约束。
xml约束的技术:DTD和SCHEMA
DTD学习
DTD简介
DTD:文档类型定义(Document Type Definition)是一套为了进行程序间的数据交换而建立的关于标记符的语法规则。
文档可根据某种DTD语法规则验证格式是否符合此规则
DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。
在eclipse中进行xml验证,如果不符合dtd的规则,就会报错。
为什么使用dtd?
通过 DTD,您的每一个 XML 文件均可携带一个有关其自身格式的描述。
通过 DTD,独立的团体可一致地使用某个标准的 DTD 来交换数据。
而您的应用程序也可使用某个标准的 DTD 来验证从外部接收到的数据。
您还可以使用 DTD 来验证您自身的数据。
DTD的内部引用
格式 <!DOCTYPE 根节点 [
<!ELEMENT 根节点 (子节点1,子节点2....)>
<!ELEMENT 子节点 类型>
<!ELEMENT 子节点 类型>
.....
]>
例子:
这时再添加其他元素时就会报错。因为不符合dtd规则。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE person [
<!ELEMENT person (name,age)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
]>
<person>
<name>zhangsan</name>
<age>18</age>
</person>
DTD的外部引用
格式:<!DOCTYPE 根节点 SYSTEM "dtd文件路径">
例子:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE person SYSTEM "dtd.dtd">
<person>
<name>zhangsan</name>
<age>18</age>
</person>
dtd.dtd文件
<!ELEMENT person (name,age)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
dtd元素
声明元素
当元素是根节点时 <!ELEMENT 根节点元素 (子节点元素1,子节点元素2...)>
当元素是子节点时 <!ELEMENT 子节点元素名称 约束类型>
约束类型
EMPTY:标签里只能是空数据
(#PCDATA):标签里是字符数据
ANY:标签里是任意数据
元素出现的次数
声明只出现一次的元素
<!ELEMENT 根节点元素 (子节点元素)>
声明最少出现一次的元素
<!ELEMENT 根节点元素 (子节点元素+)>
声明出现零次或者多次的元素
<!ELEMENT 根节点元素 (子节点元素*)>
声明出现零次或者一次的元素
<!ELEMENT 根节点元素 (子节点元素?)>
dtd属性
声明属性
格式:<!ATTLIST 元素名称 属性名称 属性类型 约束类型>
属性类型
CDATA :值为字符数据
(值1|值2|值3..) :值为枚举列表中的一个值
ID:值为唯一的ID
ENTITY:值为一个实体
约束类型:
#REQUIRED :属性值是必须的
#IMPLIED :属性值可有可无
#FIXED 值 :属性值是固定的
例子:
<!ELEMENT age (#PCDATA)>
<!ATTLIST age ID2 (12|13|14|15) #REQUIRED>
<!ELEMENT sex (#PCDATA)>
<!ATTLIST sex ID1 CDATA #REQUIRED>
dtd实体
实体是用于定义引用普通文本或特殊字符的快捷方式的变量。
格式:<!ENTITY 实体名称 "实体的值">
引用实体需要 &实体名称;
例子:
<!ENTITY name "cad">
<name>&name;</name>
xml解析
xml解析方式
(1)DOM解析
根据xml的层级结构在内存中分配一个树形结构,把xml的标签,属性,文本都封装成对象。
优点:方便程序对xml进行增删改等操作
缺点:要加载整个xml文档,占用资源太大
(2)SAX解析
通过事件驱动,每发现一个节点就引发一个事件,通过回调方法完成解析工作
优点:边读边解析,不必解析整个文档,占用资源少
缺点:需要应用程序自己负责处理TAG的处理逻辑,使用麻烦
常用解析器:
jaxp:封装了sax\dom两种接口。并在sax\dom的基础之上,作了一套简单的 java api以供开发人员使用。
dom4j:独立组织开发的
jaxp解析xml
jaxp在 javax.xml.parsers包下,有四个类。
DocumentBuilder和DocumentBuilderFactory两个类对应dom解析方式。
dom方式解析:
*DocumentBuilder:解析器类
该类为抽象类,不能通过new新建实例。可以通过ocumentBuilderFactory.newDocumentBuilder()获取实例
parse(File f)方法:将指定的文档解析为xml文档,返回Document对象
Document接口,父接口是Node,Document中找不到的方法可以在Node接口中去寻找
常用方法:
createElement(String tagName) :创建元素
getElementsById(String id):返回指定id的元素
appendChild(Node newChild):将节点添加到节点的末尾
getElementsByTagName(String tagname) :返回指定标签的NodeList集合
NodeList接口
两个方法:
getLength():获取列表的节点数
item(int index):返回集合中的第index项
*DocumentBuilderFactory:解析器工厂
该类为抽象类,可以通过newInstance()方法获取实例,主要是用来创建解析器
例子:使用jaxp查询节点
public class JaxpTest {
public static void main(String[] args) throws Exception {
//实例化一个工厂类
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
//通过工厂类的方法实例一个解析器
DocumentBuilder builder=factory.newDocumentBuilder();
//通过parse方法解析指定的文档
Document document=builder.parse("WebContent/dtd.xml");
//获取指定的标签的集合
NodeList list=document.getElementsByTagName("name");
//遍历集合
for(int i=0;i<list.getLength();i++)
{
Node node=list.item(i);
//通过getTextContent方法获取标签里面的内容
System.out.println(node.getTextContent());
}
}
}
例子:使用jaxp添加节点
public static void main(String[] args) throws Exception {
//获取解析器工厂实例
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
//通过解析器工厂的方法获得解析器实例
DocumentBuilder builder=factory.newDocumentBuilder();
//解析指定的xml文件
Document document=builder.parse("WebContent/dtd.xml");
//获得标签名为person的集合
NodeList list=document.getElementsByTagName("person");
//获取第一个person
Node person1=list.item(0);
//创建sex标签
Element sex=document.createElement("sex");
//创建文本
Text text=document.createTextNode("男");
//将文本添加到标签下面
sex.appendChild(text);
//将sex标签添加在第一个person标签末尾
person1.appendChild(sex);
//添加成功后,只是在内存中的dom树中添加成功,要想在文档中显示,需要回写
TransformerFactory transformerFactory=TransformerFactory.newInstance();
Transformer transformer=transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult("WebContent/dtd.xml"));
}
例子:使用jaxp修改节点
public static void main(String[] args) throws Exception {
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
Document document=builder.parse("WebContent/dtd.xml");
NodeList list=document.getElementsByTagName("sex");
Node sex=list.item(0);
sex.setTextContent("女");
TransformerFactory transformerFactory=TransformerFactory.newInstance();
Transformer transformer=transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult("WebContent/dtd.xml"));
}
例子:使用jaxp删除节点
public static void main(String[] args) throws Exception {
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
Document document=builder.parse("WebContent/dtd.xml");
//获取sex节点
NodeList list=document.getElementsByTagName("sex");
Node sex=list.item(0);
//获取sex的父节点
Node person1=sex.getParentNode();
//通过父节点进行删除
person1.removeChild(sex);
//回写xml
TransformerFactory transformerFactory=TransformerFactory.newInstance();
Transformer transformer=transformerFactory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult("WebContent/dtd.xml"));
}
例子:使用jaxp遍历节点
//主函数
public static void main(String[] args) throws Exception {
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
Document document=builder.parse("WebContent/dtd.xml");
list1(document);
}
//遍历节点
private static void list1(Node node) Exception {
System.out.println(node.getNodeName());//打印节点的名称
NodeList list2=node.getChildNodes();//获取子节点
for(int i=0;i<list2.getLength();i++)
{
Node node1=list2.item(i);
list1(node1);//通过递归来获得自身的子节点
}
}