XML
一、XML概述
- XML是什么?
- XML : Extensible Markup Language 可扩展标记语言 。 由w3c组织提供 , 2000年开发出1.0版本 , 现在用1.0版本居多 。
- XML是一种数据存储或传输的格式 , 本质上就是一串字符串 。
- XML是怎么保存数据的?
- 在XML中 , 利用标签来保存数据 , 利用标签之间的层级关系表示数据之间的层级关系 。
- 用户可以自定义标签 , 标签分为开始标签和结束标签 , 在开始标签和结束标签之间可以嵌套其它标签 。
- XML应用场景
- 传输数据
- 由于XML本质上是一段字符串 , 具有跨平台性 , 所以可以在不同的系统之间进行数据交换 。
- 如:天气数据XML接口 :http://flash.weather.com.cn/wmaps/xml/china.xml
- 用作配置文件
- XML可以有结构的保存数据 , 因此XML常常用作应用程序的配置文件
- 传输数据
二、XML语法
文档声明
可以用来声明XML文档的基本属性信息 , 解析器会根据文档 声明类决定如何解析这个文档 。
<?xml version="1.0" ebcoding="utf-8" ?>
- version 用于指定XML文档所遵循的XML版本
- encoding 用于通知XML解析器使用什么编码来解析该文档 encoding指定的编码必须和xml保存时指定的编码一致, 否则会出现乱码 。
- 注意:
- 一个XML文档有且仅有一个文档声明(规范要求)
- 文档声明只能放在文档的首行 , 并且前面不能有任何内容 。
- 如果一个XML文档没有文档声明 , 该文档是一个格式不良好的XML文档 。
元素
一个标签就是一个元素
如:<book></book> 其中 <book> 为开始标签 </book>为结束标签
如果一个标签体内没有任何内容 , 那么可以将开始标签和结束标签合并
如: <book/>
- 一个xml文档中只能有一个根标签
标签之间可以嵌套 , 来表示数据之间的层级关系 , 但不能出现交叉嵌套
比如: <a>welcome to <b>www.tarena.com.cn</a></b> 错误 <a>welcome to www.tarena.com.cn</b></a> 错误 <a>welcome to www.tarena.com.cn<b/></a> 正确 <a>welcome to www.tarena<b/>.com.cn</a> 正确
XML元素的命名规范:
区分大小写
如: <a/> 与 <A/> 是两个不同标签
不能以数字或标点符号开头
如: <123a/> 错误
- 不能以任意形式的xml开头
- 不能包含空格
- 不能包含冒号
- 属性
- 一个标签可以有多个属性 , 多个属性之间可以用空格分开 , 属性值一定要用单引号, 或双引号引起来 。
- 属性具有与 元素相同的命名规范 。
注释
格式
<!-- 内容-->
- 注意::
- 注释不能放在文档声明前
- 注释不能嵌套
转义字符
用其他符号代替特殊符号
几个常用的转义字符 < < > > " " ' ' & &
- XML解析
- DOM解析
- SAX解析
- 解析开发包
- Jaxp 、 Jdom 、 dom4j
三、实例
- 编写程序之前 ,需要些导入相应的解析XML的包dom4j.jar , 并build path
被操作的XML文档
<?xml version="1.0" encoding="utf-8" ?> <书架> <书> <书名>数据结构</书名> <作者>严蔚敏</作者> <售价>29.00元</售价> </书> <书> <书名>高等数学</书名> <作者>同济大学数学系</作者> <售价>55.00元</售价> </书> </书架>
入门程序
import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; /** * dom4j快速入门程序 */ public class Demo1 { public static void main(String[] args) throws DocumentException { //1.创建解析器 SAXReader reader = new SAXReader(); //2.利用解析器读取xml文件 Document doc = reader.read("book.xml"); //3.获取根节点 Element root = doc.getRootElement(); //4.获取第一本书节点 Element bookEle = root.element("书"); //5.获取第一个书名节点 Element bookNameEle = bookEle.element("书名"); //6.获取书名中的内容 String text = bookNameEle.getText(); System.out.println("第一本书的书名为:"+text); } }
操作元素
- 在案例中先将创建解析器 , 读取文档这两部每次都需要写的操作抽取了出来作为工具方法
- 对文档进行增、删、改后 , 需要将修改后的文档重新写入到xml中 , 所以也把重新写回xml的步骤也抽取出来 形成一个XMLUtils工具类 。
XMLUtils工具类
import java.io.File; import java.io.FileOutputStream; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; public class XMLUtils { /** * 将更新的document写入到xml中 * @param doc * @param xmlPath */ public static void write2Xml(Document doc, String xmlPath){ try { //将更新的document写入到xml中,并加入格式输出器 XMLWriter writer = new XMLWriter(new FileOutputStream( new File("book.xml")),OutputFormat.createPrettyPrint()); writer.write(doc); writer.close(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } /** * 解析xml文件,获取document对象 * @param xmlPath * @return */ public static Document getDoc(String xmlPath){ try { //1.创建解析器 SAXReader reader = new SAXReader(); //2.利用解析器读取xml文件 Document doc = reader.read(xmlPath); return doc; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } }
*对XML文档中的元素进行增、删、改、查
import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.List; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; /** * dom4j操作元素节点 * */ public class Demo2 { public static void main(String[] args) throws DocumentException, IOException { //2.查询第二本书的售价,并输出到控制台 //findPrice(); //3.给第一本书添加一个特价节点(2种方式) //addPrice(); //4.给第二本书在作者节点前插入一个特价节点 //addPrice2(); //5.删除第二本书的特价节点(2种方式) //deletePriceEle(); //6.更新第一本书的特价节点的内容为19.8元 //创建解析器并获取根节点 Document doc = XMLUtils.getDoc("book.xml"); doc.getRootElement().element("书").element("特价").setText("19.8元"); //将更新的document写入到xml中 XMLUtils.write2Xml(doc, "book.xml"); System.out.println("执行完毕"); } private static void deletePriceEle() { //创建解析器并获取根节点 Document doc = XMLUtils.getDoc("book.xml"); Element root = doc.getRootElement(); //获取root下所有节点集合 List<Element> list = root.elements(); //获取第二个本书 Element bookEle2 = list.get(1); /*//方法一 //获取特价节点 Element priceEle2 = bookEle2.element("特价"); //将特价节点从第二本书中删除 bookEle2.remove(priceEle2);*/ //方法二 //获取第二本书所有元素 List list2 = bookEle2.elements(); //删除第二个元素 list2.remove(1); //将更新的document写入到xml中 XMLUtils.write2Xml(doc, "book.xml"); } private static void addPrice2() { //创建解析器并获取根节点 Document doc = XMLUtils.getDoc("book.xml"); Element root = doc.getRootElement(); //获取root下所有节点集合 List<Element> list = root.elements(); //获取第二个元素 Element bookEle2 = list.get(1); //创建一个游离节点 Element priceEle2 = DocumentHelper.createElement("特价"); priceEle2.setText("6.6元"); //将游离节点插入到指定位置 List list2 = bookEle2.elements(); list2.add(1, priceEle2); //将更新的document写入到xml中 XMLUtils.write2Xml(doc, "book.xml"); } private static void addPrice() throws UnsupportedEncodingException, FileNotFoundException, IOException { //创建解析器并获取根节点 Document doc = XMLUtils.getDoc("book.xml"); Element root = doc.getRootElement(); //获取第一本书 Element bookEle = root.element("书"); /*//方式一 //创建一个游离的节点 Element priceEle2 = DocumentHelper.createElement("特价"); priceEle2.setText("9.9元"); //将游离节点挂载到第一本书上 bookEle.add(priceEle2);*/ //方式二 //在第一本书上添加特价子节点 Element priceEle2 = bookEle.addElement("特价"); priceEle2.setText("8.8元"); //将更新的document写入到xml中,并加入格式输出器 XMLWriter writer = new XMLWriter( new FileOutputStream(new File("book.xml")),OutputFormat.createPrettyPrint()); writer.write(doc); writer.close(); } private static void findPrice() throws DocumentException { //1.创建解析器 SAXReader reader = new SAXReader(); //2.利用解析器读取xml文件 Document doc = reader.read("book.xml"); //3.获取根节点 Element root = doc.getRootElement(); //4.获取root下所有节点集合 List<Element> list = root.elements(); //5.获取第二本书节点 Element bookEle2 = list.get(1); //6.获取第二本书的售价节点 Element price = bookEle2.element("售价"); //7.获取售价 String text = price.getText(); System.out.println("第二本书的售价为:"+text); } }
操作元素的属性
import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; /** * dom4j操作属性节点 */ public class Demo3 { public static void main(String[] args) { //1.给第一本书添加一个属性,如:出版社="清华大学出版社"(2种方式) //addAttr(); //2.在控制台上打印输出第一本书的出版社属性的值,并更新属性的值为“人民出版社”(3种方式) //findAndUpdateAttr(); //3.删除第一本书的出版社属性(2种方式) //创建解析器,读取xml,获取根目录 Document doc = XMLUtils.getDoc("book.xml"); Element root = doc.getRootElement(); //获取第一本书 Element bookEle = root.element("书"); /*//方式一 //获取第一本书的属性 Attribute attr = bookEle.attribute("出版社"); //将属性从第一本书中删除 bookEle.remove(attr);*/ //方式二 //如果给一个正常值,为添加,如果给一个null,则为删除 bookEle.addAttribute("出版社",null); //将更新的document写入到xml文档中 XMLUtils.write2Xml(doc, "book.xml"); System.out.println("执行完成"); } private static void findAndUpdateAttr() { //创建解析器,读取xml,获取根目录 Document doc = XMLUtils.getDoc("book.xml"); Element root = doc.getRootElement(); //获取第一本书 Element bookEle = root.element("书"); //方式一 //Attribute attr = bookEle.attribute(0); //方式二 Attribute attr = bookEle.attribute("出版社"); attr.setValue("人民出版社"); System.out.println(attr.getName()+":"+attr.getValue()); //方式三 //String value = bookEle.attributeValue("出版社"); //System.out.println(value); //将更新的document写入到xml文档中 XMLUtils.write2Xml(doc, "book.xml"); } private static void addAttr() { //创建解析器,读取xml,获取根目录 Document doc = XMLUtils.getDoc("book.xml"); Element root = doc.getRootElement(); //获取第一本书 Element bookEle = root.element("书"); /*//方法一 //创建一个游离的属性 Attribute attr = DocumentHelper.createAttribute(bookEle, "出版社", "清华大学出版社"); //将游离的属性挂载到第一本书上 bookEle.add(attr);*/ //方法二 //在第一本书上直接添加属性 bookEle.addAttribute("版次","1.0"); //将更新的document写入到xml文档中 XMLUtils.write2Xml(doc, "book.xml"); } }