1.什么是XML
XML的作用:处理有关系的数据,它允许用户自定义标签,一个标签用于描述一段数据;一个标签可以分为开始标签和结束标签,在开始标签和结束标签之间,又可以使用其他标签描述其他数据,以此来实现数据关系的描述。
2.XML常见应用
- XML技术除了用于保存有关系的数据之外,它还经常用于软件配置文件,以描述程序模板之间的关系
- 在一个软件系统中,为提高系统的灵活性,它所启动的模块通常由配置文件决定(例如一个软件在启动时,它需要启动A,B两个模块,而A,B这两个模块在启动时,又分别需要A1,A2和B1,B2模块的支持,为了准确描述这种关系,此时使用XML文件最为合适)
<soft> <a> <a1></a1> <a2></a2> </a> <b> <b1></b1> <b2></b2> </b> </soft>
3.XML语法
1.文档声明
在编写XML文档时,需要先使用文档声明,声明XML文档的类型
固定格式为
<?xml ?>
在空格里面写版本和编码格式<?xml和?>是固定格式,不能修改,中间连空格都不能有,要一模一样。
注意:写的时候如果想用空格将内容隔开,只能用英文空格。
标准写法:其中version代表版本,encoding代表编码,standalone代表文档是否独立(是否依赖别的文档)
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
2.元素
- XML元素指XML文件中出现的标签
包含标签体:<a>javaweb</a>
不含标签体:<a></a>(简写为<a/>)
- 一个标签中也可以嵌套若干子标签。但所有标签必须合理的嵌套,绝对不允许交叉嵌套
- 格式良好的XML文档必须有且仅有一个根标签,其他标签都是这个根标签的子孙标签
- 对于XMl标签中出现的所有空格和换行,XML解析程序都会当作标签内容进行处理(所以在编写XML文件时,使用换行和缩进等方式来让原文件中的内容清晰可读的“良好”书写习惯可能要被迫改变)
- 一个XML元素可以包含字母,数字以及其他一些可见字符,但是必须遵守下面一些规范
区分大小写
不能以数字或“_”开头
不能以xml(XML或Xml等开头)
不能包含空格
名称中间不能包含冒号(:)
3.属性
- 一个标签可以有多个属性,每个属性都有它自己的名字和取值
<input name="text">
- 属性值一定要用双引号或单引号引起来
- 定义属性必须遵循和标签相同的命名规范
- 在XML技术中,标签所代表的信息,也可以被改成用子元素的形式来描述
<input> <name>text</name> </input>
4.注释
- XML文件中的注释采用:<!--注释-->
- XML声明之前不能有注释
- 注释不能嵌套
5.CDATA区
- 在编写XML文件时,有些内容可能不想让解析引擎解析执行,而是当作原始内容处理,遇到这种情况,可以把这些内容放在CDATA区里,对于CDATA区域的内容,XML解析程序不会处理,而是直接原封不动的输出
- 语法:<![CDATA[内容]]>
<![CDATA[ <a>JavaWeb</a> ]]>
6.转义字符
- < < 小于号
- > > 大于号
- & & 和
- ' ' 单引号
- " " 双引号
7.处理指令
- 处理指令,简称PI。处理指令用来指挥解析引擎如何解析XML文档内容
- 例如,在XML文档中可以使用xml-stylesheet指令,通知XML解析引擎,应用css文件现实XML文档内容。
<?xml-stylesheet type="text/css" href="1.css" ?>
- 处理指令必须以“<?”开头,以"?>"作为结尾,XML声明语句就是最常见的一种处理指令
4.XML约束
什么是XML约束:在XML技术里,可以编写一个文档来约束一个XML文档的书写规范,这称之为XML约束
常用的约束技术:XML DTD,XML Schema
1.DTD
先举个例子写个book.dtd来约束book.xml
book.dtd
1 <!ELEMENT 书架 (书+)> 2 <!ELEMENT 书 (书名,作者,售价)> 3 <!ELEMENT 书名 (#PCDATA)> 4 <!ELEMENT 作者 (#PCDATA)> 5 <!ELEMENT 售价 (#PCDATA)>
book.xml
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE 书架 SYSTEM "book.dtd"> 3 <书架> 4 <书> 5 <书名>java就业培训教程</书名> 6 <作者>张孝祥</作者> 7 <售价>39.00元</售价> 8 </书> 9 <书> 10 <书名>javaScript网页开发</书名> 11 <作者>张孝详</作者> 12 <售价>28.00元</售价> 13 </书> 14 </书架>
这样就约束了book.xml的书写,也就是书架里面只能有书,书必须有书名,作者,售价,而且顺序不能改变。
2.DTD语法
- 引用DTD约束
当引用的文件在本地时,采用如下方式:
<!DOCTYPE XML文档根节点 SYSTEM "DTD文件的URL">
当引用的文件是一个公共的文件时,采用如下方法
<!DOCTYPE XML文档根节点 PUBLIC "DTD名称" "DTD文件的URL">
- 元素定义
在DTD文档中使用ELEMENT声明一个XML元素,语法格式如下:
<!ELEMENT 元素名称 元素类型>
元素类型可以是元素内容,或类型,下面举例子
元素类型为元素内容:<!ELEMENT 书 (书名,作者,售价)>
元素类型为类型:<!ELEMENT 书名 (#PCDATA)>
DTD规范定义了,EMPTY表示空元素,ANY表示元素内容为任意类型
元素内容中可以用如下方式,描述内容的组成关系
用逗号分隔,表示内容的出现顺序必须和声明时一致:<!ELEMENT 书 (书名,作者,售价)>
用 | 分隔,表示任选其一,即多个只能出现一个:<!ELEMENT MYFILE (TITLE|AUTHOR|EMAIL)>
在元素内容中也可以使用+,*,?等符号表示元素出现的次数
+:一次或多次(书+)
?:0次或一次(书?)
*:0次或多次(书*)
也可以使用圆括号()批量设置
<!ELEMENT MYFILE (TITLE*,AUTHOR?,EMALL)* | COMMENT>
- 属性定义
XML文档中的标签属性需通过ATTLIST为其设置属性
语法格式:
<!ATTLIST 元素名
属性名1 属性值类型 设置说明
属性名2 属性值类型 设置说明
........
>
属性声明举例:
<! ATTLIST 商品
类别 CDATA #REQUIRED (必须属性)
颜色 CDATA #IMPLIED (可选属性)
>
对于XML文件
<商品 类别=“服装” 颜色=“黄色”></商品>
<商品 类别=“面包”></商品>
设置说明:
#REQUIRED:必须设置改属性
#IMPLIED:可以设置也可以不设置
#FIXED:说明该属性的取值固定为一个值,在XML文件中不能为该属性设置其他值。但需要为
该属性提供这个值
直接使用默认值:在XML中可以设置该值也可以不设置该属性值。若没设置则使用默认值
常用属性值类型
CDATA
ENUMERATED
ID(表示属性的设置值为一唯一值,ID属性的值只能由字母,下划线开始,不能出现空白符)
ENTITY(实体:用于为一段内容创建一个别名,以后在XML文档中就可以使用别名引用这段内容)
在DTD中定义实体要用<!ENTITY >语句
实体可分为两种类型:引用实体和参数实体
引用实体:主要在XML文档中被应用
语法格式:<!ENTITY 实体名称 “实体内容”>:直接转变成实体内容
引用方法:&实体名称
举例:<!ENTITY copyright "l am a programmer"> ©right
-------------------------------------------------------------------------------
参数实体:被DTD文件自身使用
语法格式:<!ENTITY % 实体名称 “实体内容”>
引用方法:%实体名称
举例说明:<!ENTITY % TAG_NAMES "姓名 | EMALL | 电话 | 地址">
<!ELEMENT 个人信息 (%TAG_NAMES | 生日)>
<!ELEMENT 客户信息 (%TAG_NAMES | 公司名)>
5.XML编程(CRUD)
XML解析方式分为两种:dom和sax
dom:(Document Object Model)是W3C组织推荐的解析XML的一种方式
sax:(Simple API for XML)不是官方标准,但它是XML社区事实上的标准,几乎所有的XML解析器
都支持它
dom和sax解析方法的区别
1.dom解析的优点是对文档crud比较方便,缺点就是占用内存比较大(所有元素全部在内存中生成相应的对象)
2.sax解析的优点是占用内存少,解析速度快,缺点是只适合做文档的读取,不适合做文档的crud(一层一层的解析)
XML解析开发包
Jaxp(sun),Jdom,dom4j
Jaxp
- 是J2SE的一部分,它由javax.xml,org.w3c.dom,org.xml.parsers包及其子包组成
- 在javax.xml.parsers包中,定义了几个工厂类,程序员调用这些工厂类,可以得到xml文档的DOM
或SAX的解析器,从而实现对xml文档的解析
使用Jaxp进行DOM解析:javax.xml.parsers包中的DocumentBuilderFactory用于创建DOM模式的解析器对象,DocumentBuilderFactory是一个抽象工厂类,它不能直接实例化,但该类提供了一个newInstance方法,这个方法会根据本地平台默认安装的解析器,自动创建一个工厂的对象并返回
例子:
//1.创建工厂 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); //2.得到dom解析器 DocumentBuilder db = factory.newDocumentBuilder(); //3.解析xml文档,得到代表文档的document Document d = db.parse("src/book.xml");
再用Junit写一些测试Demo
先贴要解析的xml源码
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE 书架 SYSTEM "book.dtd"> 3 <书架> 4 <书> 5 <书名 name="Hello">java就业培训教程</书名> 6 <作者>张孝祥</作者> 7 <售价>39.00元</售价> 8 </书> 9 <书> 10 <书名 name="JavaWeb">javaScript网页开发</书名> 11 <作者>张孝详</作者> 12 <售价>28.00元</售价> 13 </书> 14 </书架>
测试代码
1 @Test 2 public void test1() throws Exception{ 3 4 //创建工厂 5 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 6 //得到dom解析器 7 DocumentBuilder db = factory.newDocumentBuilder(); 8 //解析xml文档,得到代表文档的document 9 Document d = db.parse("src/book.xml"); 10 //获得标签名为书名的对象集合 11 NodeList nlist = d.getElementsByTagName("书名"); 12 //拿到集合里面的节点对象 13 Node n1 = nlist.item(0); 14 Node n2 = nlist.item(1); 15 //得到节点的内容 16 String s1 = n1.getTextContent(); 17 String s2 = n2.getTextContent(); 18 System.out.println(s1); 19 System.out.println(s2); 20 21 }
结果如下:
java就业培训教程
javaScript网页开发
测试代码二(获得所有标签的名字)
1 @Test 2 public void test2() throws Exception{ 3 4 // 创建工厂 5 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 6 // 得到dom解析器 7 DocumentBuilder db = factory.newDocumentBuilder(); 8 // 解析xml文档,得到代表文档的document 9 Document d = db.parse("src/book.xml"); 10 //得到根节点 11 NodeList nlist = d.getElementsByTagName("书架"); 12 Node root = nlist.item(0); 13 14 list(root); 15 16 } 17 18 public void list(Node root){ 19 if(root instanceof Element){ 20 System.out.println(root.getNodeName()); 21 22 NodeList nlist = root.getChildNodes(); 23 24 for(int i=0; i<nlist.getLength(); i++){ 25 26 Node child = nlist.item(i); 27 list(child); 28 29 } 30 } 31 }
Junit测试结果
1 书架 2 书 3 书名 4 作者 5 售价 6 书 7 书名 8 作者 9 售价
得到属性名的测试
1 @Test 2 public void test3() throws Exception{ 3 4 // 创建工厂 5 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 6 // 得到dom解析器 7 DocumentBuilder db = factory.newDocumentBuilder(); 8 // 解析xml文档,得到代表文档的document 9 Document d = db.parse("src/book.xml"); 10 11 NodeList nlist = d.getElementsByTagName("书名"); 12 13 Node n = nlist.item(0); 14 15 Element e = (Element) n; 16 String str = e.getAttribute("name"); 17 System.out.println(str); 18 }
测试结果得到hello
上面的操作都只是查,没有对xml进行修改,如果需要对xml进行修改,我们需要把在内存中修改后的Document对象重新写入硬盘中原来的xml文件中,从而达到修改xml文件的效果。
那么我们就需要用到更新XML文档的包了
- javax.xml.transform包中的Teansformer类用于把代表XML文件的Document转换为某种格式后
进行输出,可以把Document对象又重新写入一个XML文件中
- Transformer类通过transform方法完成转换操作,该方法接受一个源和一个目的地,我们可以
通过javax.xml.transform.dom.DOMSource类来关联要转换的document对象,用
javax.xml.transform.stream.StreamResult对象来表示数据的目的地
- Transformer对象通过TransformerFactory获得
举例说明
1 @Test 2 public void test4() throws Exception{ 3 4 // 创建工厂 5 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 6 // 得到dom解析器 7 DocumentBuilder db = factory.newDocumentBuilder(); 8 // 解析xml文档,得到代表文档的document 9 Document d = db.parse("src/book.xml"); 10 // 创建节点 11 Element e = d.createElement("售价"); 12 e.setTextContent("100元"); 13 //把节点挂到第一本书 14 Node node = d.getElementsByTagName("书").item(0); 15 node.appendChild(e); 16 //把更新后的内存写回xml文档 17 //我们这里只是把内存中的代表xml对象的那个数据修改了,并没有把这个写进硬盘 18 //所以原来在硬盘里面的xml文件并没有被修改,所以我们需要把修改后的对象写入 19 //硬盘中,得到修改后的xml文件 20 TransformerFactory tffactory = TransformerFactory.newInstance(); 21 Transformer tf = tffactory.newTransformer(); 22 tf.transform(new DOMSource(d), new StreamResult(new FileOutputStream("src/book.xml"))); 23 24 25 } 26 27 @Test 28 //向文档中指定位置插入数据 29 public void test5() throws Exception{ 30 31 // 创建工厂 32 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 33 // 得到dom解析器 34 DocumentBuilder db = factory.newDocumentBuilder(); 35 // 解析xml文档,得到代表文档的document 36 Document d = db.parse("src/book.xml"); 37 // 创建节点 38 Element e = d.createElement("售价"); 39 e.setTextContent("100元"); 40 //得到参考节点 41 Node node2 = d.getElementsByTagName("售价").item(0); 42 //得到要插子节点的节点 43 Node node = d.getElementsByTagName("书").item(0); 44 //向指定位置插入节点 45 node.insertBefore(e, node2); 46 //把更新后的内存写回xml文档 47 //我们这里只是把内存中的代表xml对象的那个数据修改了,并没有把这个写进硬盘 48 //所以原来在硬盘里面的xml文件并没有被修改,所以我们需要把修改后的对象写入 49 //硬盘中,得到修改后的xml文件 50 TransformerFactory tffactory = TransformerFactory.newInstance(); 51 Transformer tf = tffactory.newTransformer(); 52 tf.transform(new DOMSource(d), new StreamResult(new FileOutputStream("src/book.xml"))); 53 54 55 } 56 57 @Test 58 //向指定节点添加属性 59 public void test6() throws Exception{ 60 61 // 创建工厂 62 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 63 // 得到dom解析器 64 DocumentBuilder db = factory.newDocumentBuilder(); 65 // 解析xml文档,得到代表文档的document 66 Document d = db.parse("src/book.xml"); 67 // 得到书名节点 68 Element bookName = (Element) d.getElementsByTagName("书名").item(0); 69 bookName.setAttribute("name", "修改后的名字"); 70 //更新内存 71 TransformerFactory tffactory = TransformerFactory.newInstance(); 72 Transformer tf = tffactory.newTransformer(); 73 tf.transform(new DOMSource(d), new StreamResult(new FileOutputStream("src/book.xml"))); 74 75 76 77 } 78 79 @Test 80 //删除节点 81 public void test7() throws Exception{ 82 83 // 创建工厂 84 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 85 // 得到dom解析器 86 DocumentBuilder db = factory.newDocumentBuilder(); 87 // 解析xml文档,得到代表文档的document 88 Document d = db.parse("src/book.xml"); 89 //得到要删除的节点 90 Element eSon = (Element) d.getElementsByTagName("售价").item(0); 91 //得到要删除节点的父节点 92 Element eFather = (Element) d.getElementsByTagName("书").item(0); 93 //调用父节点的方法删除子节点 94 eFather.removeChild(eSon); 95 //更新内存 96 TransformerFactory tffactory = TransformerFactory.newInstance(); 97 Transformer tf = tffactory.newTransformer(); 98 tf.transform(new DOMSource(d), new StreamResult(new FileOutputStream("src/book.xml"))); 99 100 } 101 102 @Test 103 //删除节点(方法二) 104 public void test8() throws Exception{ 105 106 // 创建工厂 107 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 108 // 得到dom解析器 109 DocumentBuilder db = factory.newDocumentBuilder(); 110 // 解析xml文档,得到代表文档的document 111 Document d = db.parse("src/book.xml"); 112 //得到要删除的节点 113 Element eSon = (Element) d.getElementsByTagName("售价").item(0); 114 eSon.getParentNode().removeChild(eSon); 115 116 //更新内存 117 TransformerFactory tffactory = TransformerFactory.newInstance(); 118 Transformer tf = tffactory.newTransformer(); 119 tf.transform(new DOMSource(d), new StreamResult(new FileOutputStream("src/book.xml"))); 120 121 } 122 123 @Test 124 //更新价格 125 public void test9() throws Exception{ 126 127 // 创建工厂 128 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 129 // 得到dom解析器 130 DocumentBuilder db = factory.newDocumentBuilder(); 131 // 解析xml文档,得到代表文档的document 132 Document d = db.parse("src/book.xml"); 133 //得到要修改的售价节点 134 Element e = (Element) d.getElementsByTagName("售价").item(0); 135 e.setTextContent("10000元"); 136 137 //更新内存 138 TransformerFactory tffactory = TransformerFactory.newInstance(); 139 Transformer tf = tffactory.newTransformer(); 140 tf.transform(new DOMSource(d), new StreamResult(new FileOutputStream("src/book.xml"))); 141 142 }
sax解析:允许我们在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才能对文档进行操作(一层一层的解析)
- sax解析采用的是事件处理的方式解析XML文件,利用SAX解析XML文档,涉及两个部分,解析器和处理器
- 解析器:可以使用JAXP的API创建,创建出SAX解析器后,就可以以指定解析器去解析某个XML文档
- 解析器采用SAX方式在解析某个XML文档时,它只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器
- 事件处理器由程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松地得到sax解析器解析到的数据,从而可以决定如何对数据进行处理
代码实例
package day0503; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.Locator; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; public class Demo1{ public static void main(String[] args) throws Exception{ //1.创建解析工厂 SAXParserFactory factory = SAXParserFactory.newInstance(); //2.得到解析器 SAXParser sp = factory.newSAXParser(); //3.得到读取器 XMLReader reader = sp.getXMLReader(); //4.设置内容处理器 reader.setContentHandler(new ListHandler()); //5.读取xml文档内容 reader.parse("src/book.xml"); } } //内容处理器 class ListHandler implements ContentHandler{ @Override public void setDocumentLocator(Locator locator) { // TODO Auto-generated method stub } @Override public void startDocument() throws SAXException { // TODO Auto-generated method stub } @Override public void endDocument() throws SAXException { // TODO Auto-generated method stub } @Override public void startPrefixMapping(String prefix, String uri) throws SAXException { // TODO Auto-generated method stub } @Override public void endPrefixMapping(String prefix) throws SAXException { // TODO Auto-generated method stub } @Override public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { // TODO Auto-generated method stub System.out.println("<" + qName + ">"); for(int i=0;atts!=null&&i<atts.getLength(); i++){ String attName = atts.getQName(i); String attValue = atts.getValue(i); System.out.println(attName + "=" + attValue); } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { // TODO Auto-generated method stub System.out.println("<" + qName + ">"); } @Override public void characters(char[] ch, int start, int length) throws SAXException { // TODO Auto-generated method stub System.out.println(new String(ch,start,length)); } @Override public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { // TODO Auto-generated method stub } @Override public void processingInstruction(String target, String data) throws SAXException { // TODO Auto-generated method stub } @Override public void skippedEntity(String name) throws SAXException { // TODO Auto-generated method stub } }
使用SAX解析封装对象
1 package day0503; 2 3 import java.io.IOException; 4 import java.util.ArrayList; 5 import java.util.List; 6 7 import javax.xml.parsers.ParserConfigurationException; 8 import javax.xml.parsers.SAXParser; 9 import javax.xml.parsers.SAXParserFactory; 10 11 import org.xml.sax.Attributes; 12 import org.xml.sax.SAXException; 13 import org.xml.sax.XMLReader; 14 import org.xml.sax.helpers.DefaultHandler; 15 16 public class Demo3 { 17 18 public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException { 19 // TODO Auto-generated method stub 20 21 //1.创建解析工厂 22 SAXParserFactory factory = SAXParserFactory.newInstance(); 23 //2.得到解析器 24 SAXParser sp = factory.newSAXParser(); 25 //3.得到读取器 26 XMLReader reader = sp.getXMLReader(); 27 //4.设置内容处理器 28 BeanListHandler handle = new BeanListHandler(); 29 reader.setContentHandler(handle); 30 //5.读取xml文档内容 31 reader.parse("src/book.xml"); 32 33 List<Book> list = handle.getList(); 34 System.out.println(list); 35 } 36 37 } 38 39 //把xml文档中的每一本书封装到一个book对象,并把多个book对象放在一个list集合中返回 40 class BeanListHandler extends DefaultHandler{ 41 42 private List list = new ArrayList(); 43 private String currentTag; 44 private Book book; 45 46 @Override 47 public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { 48 49 currentTag = qName; 50 if("书".equals(qName)){ 51 book = new Book(); 52 53 } 54 55 } 56 57 @Override 58 public void characters(char[] ch, int start, int length) throws SAXException { 59 60 if("书名".equals(currentTag)){ 61 String name = new String(ch,start,length); 62 book.setName(name); 63 } 64 if("作者".equals(currentTag)){ 65 String author = new String(ch,start,length); 66 book.setAuthor(author); 67 } 68 if("价格".equals(currentTag)){ 69 String price = new String(ch,start,length); 70 book.setPrice(price); 71 } 72 73 } 74 75 @Override 76 public void endElement(String uri, String localName, String qName) throws SAXException { 77 78 currentTag = null; 79 if("书".equals(qName)){ 80 list.add(book); 81 book = null; 82 } 83 84 } 85 86 public List<Book> getList() { 87 return list; 88 } 89 90 }
Dom4j解析XML
使用Dom4j开发,需要下载dom4j相应的jar文件
使用说明:https://dom4j.github.io/
实例代码(有乱码问题)
1 package day0506; 2 3 import java.io.File; 4 import java.io.FileWriter; 5 import java.io.IOException; 6 7 import org.dom4j.Document; 8 import org.dom4j.DocumentException; 9 import org.dom4j.Element; 10 import org.dom4j.io.SAXReader; 11 import org.dom4j.io.XMLWriter; 12 import org.junit.Test; 13 14 public class Demo1111 { 15 16 @Test 17 public void test1() throws DocumentException{ 18 19 SAXReader reader = new SAXReader(); 20 Document document = reader.read(new File("src/book.xml")); 21 Element root = document.getRootElement(); 22 Element book = root.elements("书").get(1); 23 String value = book.element("书名").getText(); 24 System.out.println(value); 25 26 } 27 28 @Test 29 public void test2() throws DocumentException, IOException{ 30 31 SAXReader reader = new SAXReader(); 32 Document document = reader.read(new File("src/book.xml")); 33 Element book = document.getRootElement().element("书"); 34 book.addElement("售价").setText("209元"); 35 //更新内存 36 XMLWriter writer = new XMLWriter(new FileWriter("src/book.xml")); 37 writer.write( document ); 38 writer.close(); 39 //乱码 40 } 41 42 }
为什么会出现乱码呢?那是因为java的io流默认的字符编码和xml的字符编码不一致,那我们就需要使用
可以指定字符编码io流了
我们查一下api就可以知道可以使用:OutputStreamWriter(OutputStream out, CharsetEncoder enc)
解决乱码的方案就是设置一个编码转换器
1 OutputFormat format = OutputFormat.createPrettyPrint(); 2 format.setEncoding("UTF-8"); 3 XMLWriter writer = new XMLWriter(new OutputStreamWriter(new FileOutputStream("src/book.xml"), "UTF-8"), format); 4 writer.write(document); 5 writer.close();
使用XPath提取xml文档数据
XPath使用很方便,要使用的时候查官方文档就行,而且官方文档有中文版的
下面给出实例代码:
public class Demo2 { @Test public void test1() throws DocumentException{ SAXReader reader = new SAXReader(); Document document = reader.read(new File("src/book.xml")); String s = document.selectSingleNode("//作者").getText(); System.out.println(s); } }
使用XPath可以非常方便的提取到想要的节点。
XML Schema
XML Schema也是一种用于定义和描述XML文档结构与内容的模式语言,其出现是为了克服DTD的局限性
XML Schema VS DTD:
- XML Schema符合XML语法结构。
- DOM,SAX等XML API很容易解析出XML Schema文档中的内容。
- XML Schema对名称空间支持得非常好
- XML Schema比XML DTD支持更多得数据类型,并支持用户自定义新的数据类型。
- XML Schema定义约束能力非常强大,可以对XML实例文档作出细致得语义限制
- XML Schema不能像DTD一样定义实体,比DTD更复杂,但Xml Schema现在已是w3c组织得标准,它正逐步取代DTD
XML Schema约束快速入门
- XMLSchema文件自身就是一个XML文件,但它得扩展名通常为xsd。
- 一个XML Schema文档通常称之为模式文档(约束文档),遵循这个文档书写的xml文件称之为实例文档
- 和XML文件一样,一个XML Schema文档也必须有一个根结点,但这个根节点的名称为Schema
- 编写一个XML Schema约束文档后,通常需要把这个文件中声明的元素绑定到一个URI地址上,在XML Schema技术中有一个专业术语来描述这个过程,即把XML Schema文档声明的元素绑定到一个名称空间上,以后XML文件就可以通过这个URI(即名称空间)来告诉解析引擎,XML文档中编写的元素来自哪里,被谁约束。
使用教程:http://www.w3school.com.cn/schema/index.asp