一、概述
是什么? 指可扩展标记语言
能干什么? 传输和存储数据
怎么干? 需要自行定义标签。
XML 独立于硬件、软件以及应用程序
通常。建立完xml文件后首要的任务是:引入约束文件!
二、XML简介:可扩展标记语言,都是标记语言,通过标签来操作
具有拓展性,标签为预定义,用户自定义标签(包括自己定义中文标签)
HTML:显示数据。
XML: 存储数据。(小型数据库)
两个版本:1.0(主流) 1.1(兼容性差)
用途:1.不同系统之间数据的传输(qq发送数据为例)
2.表示生活中有关系的数据
3.经常用在配置文件
三、XML的语法:
1.文档声明
<?xml version="1.0" encoding="gbk"?>
注意格式与位置(必须第一行第一列)
xmlns表示xml namespace
中文乱码问题的解决:一般系统默认的编码方式为gbk,打开时使用另外的编码方式
故出现乱码现象。解决方式是设置保存时候编码与打开方式编码相同:另存为时设置
编码方式。
2.元素的定义
A.有开始必须要有结束,必须成对出现。<person></person>
【成对】在 XML 中,省略关闭标签是非法的。所有元素都必须有关闭标签
标签没有内容,可以在标签内结束。<mytag/>
可以合理嵌套
只有一个根标签,其它都是子标签或是孙标签等。
B.空格和换行都会当成原始内容处理
<person>
人 <person>人</person> 两种是不同的
</person>
C。命名规范:区分大小写(HTML不区分)
不能以数字和_开头
不能以xml XML等开头
不能包含空格
不能包含冒号:
D.属性:一个标签可以有多个属性,但不能有相同的属性
E.注释:同HTML <!-- -->,注释不允许嵌套。快捷键Ctrl shift /
3.特殊字符
如 < < > > " " ' &apos & &类同HTML
4.CDATA区:解决多个字符都需要转义的操作
写法:<![CDATA[内容]]>
5.PI指令(处理指令)
对XML样式的设置,引入CSS样式等。但只能设置英文标签的样式
6.XML约束:
dtd约束(以看懂为准)
创建.dtd文件约束,看xml中有几个元素,就在dtd中写几个<!ELEMENT>
再判断是简单元素或者复杂元素(有无子元素等);复杂元素则表示为<!ELEMENT 元素名称(子元素)>
如<!ELEMENT person(name,age)>:简单元素则表示为<!ELEMENT 元素名称(#PCDATA)>
再引入dtd文件:<!DOCTYPE 根元素名称 SYSTEM "dtd文件路径">
另一书根元素名称通常记录为dtd文件名称
dtd三种引入方法:1.见上。文件引入
2.使用内部dtd <!DOCTYPE 根元素名称 []>
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
3.使用外部dtd (网络上的dtd)
<!DOCTYPE 根元素名称 PUBLIC "DTD名称" "DTD文档的URL"> (struts2框架应用)
下载一个dtd文件后,复制第一行到xml文件即为成功引入,这里给出第一个接触用法的例子
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
使用dtd定义元素:<!ELEMENT 元素 约束>
简单元素约束举例:<!ELEMENT name (#PCDATA)> 约束为字符串
EMPTY 约束元素为空
ANY 任意
复杂元素约束举例:<!ELEMENT person (name,age)>
name+:表示可以出现一次或者多次
name?:表示出现0次或者1次
name*:表示任意次数
,表示出现的顺序,
name|age表示只能出现其中一个,或的关系
使用dtd定义属性:<!ATTLIST 元素名称
属性名称 属性类型 属性约束
>
属性类型一共三种 属性约束分类
CDATA 字符串 #REQUIRED 必须出现的
ENUM 枚举类型(aa|bb) #IMPLIED 可有可无
ID类型 字母或者_开头 #FIXED "AA" 固定值,如AA
直接值(没写则按照这个值)
定义实体 <!ENTITY copyright "版权所有"> 引用 ©right 一般写在内部dtd中
W3C案例
schema约束
schema符合XML语法,不能像dtd一样语法自成一派。
可以有多个schema,而dtd只能有一个。使用名称空间进行区分(类似包名进行区分)
可以支持更多的数据类型(不止字符串#PCDATA类型)
更复杂,约束更强大。
创建一个schema文件 .xsd
先看有多少个元素,就有多少个<element> 根元素 <schema></schema>
w3c预定义了属性和标签 xmlns=""表明是一个约束文件 targetNamespace="url"可以通过这个地址进行引入
看是简单或者复杂元素。
复杂元素:<complexType>
<sequence>
子元素(就是下面的简单元素内容
</sequence>
</complexType>
除了sequence 还可以有其它的:
<all></all> 表示元素只能出现一次
<choice></choice> 只能出现一个
maxOccurs="unbounded" 元素出现次数无限制
<any></any> 任意
简单元素:<element name="name" type="string"></element>
<element name="age" type="int"></element>
在XML中引入schema文件,在xml根元素上面,<person xmlns="在schema的xmlns后加-instance"
定义属性(必须是复杂元素)写在</complexType>之前
<attribute name="id1" type="int" use="required"></attribute>
四、XML解析方式【重点】
js中的DOM解析方式为根据层级结构分配树形结构,标签、属性、文本都封装成对象
XML解析方式:DOM和SAX
DOM:类同上述;树形结构容易完成增删改操作,但同时文件过大容易造成内存溢出
SAX:采用事件驱动,边读边解析。解析到一个对象则返回该对象名称。
容易查询,但不易于增删改操作
XML的解析器:不同公司提供了针对的解析器,以API文档形式给出。
jaxp【sun公司提供】
dom4j【实际开发使用最多】(XPath)
jdom
jaxp的API,属于SE部分,能在JDK中查到,javax.xml. parsers(解析)包
主要包含以下类(操作会出现格式混乱的问题:
dom:DocumentBuilder 解析器的类,抽象类(不能new)
DocumentBuilderFactory.newDocumentBuilder()方法获得
parse(string url)解析出整个文档document接口(父接口为Node)子接口中找不到方法时找父接口
DocumentBuilderFactory 解析器的工厂
newInstance();获取
查询操作:
得到工厂-》得到解析器-》得到Document-》document.getElementsByTagName()得到Nodelist,遍历等。
getTextContent()得到具体值
添加操作:
得到Document及之前操作同上,创建需要添加的元素,类同js。得到父元素(拿到第一个.item(0))
再进行操作,但此时操作的是内存里面的文档,最后要加一步回写。
通过TransformerFactory 和Transformer(得到方法同上)
再通过.transform(new DOMSource(document),new StreamResult("url"));方法回写
修改使用setTextContent()方法;其它类同上。
注意getElementsByTayName得到的是集合,要访问带.item(0)方法
同样的删除操作使用父节点进行删除。
采用递归进行遍历:访问自己。访问子节点。递归调用。
判断元素类型再进行打印。
sax:SAXParser 解析器类
SAXParserFactory 解析器的工厂
得到SAXParser实例类同上,使用的方法:parse(File,DefauleHander);
参数一为xml的路径,参数二为事件处理器(自动执行这个事件)
三个主要方法:startElement() :遇到开始标签自动执行此方法<start>
endElement() :遇到结束时自动执行</start>
characters():遇到文本时执行此方法 开始文本
qName:把标签名返回
使用dom4j解析XML,提供了解析器dom4j,由于dom4j是另外的组织开发的,不属于se的一部分。
默认情况下dom4j是不支持XPATH的,第一步需要引入jar包:dom4j下lib/jaxen
dom4j下提供两个方法支持XPATH,在document里调用
selectNodes("xpath表达式");返回Node,强转成element
selectSingleNode("xpath表达式");
所以第一步当然是导包。创建一个folder,复制jar包,点击jar包右键build path>add to path>变成奶瓶的样子
一般找docs就先看index.html,
得到document的方法:
SAXReader reader = new SAXReader();
Document document = reader.read(url);
document里面的方法:getRootElement();返回Element,也是接口(Node子接口)
Element里面的方法:getParent():得到父节点 addElement():添加标签
使用dom4j进行查询操作【XPath更方便】(增删改查操作)getText setText
创建解析器SAXReader,read()方法得到document,
得到根节点,getRootElement()
得到一层层的标签直到需要的标签(从上到下解析)
注意返回值,Element 与List<Element>
element(qname)得到标签下面第一个name子标签
elements()获取标签下面的一层子标签
elements(qname)所有一层子标签
使用dom4j进行元素末尾的添加操作(注意回写操作)
得到根节点之前同上。
得到P1,直接添加元素(不需要像前面一样先创建)
Element sex1 = p1.addElement("sex"); sex1.setText("nv");
使用这个类进行回写XMLWriter xmlWriter = new XMLWriter(OutputStream out, OutputFormat format)
一个是输出流 new FileOutputStream(xml路径),一个是格式
OutputFormat format = OutputFormat.createPrettyPrint();(是静态方法,直接类名调用,漂亮的格式,即有缩进的)
最后加一个回写回去,xmlWriter.write(document);
当然,流打开那必须关闭,xmlWriter.close();
在特定位置添加元素,应该在上一级用Elements返回list,
在list中使用list.add(index,element);需要创建一个用于添加
使用documentHelper帮助类,使用createElement()静态方法 documentHelper.createElement();
将部分代码封装到一个Utils类,封装成相关方法,常量如路径,
表示成public static final String PATH = "";
使用dom4j进行修改操作(重复部分使用封装的方法(得到Document)与回写与常量(路径等)等)
得到需要的标签后,setText()即可。
使用dom4j进行删除节点的操作,同样需要使用父节点进行删除,(可以使用getParent()方法获取父节点)
方法与Js稍有区别,remove()进行删除
【!】attributeValue()方法,得到属性值
使用dom4j支持XPath的操作,可以直接获取到某一个元素,而不用一层一层解析,
这里的XPath就类似于一种写法,一种表达式。详见手册前六实例。
/AAA/DDD/BBB一个/表示一层一层
//BBB每一层的BBB,不管哪一层都可以,只要名字相同
/AAA/BBB/*表示BBB下所有的
/AAA/BBB[1] 第一个BBB /AAA/BBB[last()] 最后一个BBB
//BBB[@id] 选择有id属性的所有BBB元素
//BBB[@id='b1'] 选择id属性为指定值的所有BBB