xml入门
xml入门
1.xml简介
eXtensible Marup Language:可扩展标记语言
标记型语言:html,使用标签来操作
可扩展:html里面的标签是固定的,每个标签都有特定的含义<h1></br>,能自己定义
xml用途:
html主要是显示数据,xml也可以显示数据(不是主要功能)
xml主要功能,为了存储数据,而不是显示数据
xml是w3c组织发布的技术
xml有两个版本1.0,1.1
使用的版本都是1.0(1.1不能向下兼容)
2.xml的应用
1.不同的系统之间传输数据
qq之间数据的传输
string str= “
<message id="1">
<sender>10000</sender>
<getter>20000</getter>
<content>hello</content>
<ip>11111</ip>
</message>
”
2.用来表示生活中有相关的数据
<中国>
<北京>
<海淀></海淀>
</北京>
</中国>
3.经常在配置文件(利于程序的扩展和维护)
例如:连接数据库,修改数据库信息,不需要修改源代码,只需要修改配置文件就ok
3.xml的语法
1.xml的文档声明(必须第一行第一列)
1.创建一个文件,后缀名为(.xml)
2.如果写xml,第一步,必须要有一个文档声明(写了文档声明之后,表示写xml文件的内容)
3.<?xml version="1.0" encoding="UTF-8"?>
属性:version
encoding:xml编码 gbk utf-8 iso8859-1不包含中文
standalone:是否需要依赖其他文件 yes/no
4.xml中文乱码解决
1.将文件保存到本地硬盘,使用gbk编码保存
2.而在我们写的时候,打开的编码为utf-8,打开和保存不一致,出现乱码
3.解决就是保存和打开保持一致
5.xml元素的定义
1.标签定义:
2.标签定义有开始必须有结束:<br></br>
3.标签没有内容,可以在标签内结束:<br/>
4.标签可以嵌套,必须要合理嵌套
一个xml中,只能有一个根标签,其他的标签都是这个标签下面的标签
5.在xml中把空格和换行都当成内容来解析
<br>hello</br>
和
<br>
hello
</br>
这是不一样的
6.xml里面的命名规则
1.xml代码区分大小写
2.xml标签不能以数字和下划线开头,这是不正确的
3.不能以xml、XML、Xml等开头
4.标签不能包含空格和:冒号
6.xml属性的定义
1.一个标签可以有多个属性
2.属性名称不能相同
3.属性名称和属性值之间使用“=”,属性值使用引号包起来,(可以是单引号和双引号)
7.xml注释
1.写法:<!-- xml的注释 -->
2.注释不能有嵌套
8.xml特殊字符
1.在xml中想要显示 a<b,不能正常显示,需要对特殊字符< 进行转义
< <
> >等
9.xml的CDATA区
解决多个字符需要转义的操作,把这些内容放到CDATA区里面,不需要转义
写法:<![CDATA[内容]]>
将特殊字数当成文本内容,而不是标签了
10.xml的PI指令(处理指令)对中文标签不起作用,只对英文的起作用
可以在xml中设置样式
写法:<?xml-stylesheet type="text/css" href="css的路径"?>
11.xml约束简介
为什么需要约束,定义一个person的xml文件,只想要在这个文件里面保存人的信息,name、age等,但是如果在xml文件中写了一个其他(狗)的标签,也会正常显示,因为合乎语法规范,但是狗不是人的信息
xml的约束技术,dtd约束和schema约束
12.dtd的快速入门
1.创建一个文件,后缀名 1.dtd
步骤:
1.看xml中有多少个xml元素,有几个元素,在dtd中写几个<!ELEMENT>
2.判断元素是简单元素还是复杂元素
复杂元素:有子元素的元素
<!ELEMENT 元素名称 (子元素)>
简单元素:没有子元素
<!ELEMENT 元素名称 (#PCDATA)>
3.在xml中引入dtd文件
<!DOCTYPE person(根标签) SYSTEM "1.dtd">
打开xml文件用浏览器打开,浏览器只负责校验xml的语法,不负责校验约束
13.dtd的三种引入方式
1.引入外部的dtd文件
<!DOCTYPE 根元素名称 SYSTEM "dtd路径">
2.使用内部的dtd文件(元素名称之间一定要有空格)
<!DOCTYPE 根元素名称[
<!ELEMENT person (name,age)>
<!ELEMENT 元素名称 (#PCDATA)>
<!ELEMENT 元素名称 (#PCDATA)>
]>
3.使用外部的dtd文件(网络上的dtd文件)
<!DOCUTYPE 根元素 PUBLIC "DTD名称" "DTD文档的URL">
14.使用dtd定义元素
1.语法:<!ELEMENT 元素名 约束>
2.简单元素:没有子元素的元素
<!ELEMENT name (#PCDATA)>
1.(#PCDATA):约束name是字符串类型
2.EMPTY:元素为空(没有内容) <!ELEMENT name EMPTY>
3.ANY:任意
3:复杂元素
<!ELEMENT 元素名称 (子元素)>
1.<!ELEMENT person (name,age,sex,school)>
子元素只能出现一次
2.表示子元素出现的次数
+:表示一次或者多次
?:表示出现0次或者1次
*:表示0次或者多次
3.元素之间使用,进行隔开,表示元素出现的顺序
4.子元素直接使用|隔开,表示只能出现之间的一个
15.使用dtd定义属性
1.语法:
<! ATTLIST 元素名称
属性名称 属性类型 属性的约束
>
2.属性类型:
1.-CDATA:字符串
2.-枚举:在一定的范围内出现值,但是只能每次出现其中一个
(aa|bb|cc)
3.-ID:值只能是字母或者下滑线开头
<!ATTLIST name
ID3 ID #REQUIRED
>
3.属性的约束
1.#REQUIRED 属性必须存在
2.#IMPLIED 属性可有可无
3.#FIXED 表示一个固定值 #FIXED "AAA"
属性的值必须是设置的这个固定值
<!ATTLIST sex
ID4 CDATA #FIXED "ABC"
>
4.直接值
不写属性:使用直接值
写属性:使用属性值
16.实体的定义
语法:<!ENTITY 实体名称 ”实体的值“>
<!ENTITY TEST "hello">
使用实体 &实体名称;
注意:定义实体需要写在内部dtd里面,如果写在外部的dtd里面,在有些浏览器下,内容得不到
17.xml的解析的简介(写到java代码里)
1.xml是标记型文档
2.js使用dom解析标记型文档
3.xml的解析方法(技术):dom 和 sax
dom
根据xml的层级结构在内存中分配一个树形结构,把xml的标签,树形和文本都封装成对象
缺点:
如果文件过大,造成内存溢出
使用dom优点:
方便增删改查
sax
采用事件驱动,边读边解析,从上到下,一行一行的解析,解析到某一对象,把对象名称返回
优点:不会造成内存溢出
缺点:不能实现增删改查
想要解析xml,首先需要解析器
针对dom和sax方式的解析器,通过api方式提供
sun公司提供的针对dom和sax解析器 jaxp
dom4j ---- dom4j(实际开发中使用最多)
jdom ---- jdom
18.jaxp的api的查看
jaxp是javase的一部分
jaxp解析器在jdk的javax.xml,parsers包里面
四个类:分别针对dom和sax解析使用的类
dom:DocumentBuilder :解析器类
这是一个抽象类,不能new
此类的实例可以从 DocumentBuilderFactory.newDocumentBuilder()方法获取
DocumentBuilderFactory:解析器工厂
这是一个抽象类,不能new
newInstance()获取实例
sax:SAXParser:解析器类
SAXFactory:解析器工厂
19.使用jaxp实现查询操作
查询xml中所有的name元素的值
步骤:
1.创建解析器工厂
DocumentBuilderFactory builderFactory = DocumentBuilderuilderFactory.newInstance()
2.根据解析器工厂创建解析器
DocumentBuilder builder = DocumentBuilder.newDocumentBuilder()
3.解析xml返回document
Document document = builder.parse("src/person.xml")
4.得到所有的name元素
NodeList list = document.getElementsByTagName("name")
4.1获取第一个元素,item方法获取具体元素
Node name1 = list.item(0);
5.返回集合,遍历集合,得到每一个name元素
for (int i=0;i<list.getLength();i++){
Node name1 = list.item(i);
String s = name1.getTextContent();
System.out.println(s);
}
在第一个p1后面添加<sex>women</sex>
· 步骤:
1.创建解析器工厂
2.根据解析器工厂创建解析器
3.解析xml,返回Document
4.得到第一个p1
得到所有p1,使用item方法下标得到
5.创建sex标签createElement
6.创建文本createTextNode
7.把文本添加到sex下面appendChild
8.把sex添加到第一个p1下面
9.回写,在内存中生效
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = DocumentBuilder.newDocumentBuilder();
Document document = builder.parse("src/person.xml")
NodeList list = document.getElementsByTagName("p1");
Node p1 = list.item(0);
Element sex1 = document.createElement("sex");
Text text1 = document.createTextNode("women");
sex1.appendChild(text1);
p1.appendChild(sex1);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(new DOMSource(document),new StreamResult("src/person.xml"));
21.使用jaxp修改节点
步骤:
1.创建解析器工厂
2.根据解析器工厂创建解析器
3.解析xml,返回Document
4.得到sex item方法
5.修改sex里面的值setTextContent方法
6.回写xml
22.遍历节点
方法:递归遍历的方法
步骤:
1.创建解析器工厂
2.创建解析器
3.解析xml,返回Document
====使用递归实现
4.得到根节点
5.得到根节点子节点
6.得到根节点子节点的子节点
方法:
private static void list1(Node node){
if(node.getNodeType() == Node.ELEMENT_NODE){
System.out.println(node.getNodeName);
}
//得到一层子节点
NodeList list = node.getChildNodes();
//遍历list
for(int i=0;i<list.getLength;i++){
//得到每一个节点
Node node1 = list.item(i);
//继续得到node的子节点
list1(node1);
}
}
23.schema约束
创建一个schema文件,后缀名为 .xsd
根节点<schema>
在schema文件里面
(属性 xmlns=“http://www.w3.org/2001/XMLSchema” -表示当前xml文件是一个约束文件
targetNamespace=“http://www.example.org/one”
-使用schema约束文件,直接通过这个地址引入约束文件
elementFormDefault=“qualified”
-质量良好
步骤:
(1)看xml中有多少个元素
<element>
(2) 看简单元素和复杂元素
<completeType>
< sequence>
子元素
< /sequense>
</completeType>
(3)简单元素写在 复杂元素的里面
<element name="person">
<complexType>
<sequence>
<element name="name" type="string"></element>
<element name="age" type="int"></element>
</sequence>
</complexType>
</element>
(4)在xml(被约束文件)中 添加约束文件
<?xml version="1.0" encoding="UTF-8"?>
<person xmlns:(xsi)/*取个别名*/="http://www.w3.org/2001/XMLSchema-instance" /*表示xml是一个被约束文件*/
xmlns="http://www.example.org/one"/*是约束文档里的 yargetNamespace*/
xsi:schemaLocation="http://www.example.org/one one.xsd">/*targetNamespace +空格 约束文档的地址路径(因为在同一个目
sequence:表示元素出现的顺序
<all>:元素只能出现一次
<choice>:元素只能出现一个
maxOccurs=”unbounded“:表示元素出现的次数
<any>:表示任意元素
属性约束:
写在复杂元素里面
写在</complexType>之前
<attribute name="id1" type="int" use="required"></attribute>
name:属性名称
type:属性类型 int string
use:属性是否必须出现 required
复杂的schema约束:如何在xml里面有多个.xsd文件,而进行约束
<dept:name></dept:name>
24.使用jaxp的sax方式解析xml
sax方式不能实现增删改查操作,只能进行查询
打印整个xml文档:
执行parse方法,第一个参数xml路径,第二个参数是 事件处理器
创建一个类,继承事件处理器的类
重写里面的三个方法
获取所有name元素的值
定义一个成员变量flag = false
判断开始方法是否是name元素,如果是name元素,把flag值设置成true
如果flag值为true,在Characters方法里打印内容
当执行到结束方法的时候,把flag设置成false
得到document
创建解析器
SAXReader reader = new SAXReader();
Document document = reader.read(url);
getRootElement();获取根节点 返回的是Element
Element也是一个接口,父接口是Node
Element和Node里面方法
得到所有的p1标签
element(qname)
表示获取标签下面的第一个子标签
elements("p1") 返回list集合
获取标签下面是这个名称的所有子标签
elements()
获取标签下面的所有一层子标签
使用dom4j实现添加操作
1.创建解析器
2.创建document
3.得到根节点
4.获取到第一个p1
5.在p1下面添加元素
6.在添加完成后的元素下面添加文本
7.回写xml
SAXReader reader = new SAXReader();
Document document = reader.read("path");
Element root = document.getRootElement();
Element p1 = root.element("p1");
Element sex1 = p1.addElement("sex");
sex1.setText("nv");
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWrite xmlWriter = new XMLWriter(new FileOutputStream("src/student.xml"),format);
xmlWriter.write(document);
xmlWriter.close();
获取指定属性值的操作
1.得到document (封装了dom4j)
Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH)
2.得到根节点
Element root = document.getRootElement()
3.得到第一个p1标签
Element p1 = root.element("p1")
4.得到p1的属性值
String value = p1.attributeValue("id1")
25.dom4j支持xpath操作
可以直接获取到某个元素
第一种形式:
/AAA/DDD:表示一层一层的,AAA下面的DDD
第二种形式:
//BBB:表示和这个名称相同,表示只要是这个名字
第三种形式:
/*:表示所有元素
第四种形式:
/AA[1]:第一个
/AA[last()]:最后一个
第五种形式:
//BBB@id:选择有属性的BBB元素
第六种形式:
//BBB[@id='bbb']:元素名称为BBB,在BBB上面有id属性,并且属性值为bbb
26.使用dom4j支持xpath具体操作
默认情况下,dom4j不支持xpath
如果想要在dom4j里面有xpath
第一步需要,引入支持xpath的jar包,使用jaxen-1.1-beta-6.jar
需要把jar包导入到项目中
在dom4j里面提供了两个方法,用来支持xpath
selectNodes("xpath表达式")
获取多个表达式
selectSingleNode(”xpath表达式“)
获取单个表达式
使用xpath实现:查询xml中所有name元素的值
所有name元素的xpath表示 ://name
使用selectNodes("//name")
代码和步骤
1.得到document
2.直接使用selectNodes("//name")方法得到所有的元素
//得到document
Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH)
//使用selectNodes("//name")方法得到所有的name元素
List<Node> list = document.selectNodes("//name")
//遍历list集合
for(Node node:list){
//node是每一个name元素
//得到name元素里面的值
String s = node.getText();
System.out.println(s);
}
使用xpath实现:获取第一个p1下面name的值
//p1[@id)='aaa']/name
Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH)
Node name1 = document.selectSingleNode("//p1[@id)='aaa']/name")
String s1 = name1.getText();
System.out.println(s1);
27.实现简单的学生管理系统
xml
<?xml version="1.0" encoding="utf-8">
<student>
<stu>
<id>100</id>
<name>zhangsan</name>
<age>20</age>
</stu>
<id>101</id>
<name>lisi</name>
<age>21</age>
<stu>
</stu>
</student>
增加:步骤
1.创建解析器
2.得到document
3.获取根节点
4.在根节点上面创建stu标签
5.在stu标签上面依次添加
6.在id,name,age上依次添加值
7.回写xml
删除:步骤
1.创建解析器
SAXReader saxReader = new SAXReader();
2.得到document
Document document = saxReader.read("src/student.xml");
3.获取所有的id
List<Node> list = document.selectNodes("//id");
4.遍历list集合
for(Node node:list){
String idv = node.getText();
if(idv.equals(id)){
Element stu = node.getParent();
Element student = stu.getParent();
student.remove(stu);
}
}
5.判断集合里面的id和传递的id值是否相同
6.如果相同,把id所在的stu删除
7.回写xml
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWrite xmlWriter = new XMLWriter(new FileOutputStream("src/student.xml"),format);
xmlWriter.write(document);
xmlWriter.close();
Dom4jUtils.xmlWriters("src/p1.xml",document);
查询:步骤
1.创建解析器
2.得到document
3.获取到所有的id
4.返回的是list的集合,遍历list集合
5.得到每一个id的节点
6.id节点的值
7.判断id的值和传递的id值是否相同
8.如果相同,先获取到id的父节点stu
9.通过stu获取到name,age