目录
- XML简介
- XML基本语法
- XML解析
* DOM解析
* DOM解析原理及工具
* DOM4J解析工具用法及示例
* xPath技术
* SAX解析
* SAX解析工具
* SAX解析原理
* SAX解析工具用法及示例
* SAX解析与DOM解析的区别 - XML约束
* 引入
* XML约束技术
* DTD约束
* Schema约束
XML简介
XML(Extend Markup Language)是一种标记语言,被用来格式化的传输数据
示例
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type = "text/css">
<!--this is content-->
<CATALOG>
<CD id = "132">
<TITLE>Empire Burlesque</TITLE>
<ARTIST>Bob Dylan</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>Columbia</COMPANY>
<PRICE>10.90</PRICE>
<YEAR>1985</YEAR>
</CD>
</CATALOG>
其中:
- <?xml version="1.0" encoding="ISO-8859-1"?>声明了XML的版本(version)以及编码方式(encoding)
- <?xml-stylesheet type = "text/css"> 处理指令,告诉XML解析如何解析XML文件,type的值表示对应的css文件
- < !--this is content-->是注释
- <CATALOG></CATALOG>是一对标签它们的名字可以自己定义,其中<CATALOG>是开始标签,</CATALOG>是关闭标签
- <CD id = "132"> id是CD的属性
- <PRICE>10.90</PRICE> 10.90是标签的内容
- xml描述了一种树形结构 CATALOG是根,CD是CATALOG的子节点;TITLE,ARTIST,COUNTRY等是CD的子节点
XML基本语法
一、XML对大小写敏感
二、所有XML标签都必须有关闭标签
三、头尾标签名应该一样
四、属性值必须加引号
五、在 XML 中,空格会被保留(XML中多个空格只会保留一个)
六、实体引用(转义字符)
-
在 XML 中,一些字符拥有特殊的意义。如果你把字符 "<" 放在 XML 元素中,会发生错误,这是因为解析器会把它当作新元素的开始。这样会产生 XML 错误:
解决办法:
- CDATA块,让一些需要进行原样输出的内容中的特殊字符原样输出。
<![CDATA[<html><head></head><body></body></html>]]>
DOM解析
1)DOM解析原理
DOM解析XML文档时,XML解析器一次性吧整个XML文档加载进内存,然后在内存中构建一棵Document对象树,通过Document对象,可以得到下面的节点对象,通过节点对象访问数据
2)DOM解析工具
- JAXP (oracle-Sun公司官方)
- JDOM工具(非官方)
- Dom4J工具(非官方)(三大框架默认读取xml的工具就是Dom4j)
DOM4J解析工具
需要导包使用
1)dom4j结构
2)dom4j读取xml文件
节点:
- Iterator Element.nodeIterator(); //获取当前标签节点下的所有子节点
标签:
- Element Document.getRootElement(); //获取xml文档的根标签
- Element ELement.element("标签名") //指定名称的第一个子标签
- Iterator<Element> Element.elementIterator("标签名");// 指定名称的所有子标签
- List<Element> Element.elements(); //获取所有子标签
属性:
- String Element.attributeValue("属性名") //获取指定名称的属性值
- Attribute Element.attribute("属性名");//获取指定名称的属性对象
- Attribute.getName() //获取属性名称
- Attibute.getValue() //获取属性值
- List<Attribute> Element.attributes(); //获取所有属性对象
- Iterator<Attribute> Element.attibuteIterator(); //获取所有属性对象
文本:
- Element.getText(); //获取当前标签的文本
- Element.elementText("标签名") //获取当前标签的指定名称的子标签的文本内容
示例1:利用dom4j输出一个xml文件
public class Demo1 {
@Test
public void test()throws Exception {
SAXReader reader = new SAXReader();
Document document = reader.read(new File("./src/contact.xml"));
//获得根标签
Element element = document.getRootElement();
StringBuffer sb = new StringBuffer();
//用此方法遍历整个xml文件(先根遍历形式)
getchild(element,sb);
System.out.println(sb.toString());
}
private void getchild(Element element, StringBuffer sb) {
// TODO Auto-generated method stub
sb.append("<"+element.getName());
//获得标签的所有属性
List<Attribute> attrs = element.attributes();
//输出标签属性
if(attrs!=null) {
for (Attribute attribute : attrs) {
sb.append(" "+attribute.getName()+"=\""+attribute.getValue()+"\"");
}
}
sb.append(">");
//获得当前标签下的所有子标签
Iterator<Node> iterator= element.nodeIterator();
while(iterator.hasNext()) {
Node node = iterator.next();
//输出标签
if(node instanceof Element) {
Element e = (Element)node;
getchild(e,sb);
}
//输出文本
if(node instanceof Text) {
Text text = (Text)node;
sb.append(node.getText());
}
}
sb.append("</"+element.getName()+">");
}
}
示例2:把xml获取的信息封装到对象内
/**
* 把xml封装到对象中
*
*/
public class Demo2 {
@Test
public void test2() throws Exception{
SAXReader reader = new SAXReader();
Document doc = reader.read(new File("./src/contact.xml"));
Element elem = doc.getRootElement();
Iterator<Element> it = elem.elementIterator();
ArrayList<Contact> contacts = new ArrayList();
while(it.hasNext()) {
Contact contact = new Contact();
Element element = it.next();
contact.setId(element.attributeValue("id"));
contact.setAge(element.elementText("age"));
contact.setPhone(element.elementText("phone"));
contact.setEmail(element.elementText("email"));
contact.setQq(element.elementText("qq"));
contacts.add(contact);
}
for(Contact contact:contacts) {
System.out.println(contact);
}
}
}
3) 修改xml文件
增加:
- DocumentHelper.createDocument() 增加文档
- addElement("名称") 增加标签
- addAttribute("名称",“值”) 增加属性
修改:
- Attribute.setValue("值") 修改属性值
- Element.addAtribute("同名的属性名","值") 修改同名的属性值
- Element.setText("内容") 修改文本内容
删除
- Element.detach(); 删除标签
- Attribute.detach(); 删除属性
写入
- OutputFormat.createPrettyPrint() 创建易读的xml文件
- OutputFormat.createCompactFormat() 创建紧凑的xml文件
- format.setEncoding("编码方式");设置编码方式
- XMLWriter(OutputStream out,OutPutformat format) 设置写入方式
- XMLWriter.write 写入内容
写入基本流程:首先创构建一个空的Document对象,然后向其中按照节点关系添加标签(根标签只能有一个),然后创建文件输出流,指定输出格式,利用XMLWriter对象设置格式和写入内容,最后关闭writer对象。
示例3:创建文件并写入一个简单的XML文档:
************
/**
* 生成xml文档
*
<Students>
<Student id="1">
<name>张三</name>
<gender>男</gender>
<grade>计算机1班</grade>
<address>广州天河</address>
</Student>
<Student id="2">
<name>李四</name>
<gender>女</gender>
<grade>计算机2班</grade>
<address>广州越秀</address>
</Student>
</Students>
*
*/
public class Demo3 {
@Test
public void test() throws Exception {
//在内存创建Document文档
Document doc = DocumentHelper.createDocument();
//写入内容
Element rootElement = doc.addElement("Students");
//增加第二层标签
Element studentElem = rootElement.addElement("Student");
//增加属性
studentElem.addAttribute("id", "1");
//添加第三层标签
studentElem.addElement("name").setText("张三");
studentElem.addElement("gender").setText("男");
studentElem.addElement("grade").setText("计算机一班");
studentElem.addElement("address").setText("广州天河");
//增加第二个二层标签
Element studentElemnt2 = rootElement.addElement("Student");
studentElemnt2.addAttribute("id", "2");
//为第二个二层标签添加子标签
studentElemnt2.addElement("name").setText("李四");
studentElemnt2.addElement("gender").setText("女");
studentElemnt2.addElement("grade").setText("计算机二班");
studentElemnt2.addElement("address").setText("广州越秀");
//将内容写出到文件
//创建输出流
FileOutputStream out = new FileOutputStream(new File("f:/student.xml"));
//指定输出方式
OutputFormat format = OutputFormat.createPrettyPrint();
//指定编码方式
format.setEncoding("utf-8");
XMLWriter writer = new XMLWriter(out,format);
//写出内容
writer.write(doc);
//关闭资源
writer.close();
}
}
示例4:修改、删除xml文件
/**
* 修改id为2的学生的姓名+删除id为2的学生标签
*
*/
public class Demo3 {
@Test
public void test() throws Exception {
//将XML文件载入为document对象
Document document = new SAXReader().read(new File("f:/student.xml"));
//获取所有Student标签
Iterator<Element> it = document.getRootElement().elementIterator("Student");
//查询id为2的学生
while(it.hasNext()) {
Element elem = it.next();
System.out.println(elem.attribute("id").getValue());
if(elem.attributeValue("id").equals("2")) {
//修改姓名
//elem.element("name").setText("王丽");
//删除该学生标签
elem.detach();
break;
}
}
FileOutputStream out = new FileOutputStream("f:/student.xml");
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("utf-8");
XMLWriter writer = new XMLWriter(out,format);
writer.write(document);
writer.close();
}
}
4)xPath技术
当使用dom4j查询比较深的层次节点时比较麻烦,xPath技术可以使我们快速获得深层次节点
使用xPath的方法需要导入dom4j文件夹下的jaxen-1.1-beta-6.jar包。
xPath语法:
Xpath语法类似于在一个文件系统中定位文件
W3C的Xpath语法教程:http://www.w3school.com.cn/xpath/xpath_syntax.asp
- / 绝对路径 表示从xml的根位置开始或子元素(一个层次结构)
- // 相对路径 表示不分任何层次结构的选择元素。
- * 通配符 表示匹配所有元素
- [] 条件 表示选择什么条件下的元素
- @ 属性 表示选择属性节点
- and 关系 表示条件的与关系(等价于&&)
- text() 文本 表示选择文本内容
在DOM4J中的使用方法:
- List<Node> selectNodes("xpath表达式"); 查询多个节点对象
- Node selectSingleNode("xpath表达式"); 查询一个节点对象
SAX解析
1)SAX解析工具
SAX解析工具- Sun公司提供的。内置在jdk中。org.xml.sax.*
2)SAX解析原理
加载一点,读取一点,处理一点。对内存要求比较低。
核心的API:
SAXParser类: 用于读取和解析xml文件对象
- parse(File file,DefautHandler);
参数一: File:表示 读取的xml文件。
参数二: DefaultHandler: SAX事件处理程序。需要自己实现它的子类,覆盖相应方法进行解析
DefaultHandler类的API:
- void startDocument() : 在读到文档开始时调用
- void endDocument() :在读到文档结束时调用
- void startElement(String uri, String localName, String qName, Attributes attributes) :读到开始标签时调用
- void endElement(String uri, String localName, String qName) :读到结束标签时调用
- void characters(char[] ch, int start, int length) : 读到文本内容时调用
3)示例,利用SAX解析输出完整xml文档内容
1.主函数:
/**
* 读取contact.xml文件,完整输出文档内容
*
*/
public class Demo2 {
public static void main(String[] args)throws Exception {
//1.创建SAXParser
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
//2.读取xml文件
MyDefaultHandler2 handler = new MyDefaultHandler2();
parser.parse(new File("./src/contact.xml"), handler);
String content = handler.getContent();
System.out.println(content);
}
}
2.MyDefaultHandler2类
/**
* SAX处理器程序
*/
public class MyDefaultHandler2 extends DefaultHandler {
//存储xml文档信息
private StringBuffer sb = new StringBuffer();
//获取xml信息
public String getContent(){
return sb.toString();
}
/**
* 开始标签
*/
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
sb.append("<"+qName);
//判断是否有属性
if(attributes!=null){
for(int i=0;i<attributes.getLength();i++){
//得到属性名称
String attrName = attributes.getQName(i);
//得到属性值
String attrValue = attributes.getValue(i);
sb.append(" "+attrName+"=\""+attrValue+"\"");
}
}
sb.append(">");
}
/**
* 文本内容
*/
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
//得到当前读取的文本
String content = new String(ch,start,length);
sb.append(content);
}
/**
* 结束标签
*/
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
sb.append("</"+qName+">");
}
}
SAX解析与DOM解析的区别
DOM解析 | SAX解析 |
---|---|
原理: 一次性加载xml文档,不适合大容量的文件读取 | 原理: 加载一点,读取一点,处理一点。适合大容量文件的读取 |
DOM解析可以任意进行增删改查 | SAX解析只能读取 |
DOM解析任意读取任何位置的数据,甚至往回读 | SAX解析只能从上往下,按顺序读取,不能往回读 |
DOM解析面向对象的编程方法(Node,Element,Attribute),Java开发者编码比较简单。 | SAX解析基于事件的编程方法。java开发编码相对复杂。 |
XML约束
1)引入
XML语法是由w3c组织制定的规范xml文件的基本编写规则,而XML约束是开发者自定义规则以使XML符合自己的规范的约束。
2)XML约束技术
DTD约束:语法相对简单,功能也相对简单。学习成本也低。
Schema约束:语法相对复杂,功能也相对强大。学习成本相对高!!!(名称空间)
3)DTD约束
1.导入DTD方式
- 内部导入
<?xml version="1.0"?>
<!DOCTYPE note [//定义此文档是 note 类型的文档。
<!ELEMENT note (to,from,heading,body)> //定义 note 元素有四个元素:"to、from、heading,、body"
<!ELEMENT to (#PCDATA)> //元素为 "#PCDATA" 类型
<!ELEMENT from (#PCDATA)> //元素为 "#PCDATA" 类型
<!ELEMENT heading (#PCDATA)> //元素为 "#PCDATA" 类型
<!ELEMENT body (#PCDATA)> //元素为 "#PCDATA" 类型
]>
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
- 外部导入
本地文件系统:<!DOCTYPE note SYSTEM "note.dtd">
公共的外部导入:<!DOCTYPE 根元素 PUBLIC "http://gz.itcast.cn/itcast.dtd">
2.DTD语法
- 约束标签 <!ELEMENT 元素名称 类别> 或 <!ELEMENT 元素名称 (元素内容)>
类别:
空标签: EMPTY。 表示元素一定是空元素。
普通字符串: (#PCDATA)。表示元素的内容一定是普通字符串(不能含有子标签)。
任何内容: ANY。表示元素的内容可以是任意内容(包括子标签)
顺序问题:
<!ELEMENT 元素名称 (子元素名称 1,子元素名称 2,.....)>: 表示子标签必须按顺序出现
次数问题:
标签名 : 表示标签必须出现且只出现1次。
标签名+ : 至少出现1次
标签名* : 0或n次。
标签名? : 0 或1次。
- 约束属性 <!ATTLIST 元素名称 属性名称 属性类型 默认值>
默认值:
#REQUIRED 表示属性是必需的
#IMPLIED 表示属性不是必需的
#FIXED value 表示属性不是必须的,但属性值是固定的
属性类型:控制属性值的
CDATA : 表示普通字符串
(en1|en2|..): 表示一定是任选其中的一个值
ID: 表示在一个xml文档中该属性值必须唯一。值不能以数字开头
4)Schema约束
名称空间:告诉xml文档的哪个元素被哪个schema文档约束。 在一个xml文档中,不同的标签可以受到不同的schema文档的约束。
1.一个名称空间受到schema文档约束的情况
2.多个名称空间受到多个schema文档约束的情况
3.默认名称空间的情况
4.没有名称空间的情况