一、XML是什么?作用是什么?

l  XML ( eXtensible Markup Language )语言是一种可扩展的标记语言。其中的可扩展是相对HTML来说的。因为XML标签没有被预定义,需要用户自行定义标签。

l  XML 被设计的宗旨是:是表示数据,而非显示数据。

作用:

l  Java开发中,传统的配置文件是*.properties属性文件(key=value),而XML表示的数据更为丰富。

l  XML技术除用于描述有关系的数据外,还经常用作软件配置文件,以描述程序模块之间的关系。如:

              

这样的关系数据该如何处理?

用XML语言处理:

              
      

    总结:在XML语言中,它允许用户自定义标签,一个标签用于描述一段数据,一个标签分为开始标签和结束标签,在这两者之间又可以使用其它标签描述其他数据,以此来实现数据关系的描述。

二、XML的基本语法

1、文档声明

  文档的声明必须出现在第一行,之前连空行和注释都不能有.

  文档声明, 最简单的语法: <?xml version="1.0"?>

  encoding="UTF-8", 如果不添加,默认的采用的是UTF-8编码,保存在磁盘上的编码要与声明的编码一样!

  standalone属性,用来说明文档是否独立,即文档是否依赖其他文档。

  1. <?xml version="1.0" encoding="utf-8"?>

2、元素

  1)       xml 元素是指xml中的标签。一个标签分为开始标签和结束标签:

    a)         包含标签主体:<mytag>some content</mytag>

    b)         不含标签主体:<mytag/>

  2)       一个XML文档必须有且仅有一个根标签,其他标签都是这个根标签的子标签或孙标签。

  3)       一个标签中可以嵌套若干子标签,但所有标签必须合理的嵌套,不允许有交叉嵌套。

  4)       xml 中的空格与换行不会被忽略,会当做原始内容被处理.

  5)       一个XML元素可以包含字母、数字以及其它一些可见字符,但必须遵守下面的一些规范:

    a)         区分大小写,例如,<P>和<p>是两个不同的标记。

    b)         不能以数字或"_" (下划线)开头。

    c)         不能以xml(或XML、或Xml 等)开头。

    d)         不能包含空格。

    e)         名称中间不能包含冒号(:) (有特殊用途)。

3、属性

  1)       一个标签可以有多个属性,每个属性都有它自己的名称和取值,例如:  <mytag name="value"/>

  2)       属性值一定要用双引号(")或单引号(')引起来

  3)       定义属性必须遵循与标签相同的命名规范

  4)    在XML技术中,标签属性所代表的信息,也可以被改成用子元素的形式来描述。

4.注释 

  注释的语法: <!--这是注释哦.-->

  注释不能写在第一行.

  注释不能够嵌套.

  1. 1 <?xml version="1.0" encoding="utf-8"?>
  2. 2 <!-- 注释 -->
  3. 3 <书架>
  4. 4 <书 出版社="中国上海">
  5. 5 <名字>诛仙</名字>
  6. 6 <作者>萧鼎</作者>
  7. 7 <价格>32.00</价格>
  8. 8 <出版日期>2007年</出版日期>
  9. 9 </书>
  10. 10 <书 出版社="中国北京">
  11. 11 <名字>笑傲江湖</名字>
  12. 12 <作者>金庸</作者>
  13. 13 <价格>50.00</价格>
  14. 14 </书>
  15. 15 </书架>

5.CDATA区

  用于将一段内容当做普通文本.

  语法:<![CDATA[

文本内容

]]>

6.特殊字符

    &     &amp;    ampersand

    <      &lt;          less than

    >      &gt;         great than

    "      &;quot;   quotation

    '        &apos;    apostrophe

7.处理指令(processing instruction) (PI)

    作用:用来指挥软件如何解析XML文档

    语法: <?xml  ?>

    如:常用的PI指令:

    XML声明:<?xml version=“1.0” encoding=“GB2312”?>

    xml-stylesheet指令:<?xml-stylesheet type = “text/css” herf=”test.css”>

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- 这里用处理命令加入css样式 -->
  3. <?xml-stylesheet type="text/css" href = "PITest.css" ?>
  4. <中国>
  5. <北京>北京</北京>
  6. <上海>上海</上海>
  7. <深圳>深圳</深圳>
  8. </中国>

  PITest.css 文档如下:

  1. 1 @CHARSET "UTF-8";
  2. 2 北京{
  3. 3 font-size: 100px ;
  4. 4 color: red;
  5. 5 }
  6. 6 上海{
  7. 7 font-size: 110px ;
  8. 8 color: green ;
  9. 9 }
  10. 10 深圳{
  11. 11 font-size:100px ;
  12. 12 color: yellow ;
  13. 13 }

  

三、XML的约束

1、在XML 技术中可以编写一个文档来约束XML 文档里面的书写规范,这称为XML约束。

2、XML 约束技术:

常用的有:XML DTD 和 XML Schema

3、XML 约束的必要性:

     a) XML都是用户自定义的标签,若出现小小的错误,软件程序将不能正确地获取文件中的内容而报错.

总结:

格式良好的XML 文档,遵循语法规则的XML 文档。

有效的XML 文档,遵循约束文档的 XML 文档。

约束文档定义了在XML中允许出现的元素名称、属性及元素出现的顺序等等。

四、DTD的基本语法

   1.DTD 约束的两种方式:

DTD 约束可以作为一个单独的文档编写,也可以编写在XML 文档内。(编写XML内部的DTD代码),当作为单独文件时,要用utf-8格式存储。

  1. 1 <?xml version="1.0" encoding="UTF-8"?>
  2. 2 <!-- XML 写入DTD 约束 -->
  3. 3 <!DOCTYPE 世界[
  4. 4 <!ELEMENT 世界 (国家+) >
  5. 5 <!ELEMENT 国家 (名字)>
  6. 6 <!ELEMENT 名字 (#PCDATA) >
  7. 7 <!ATTLIST 名字
  8. 8 所属洲 CDATA #IMPLIED
  9. 9 >
  10. 10 <!ATTLIST 国家 所属洲 (亚洲|欧洲|南美洲|南极洲|澳洲|非洲|北美洲) "亚洲">
  11. 11 ]>
  12. 12
  13. 13 <世界>
  14. 14 <国家 所属洲 = "亚洲">
  15. 15 <名字>中国</名字>
  16. 16 </国家>
  17. 17 <国家>
  18. 18 <名字 所属洲 = "美洲">美国</名字>
  19. 19 </国家>
  20. 20 </世界>

XML 引用 DTD 约束文件时:

  1. 1 <?xml version="1.0" encoding="utf-8"?>
  2. 2 <!DOCTYPE 书架 SYSTEM "book.dtd" >
  3. 3 <书架>
  4. 4 <书>
  5. 5 <名字>诛仙</名字>
  6. 6 <作者>萧鼎</作者>
  7. 7 <价格>32.00</价格>
  8. 8 </书>
  9. 9 <书 >
  10. 10 <名字>笑傲江湖</名字>
  11. 11 <作者>金庸</作者>
  12. 12 <价格>50.00</价格>
  13. 13 </书>
  14. 14 </书架>

a)本地的 : <!DOCTYPE 根元素 SYSTEM “DTD文档路径”>

b)互联网上的:  <!DOCTYPE 根元素 PUBLIC “DTD文档路径” "dtd的URL地址">

如:<!DOCTYPE web-app PUBLIC  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"

    "http://java.sun.com/dtd/web-app_2_3.dtd">

  注意book.dtd文档如下:

  1. <!ELEMENT 书架 (书+)>
  2. <!ELEMENT 书 (名字,作者,价格)>
  3. <!ELEMENT 名字 (#PCDATA)>
  4. <!ELEMENT 作者 (#PCDATA)>
  5. <!ELEMENT 价格 (#PCDATA)>

  DTD 编写细节:

  1、 元素定义

  在DTD 文件中用ELEMENT 声明一个 XML元素,语法:

  <!ELEMENT 元素名称 元素类型>

  元素类型可以是元素内容。

  元素内容,则需要用() 括起来,

<!ELEMENT 世界 (国家+) >

<!ELEMENT 国家 (名字,所属洲)>

<!ELEMENT 名字 (#PCDATA)>

  元素类型的组成遵循正则表达式的格式:

    1、用逗号分隔,表示内容的出现顺序必须与声明时一致。

      <!ELEMENT MYFILE (TITLE,AUTHOR,EMAIL)>

    2、用|分隔,表示任选其一,即多个只能出现一个

  <!ELEMENT MYFILE (TITLE|AUTHOR|EMAIL)>

    3、在元素内容中也可以使用+、*、?等符号表示元素出现的次数:

+: 一次或多次 (书+)      regex

?: 0次或一次 (书?)

*: 0次或多次  (书*)

    4、也可使用圆括号( )批量设置,例

      <!ELEMENT FILE ((TITLE*, AUTHOR?, EMAIL)* | COMMENT)>

   元素类型,则直接书写,DTD规范定义了如下几种类型:

    EMPTY:用于定义空元素,例如<br/> <hr/>

    ANY:表示元素内容为任意类型。

2、 属性定义

  xml文档中的标签属性需通过ATTLIST为其设置属性

  语法格式:

  <!ATTLIST 元素名

        属性名1 属性值类型 设置说明

          属性名2 属性值类型 设置说明

       ……

  >

  设置说明:

  #REQUIRED:必须设置该属性

  #IMPLIED:可以设置也可以不设置

  #FIXED:说明该属性的取值固定为一个值,在 XML 文件中不能为该属性设置其它值。但需要为该属性提供这个值

  直接使用默认值:在 XML 中可以设置该值也可以不设置该属性值。若没设置则使用默认值。但需要为该属性提供这个值

  常用属性值类型

  l  CDATA:表示属性值为普通文本字符串

  l  ENUMERATED

  l  ID  indentity

  l  ENTITY(实体)

  1. 1 <!ELEMENT 国家 (名字)>
  2. 2 <!ATTLIST 国家
  3. 3 所属洲 CDATA #REQUEIRED >

  

3、 实体定义

  实体用于为一段内容创建一个别名,以后在XML  文档中就可以使用别名引用这段内容。

  实体可分为两种类型:引用实体和参数实体。

  引用实体主要在XML 文档中被使用:

  语法格式:<!ENTITY 实体名称 “实体内容” >: 直接转变成实体内容。

  引用方式:&实体名称;

  参数实体则是在DTD 文档中自身使用

  语法格式:<!ELEMENT % 实体名称 “实体内容” >

  引用方式 :%实体名称

  1. <!ENTITY % TAG_NAMES "姓名 | EMAIL | 电话 | 地址">
  2.  
  3. <!ELEMENT 个人信息 (% TAG_NAMES; | 生日)>
  4. <!ELEMENT 客户信息 (% TAG_NAMES; | 公司名)>

五、JUnit 测试类

  JUnit 作为测试工具,可以通过注释的方法来代替写main方法,同时来测试相应的方法:再用JUbit 之前 先导入junit.jar 包。
   @Test :用来注释需要被测试的方法。

   @Before : 用来注释在运行@Test方法之前需要被运行的方法。 注意:如果有多个方法被@Before 注释,则从最后一个开始运行。

   @After : 则注释在运行@Test方法之后需要被运行的方法。 注意:如果有多个方法被@After 注释,则从第一个开始运行。

   @AfterClass :注释的方法在类释放时运行。

   @BeforeClass : 注释的方法在类加载时运行。

  1. 1 import org.junit.After;
  2. 2 import org.junit.AfterClass;
  3. 3 import org.junit.Before;
  4. 4 import org.junit.BeforeClass;
  5. 5 import org.junit.Test;
  6. 6
  7. 7
  8. 8 public class JUnitDemo {
  9. 9 @Test
  10. 10 public void test_1() {
  11. 11 System.out.println("Hello JUnit!");
  12. 12 }
  13. 13 @Before
  14. 14 public void before(){
  15. 15 System.out.println("Before");
  16. 16 }
  17. 17 @AfterClass
  18. 18 public static void afterClass(){
  19. 19 System.out.println("AfterClass");
  20. 20 }
  21. 21 @After
  22. 22 public void after(){
  23. 23 System.out.println("After");
  24. 24 }
  25. 25 @BeforeClass
  26. 26 public static void beforeClass(){
  27. 27 System.out.println("BeforeClass");
  28. 28 }
  29. 29 }

  

六、JAXP进行DOM解析

XML 的两种解析方式:DOM 解析和SAX 解析。

DOM (Document  Object  Model ,文档对象模式 ) 解析,原理DOM解析器在解析XML文档时,会把文档中的所有元素(document\element\attribute\character),按照其出现的层次关系,解析成一个个Node对象(节点)

   在dom中,节点之间关系如下:

    1、  位于一个节点之上的节点是该节点的父节点(parent)

    2、    一个节点之下的节点是该节点的子节点(children)

    3、  同一层次,具有相同父节点的节点是兄弟节点(sibling)

    4、    一个节点的下一个层次的节点集合是节点后代(descendant)

    5、祖父节点及所有位于节点上面的,都是节点的祖先(ancestor)

    Node对象提供了一系列常量来代表结点的类型,当开发人员获得某个Node类型后, 就可以把Node节点转换成相应的节点对象(Node的子类对象),以便于调用其特有的方法。

    Node对象提供了相应的方法去获得它的父结点或子结点。编程人员通过这些方法就可以读取整个XML文档的内容、或添加、修改、删除XML文档的内容了。

    练习:

     1.读取节点的文本内容
     2.读取属性值
     3.添加节点
     4.删除节点
     5.更新节点
     6.打印所有元素节点的名称.

  1. 1 package cn.itheima.xml.day01;
  2. 2
  3. 3 import javax.xml.parsers.DocumentBuilderFactory;
  4. 4 import javax.xml.transform.TransformerFactory;
  5. 5 import javax.xml.transform.dom.DOMSource;
  6. 6 import javax.xml.transform.stream.StreamResult;
  7. 7
  8. 8 import org.junit.After;
  9. 9 import org.junit.Before;
  10. 10 import org.junit.Test;
  11. 11 import org.w3c.dom.Document;
  12. 12 import org.w3c.dom.Element;
  13. 13 import org.w3c.dom.NamedNodeMap;
  14. 14 import org.w3c.dom.Node;
  15. 15 import org.w3c.dom.NodeList;
  16. 16
  17. 17 public class DOMTest {
  18. 18 /*
  19. 19 1.读取节点的文本内容
  20. 20 2.读取属性值
  21. 21 3.添加节点
  22. 22 4.删除节点
  23. 23 5.更新节点
  24. 24 6.打印所有元素节点的名称.
  25. 25 */
  26. 26 /*
  27. 27 * DOM解析器在解析XML文档时,会把文档中的所有元素(document\element\attribute\character),按照其出现的层次关系,
  28. 28 * 解析成一个个Node对象(节点)。
  29. 29 *
  30. 30 * Node对象提供了一系列常量来代表结点的类型,当开发人员获得某个Node类型后,
  31. 31 * 就可以把Node节点转换成相应的节点对象(Node的子类对象),以便于调用其特有的方法。
  32. 32 */
  33. 33
  34. 34 //1、读取节点的文本内容
  35. 35 private Document doc = null ;
  36. 36 @Test
  37. 37 public void readContent() {
  38. 38 //获得标签名为"名字" 的 NodeList ;
  39. 39 NodeList lists = doc.getElementsByTagName("名字") ;
  40. 40 //获得节点的文本类容
  41. 41 for (int i = 0; i < lists.getLength(); i++) {
  42. 42 System.out.println(lists.item(i).getTextContent());
  43. 43 }
  44. 44 }
  45. 45 //2、读取属性值
  46. 46 @Test
  47. 47 public void getAttr() {
  48. 48 //获取元素“书”的NodeList
  49. 49 NodeList lists = doc.getElementsByTagName("书") ;
  50. 50 //通过遍历lists ,获取每个节点中的属性值
  51. 51 for (int i = 0; i < lists.getLength(); i++) {
  52. 52 NamedNodeMap attributes = lists.item(i).getAttributes();
  53. 53 for (int j = 0; j < attributes.getLength(); j++) {
  54. 54 System.out.println(attributes.item(j).getTextContent());
  55. 55 }
  56. 56 }
  57. 57 }
  58. 58 //3.添加节点
  59. 59 //在“书”标签下添加一个<出版日期>的元素
  60. 60 @Test
  61. 61 public void addNode() throws Exception{
  62. 62 //创建一个<出版日期> 添加到内存中
  63. 63 Element element = doc.createElement("出版日期") ;
  64. 64 //设置该标签的的文本值
  65. 65 element.setTextContent("2007年");
  66. 66 //通过Node 类中的 appendChild 方法将<出版日期>添加到节点的子节点列表的末尾
  67. 67 NodeList lists = doc.getElementsByTagName("书");
  68. 68
  69. 69 //问题:为什么只在第二个"书" 标签添加了该子节点。
  70. 70 //而且如果存在<出版日期> 子节点,为什么添加之后有两个该节点。
  71. 71 /*
  72. 72 Node appendChild(Node newChild) throws DOMException
  73. 73 将节点 newChild 添加到此节点的子节点列表的末尾。如果 newChild 已经存在于树中,则首先移除它。
  74. 74 */
  75. 75 for (int i = 0 ; i < lists.getLength() ; i ++) {
  76. 76 System.out.println(lists.item(i).getNodeName());
  77. 77 lists.item(i).appendChild(element) ;
  78. 78 }
  79. 79 updateXML() ;
  80. 80 }
  81. 81
  82. 82 //如何将修改后的DOC写到XML中?
  83. 83 public void updateXML() throws Exception {
  84. 84 /*
  85. 85 * javax.xml.transform包中的Transformer类用于把代表XML文件的Document对象转换为某种格式后进行输出
  86. 86 * Transformer类通过transform方法完成转换操作,该方法接收一个源和一个目的地。我们可以通过:
  87. 87 * > javax.xml.transform.dom.DOMSource 类来关联要转换的document对象,
  88. 88 * > javax.xml.transform.stream.StreamResult 对象来表示数据的目的地。
  89. 89 */
  90. 90
  91. 91 //创建TransformFactory 对象:
  92. 92 TransformerFactory.newInstance()
  93. 93 .newTransformer()
  94. 94 .transform(new DOMSource(doc), new StreamResult("src/cn/itheima/xml/day01/book.xml"));
  95. 95 }
  96. 96
  97. 97 //4.删除节点
  98. 98 //删除“出版日期”节点。
  99. 99 @Test
  100. 100 public void removeNode() throws Exception {
  101. 101 //获取 "出版日期" 的节点
  102. 102 Node node = doc.getElementsByTagName("出版日期").item(0) ;
  103. 103
  104. 104 //获取 node 节点的父节点。
  105. 105 //通过父节点删除"出版日期"节点
  106. 106 node.getParentNode().removeChild(node) ;
  107. 107 updateXML() ;
  108. 108 }
  109. 109
  110. 110 //5.更新节点
  111. 111 //将 "笑傲江湖" 的“价格”修改为 50.00
  112. 112 /*
  113. 113 * 1、获取“名字”的NodeList , 然后遍历 值为“笑傲江湖” 的节点。
  114. 114 * 2、获取“笑傲江湖”节点的兄弟节点。
  115. 115 */
  116. 116 @Test
  117. 117 public void updateNode() throws Exception{
  118. 118 //获取“笑傲江湖”的节点
  119. 119 NodeList nodeList = doc.getElementsByTagName("名字");
  120. 120 for (int i = 0; i < nodeList.getLength(); i++) {
  121. 121 // System.out.println(nodeList.item(i).getTextContent());
  122. 122 if ( nodeList.item(i).getTextContent().equals("笑傲江湖")) {
  123. 123 NodeList childNodes = nodeList.item(i).getParentNode().getChildNodes();
  124. 124 for (int j = 0; j < childNodes.getLength(); j++) {
  125. 125 if (childNodes.item(j).getNodeName().equals("价格")) {
  126. 126 childNodes.item(j).setTextContent("50.00") ;
  127. 127 break ;
  128. 128 }
  129. 129 }
  130. 130 }
  131. 131 }
  132. 132 //通过获取 其父节点然后通过父节点获取到“价格”节点,修改其节点的值
  133. 133 /*NodeList lists = node.getParentNode().getChildNodes() ;
  134. 134 for(int i = 0 ; i < lists.getLength() ; i++) {
  135. 135 if( lists.item(i).getNodeName().equals("价格") ) {
  136. 136 lists.item(i).setTextContent("50.00");
  137. 137 break ;
  138. 138 }
  139. 139 }*/
  140. 140 updateXML() ;
  141. 141 }
  142. 142 //6.打印所有元素节点的名称.
  143. 143 @Test
  144. 144 public void printNode(){
  145. 145 treeWeek(doc) ;
  146. 146 }
  147. 147 public void treeWeek(Node node) {
  148. 148 if(Node.ELEMENT_NODE == node.getNodeType()){
  149. 149 System.out.println(node.getNodeName());
  150. 150 }
  151. 151 NodeList nl = node.getChildNodes();
  152. 152 for (int i = 0; i < nl.getLength(); i++) {
  153. 153 Node item = nl.item(i);
  154. 154 treeWeek(item);
  155. 155 }
  156. 156 }
  157. 157 @Before
  158. 158 public void getDOM() throws Exception{
  159. 159 /*
  160. 160 * 1、获得DocumentBuilderFactory 对象。
  161. 161 * 2、通过DocumentBuilderFactory 对象创建 DocumentBuilder 对象(DOM 解析器对象)。
  162. 162 * 3、通过DocumentBuilder 对象解析XML文件,进而可以利用DOM特性对整个XML文档进行操作了。
  163. 163 */
  164. 164 doc = DocumentBuilderFactory.newInstance()
  165. 165 .newDocumentBuilder()
  166. 166 .parse("src/cn/itheima/xml/day01/book.xml") ;
  167. 167 }
  168. 168 @After
  169. 169 public void setDOM() {
  170. 170 doc = null ;
  171. 171 }
  172. 172 }

   总结:

DOM 解析 的优点是增删改方便,

缺点,如果要解析的XML 文档过大,就会导致内存溢出(Out Of Memory , OOM),因为DOM解析需要将XML 文档内容全部加载到内存中再解析。

   

  

七、JAXP进行SAX解析

l  SAX (Simple API for XML ) 解析:SAX解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才对文档进行操作。

l  SAX采用事件处理的方式解析XML文件,利用 SAX 解析 XML 文档,涉及两个部分:解析器和事件处理器:

l  解析器可以使用JAXP的API创建,创建出SAX解析器后,就可以指定解析器去解析某个XML文档。

l  解析器采用SAX方式在解析某个XML文档时,它只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器。

l  事件处理器由程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松地得到sax解析器解析到的数据,从而可以决定如何对数据进行处理。

SAX解析步骤:

1、使用SAXParserFactory创建SAX解析工厂

2、通过SAX解析工厂得到解析器对象

3、通过解析器对象得到一个XML的读取器

4、设置读取器的事件处理器

5、解析xml文件

  1. package cn.itheima.xml.day01;
  2.  
  3. import java.io.IOException;
  4.  
  5. import javax.xml.parsers.SAXParserFactory;
  6.  
  7. import org.junit.After;
  8. import org.junit.Before;
  9. import org.junit.Test;
  10. import org.xml.sax.Attributes;
  11. import org.xml.sax.SAXException;
  12. import org.xml.sax.XMLReader;
  13. import org.xml.sax.helpers.DefaultHandler;
  14.  
  15. /*
  16. * SAX解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才对文档进行操作。
  17. *
  18. * SAX采用事件处理的方式解析XML文件,利用 SAX 解析 XML 文档,涉及两个部分:解析器和事件处理器:
  19. * 解析器可以使用JAXP的API创建,创建出SAX解析器后,就可以指定解析器去解析某个XML文档。
  20. *
  21. * 解析器采用SAX方式在解析某个XML文档时,它只要解析到XML文档的一个组成部分(startDocument,startElement,character,endElement,endDocument),
  22. * 都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,
  23. * 会把当前解析到的xml文件内容作为方法的参数传递给事件处理器。
  24. *
  25. * 事件处理器由程序员编写,程序员通过事件处理器中方法的参数,
  26. * 就可以很轻松地得到sax解析器解析到的数据,从而可以决定如何对数据进行处理。
  27. * javax.xml.parsers.SAXParserFactory
  28. *
  29. */
  30.  
  31. /*
  32. SAX 解析练习.
  33. 1.读取节点的文本内容
  34. 2.读取属性值
  35. 3.添加节点
  36. 4.删除节点
  37. 5.更新节点
  38. 6.打印所有元素节点的名称.
  39.  
  40. 思路:
  41. 1、使用SAXParserFactory创建SAX解析工厂
  42. 2、通过SAX解析工厂得到解析器对象
  43. 3、通过解析器对象得到一个XML的读取器
  44. 4、设置读取器的事件处理器
  45. 5、解析xml文件
  46. */
  47. public class SAXTest {
  48. private XMLReader reader = null ;
  49. //打印出解析出的XML所有内容
  50. @Test
  51. public void printTest() throws IOException, SAXException {
  52. //设置读取器的事件处理器:
  53. reader.setContentHandler(new MyHandler()) ;
  54. reader.parse("src/cn/itheima/xml/day01/book.xml") ;
  55. }
  56.  
  57. //1.读取节点的文本内容
  58. /*
  59. * 读取节点名字为“名字”的文本内容
  60. */
  61. @Test
  62. public void getTextContent() throws IOException, SAXException {
  63. reader.setContentHandler(new getTestContent()) ;
  64. reader.parse("src/cn/itheima/xml/day01/book.xml") ;
  65. }
  66. //2.读取属性值
  67. /*
  68. * 读取节点名字为"书" 的属性值
  69. */
  70. @Test
  71. public void getAttributeName() throws IOException, SAXException {
  72. reader.setContentHandler(new getAttribute()) ;
  73. reader.parse("src/cn/itheima/xml/day01/book.xml") ;
  74. }
  75.  
  76. // 在测试之前获得一个XML读取器:
  77. @Before
  78. public void getReader() throws Exception {
  79. /*
  80. 1、使用SAXParserFactory创建SAX解析工厂
  81. 2、通过SAX解析工厂得到解析器对象
  82. 3、通过解析器对象得到一个XML的读取器
  83. */
  84. reader = SAXParserFactory.newInstance()
  85. .newSAXParser()
  86. .getXMLReader() ;
  87. }
  88. //测试完重置reader = null
  89. @After
  90. public void setReader() {
  91. reader = null ;
  92. }
  93. }
  94. class getAttribute extends DefaultHandler {
  95. @Override
  96. public void startElement(String uri, String localName, String qName,
  97. Attributes attributes) throws SAXException {
  98. if ("书".equals(qName)) {
  99. for (int i = 0; i < attributes.getLength(); i++) {
  100. System.out.println(attributes.getValue(i));
  101. }
  102. }
  103. }
  104.  
  105. }
  106. class getTestContent extends DefaultHandler{
  107. private boolean flag = false ;
  108. @Override
  109. public void startElement(String uri, String localName, String qName,
  110. Attributes attributes) throws SAXException {
  111. if ("名字".equals(qName)) {
  112. flag = true ;
  113. }
  114. }
  115.  
  116. @Override
  117. public void characters(char[] ch, int start, int length)
  118. throws SAXException {
  119. if (flag){
  120. System.out.println("文本类容:"+new String(ch,start,length));
  121. flag = false ;
  122. }
  123. }
  124.  
  125. }
  126. //编写事件处理器:
  127. /* 继承org.xml.sax.helpers.DefaultHandler
  128. * DefaultHandler 类:
  129. * SAX2 事件处理程序的默认基类。应用程序编写者可以在他们仅需实现部分接口时扩展此类;
  130. * 类似于ContentHandler 接口的适配器(adapter) ;
  131. */
  132. class MyHandler extends DefaultHandler {
  133.  
  134. //在此类中重写我们需要的几个方法:
  135. @Override
  136. public void startDocument() throws SAXException {
  137. System.out.println("XML文件开始解析:");
  138. }
  139.  
  140. @Override
  141. public void endDocument() throws SAXException {
  142. System.out.println("XML文件解析结束:");
  143. }
  144.  
  145. @Override
  146. public void startElement(String uri, String localName, String qName,
  147. Attributes attributes) throws SAXException {
  148. System.out.println("元素标签开始:"+ qName);
  149. }
  150.  
  151. @Override
  152. public void endElement(String uri, String localName, String qName)
  153. throws SAXException {
  154. System.out.println("元素标签结束:" + qName);
  155. }
  156.  
  157. @Override
  158. public void characters(char[] ch, int start, int length)
  159. throws SAXException {
  160. System.out.println("文本类容:"+new String(ch,start,length));
  161. }
  162.  
  163. }

  

  总结:优点查找非常快,但是没DOM 解析 方法那样直观明白。  

  

八、Dom4J简介、进行解析

  Dom4J 则是一层一层的解析XML文件,而且直观。

  1. 1 package cn.itheima.xml.day01;
  2. 2
  3. 3 import java.io.FileNotFoundException;
  4. 4 import java.io.FileOutputStream;
  5. 5 import java.io.UnsupportedEncodingException;
  6. 6 import java.util.Iterator;
  7. 7 import java.util.List;
  8. 8
  9. 9 import org.dom4j.Attribute;
  10. 10 import org.dom4j.Document;
  11. 11 import org.dom4j.DocumentException;
  12. 12 import org.dom4j.Element;
  13. 13 import org.dom4j.io.OutputFormat;
  14. 14 import org.dom4j.io.SAXReader;
  15. 15 import org.dom4j.io.XMLWriter;
  16. 16 import org.junit.After;
  17. 17 import org.junit.Before;
  18. 18 import org.junit.Test;
  19. 19
  20. 20 /*
  21. 21 * Dom4j是一个非常优秀的Java XML API,具有性能优异、功能强大和极易使用的特点。
  22. 22 */
  23. 23 public class DOM4JTest {
  24. 24 /*
  25. 25 1.读取节点的文本内容
  26. 26 2.读取属性值
  27. 27 3.添加节点
  28. 28 4.删除节点
  29. 29 5.更新节点
  30. 30 6.打印所有元素节点的名称.
  31. 31 */
  32. 32 private Document doc = null ;
  33. 33 //1.读取节点的文本内容
  34. 34 /*
  35. 35 * 读取"书"节点下,“名字”节点的文本内容
  36. 36 * DOM4J 思路:
  37. 37 * 1.获取文档的根节点.
  38. 38 Element root = document.getRootElement();
  39. 39
  40. 40 2.取得某个节点的子节点.
  41. 41 Element element=node.element(“书名");
  42. 42
  43. 43 3.取得节点的文字
  44. 44 String text=node.getText();
  45. 45
  46. 46 */
  47. 47 @Test
  48. 48 public void getNodeText() {
  49. 49 //获得跟节点
  50. 50 Element root = doc.getRootElement() ;
  51. 51 //通过跟节点获取到子节点
  52. 52 List<Element> lists = root.elements() ;
  53. 53 for (Element ele : lists) {
  54. 54 List<Element> elements = ele.elements() ;
  55. 55 for (Element element : elements) {
  56. 56 if (element.getName().equals("名字"))
  57. 57 System.out.println(element.getText());
  58. 58 }
  59. 59 }
  60. 60 }
  61. 61 //2.读取属性值
  62. 62 @Test
  63. 63 public void getAttribute () {
  64. 64 Element root = doc.getRootElement() ;
  65. 65 //通过跟节点获取到子节点
  66. 66 List<Element> lists = root.elements() ;
  67. 67 for(Element ele : lists) {
  68. 68 List<Attribute> attributes = ele.attributes();
  69. 69 for (Attribute attribute : attributes) {
  70. 70 System.out.println(attribute.getText());
  71. 71 }
  72. 72 }
  73. 73 }
  74. 74 //3.添加节点
  75. 75 /*
  76. 76 * 在“书”节点下添加“出版日期”节点。
  77. 77 */
  78. 78 @Test
  79. 79 public void addNode() throws Exception {
  80. 80 Element root = doc.getRootElement() ;
  81. 81 for (Iterator<Element> it = root.elementIterator(); it.hasNext() ;) {
  82. 82 it.next().addElement("出版日期")
  83. 83 .setText("2007年") ;
  84. 84 }
  85. 85 //写到XML文件中去。
  86. 86 writeToXML() ;
  87. 87 }
  88. 88 //4.删除节点
  89. 89 /*
  90. 90 * 删除“书”节点下,“名字”为“笑傲江湖”的“出版日期”的节点。
  91. 91 * 思路:
  92. 92 * 1、获取根元素。
  93. 93 * 2、通过根元素获取其子元素,。
  94. 94 * 3、遍历其子元素,获取子元素的"名字"元素。
  95. 95 * 4、如果"名字"元素的值符合条件。
  96. 96 * 5、则删除其兄弟元素"出版日期" 。
  97. 97 */
  98. 98 @Test
  99. 99 public void removeNode() throws Exception{
  100. 100 Element root = doc.getRootElement() ;
  101. 101 //
  102. 102 for (Iterator<Element> it = root.elementIterator(); it.hasNext() ;) {
  103. 103 Element element = it.next() ;
  104. 104 if (element.element("名字").getText().equals("笑傲江湖"))
  105. 105 element.remove(element.element("出版日期")) ;
  106. 106 }
  107. 107 writeToXML() ;
  108. 108 }
  109. 109 public void writeToXML() throws Exception{
  110. 110
  111. 111 //在写入XML文件时,要设置写入的编码格式:utf-8
  112. 112 OutputFormat format = OutputFormat.createPrettyPrint();
  113. 113 format.setEncoding("utf-8") ;
  114. 114 //最好不要用 FileWriter 写入,因为,FileWriter 写入时默认为系统设定的编码!
  115. 115 XMLWriter writer = new XMLWriter(
  116. 116 new FileOutputStream("src/cn/itheima/xml/day01/book.xml"),format );
  117. 117 writer.write( doc );
  118. 118 writer.close();
  119. 119 }
  120. 120 @Before
  121. 121 public void getDoc() throws Exception {
  122. 122 doc = new SAXReader().read( "src/cn/itheima/xml/day01/book.xml");
  123. 123 }
  124. 124 @After
  125. 125 public void setDoc() {
  126. 126 doc = null ;
  127. 127 }
  128. 128 }

九、XML约束之schema

l  XML Schema 文件自身就是一个XML文件,但它的扩展名通常为.xsd。

l  一个XML Schema文档通常称之为模式文档(约束文档),遵循这个文档书写的xml文件称之为实例文档

l  和XML文件一样,一个XML Schema文档也必须有一个根结点,但这个根结点的名称为Schema。

l  编写了一个XML Schema约束文档后,通常需要把这个文件中声明的元素绑定到一个URI地址上,在XML Schema技术中有一个专业术语来描述这个过程,即把XML Schema文档声明的元素绑定到一个名称空间上,以后XML文件就可以通过这个URI(即名称空间)来告诉解析引擎,xml文档中编写的元素来自哪里,被谁约束。

  1. 1 <?xml version="1.0" encoding="UTF-8"?>
  2. 2 <!--
  3. 3 XML Schema中,每个约束模式文档都可以被赋以一个唯一的名称空间,
  4. 4 名称空间用一个唯一的URIUniform Resource Identifier,统一资源标识符)表示
  5. 5
  6. 6 名称空间:
  7. 7 targetNamespace="http://jbelial.cnblogs.com"
  8. 8 URLhttp://jbelial.cnblogs.com 根本没有指向任何文件,只是一个分配的名字。
  9. 9
  10. 10 elementFormDefault="qualified"
  11. 11
  12. 12 elementFormDefault元素用于指定,
  13. 13 schema文档中声明的根元素及其所有子元素都属于targetNamespace所指定的名称空间。
  14. 14
  15. 15 -->
  16. 16 <schema xmlns="http://www.w3.org/2001/XMLSchema"
  17. 17 targetNamespace="http://jbelial.cnblogs.com"
  18. 18 xmlns:tns="http://www.example.org/NewXMLSchema"
  19. 19 elementFormDefault="qualified">
  20. 20 <!-- 规定根元素 -->
  21. 21 <element name='书架'>
  22. 22 <!-- 根元素下存放复杂数据类型 -->
  23. 23 <complexType>
  24. 24 <!-- 根元素下的元素的排列方式,和数目为"未绑定" -->
  25. 25 <sequence maxOccurs='unbounded'>
  26. 26 <element name='书'>
  27. 27 <complexType>
  28. 28 <sequence>
  29. 29 <!-- 约束:元素的名字,和接收类型: -->
  30. 30 <element name="名字" type="string" />
  31. 31 <element name="作者" type="string" />
  32. 32 <element name="价格" type="string" />
  33. 33 </sequence>
  34. 34 </complexType>
  35. 35 </element>
  36. 36 </sequence>
  37. 37 </complexType>
  38. 38 </element>
  39. 39 </schema>

在用Schema 约束XML 文档时,要注意一下问题:

a)你要创建的xml文档中的根标签是什么?

第一个出现的 <xs:element name='书架' > 就是根标签

b) 思考: 你使用这个根标签它来自哪个名称空间.

在schema约束文档中的 targetNamespace="http://jbelial.cnblogs.com" 就是用来说明所有跟标签绑定在哪个目标名称空间上.

c) 思考: 你要引用 schema文档它与目前名称空间的对应关系?

需要在xml文档中添加  xsi:schemaLocation="{namespace} {location}"

{namespace} 就是 : http://jbelial.cnblogs.com

{location}  : 引用的schema文档在哪里

d) 固定的写法:

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  

  1. <?xml version="1.0" encoding="UTF-8"?>
  2.  
  3. <p:书架 xmlns:p = "http://jbelial.cnblogs.com"
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5. xsi:schemaLocation="http://jbelial.cnblogs.com
  6. NewXMLSchema.xsd">
  7. <p:书>
  8. <p:名字>射雕英雄传</p:名字>
  9. <p:作者>金庸</p:作者>
  10. <p:价格>100.00</p:价格>
  11. </p:书>
  12. </p:书架>

  总结:

  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。 
 
本文来源于: http://www.cnblogs.com/jbelial/archive/2013/06/27/3159127.html

Xml语言的更多相关文章

  1. javaweb学习总结七(XML语言作用、语法)

    一:XML语言的概念以及作用 1:xml概念:extensible Markup language,可扩展行标记语言,因为html的语法比较混乱,不够严谨. 用html写的系统不好维护,所以w3c组织 ...

  2. XML语言1.简介和语法

    一.什么是XML语言? XML 指可扩展标记语言(Extensible Markup Language) Xml是独立于软件和硬件的信息传输工具. XML 是一种很像HTML的标记语言. 但xml不是 ...

  3. 四、XML语言学习(1)

    XML语言 1.XML是什么?XML是指可扩展标记语言XML是指可扩展标记语言(eXtensible Markup Language),它是一种标记语言,很类似HTML.它被设计的宗旨是传输数据,而非 ...

  4. 2.XML语言

    XML语言 常见应用: XML技术除用于 /*保存有关系的数据*/之外,它还经常作软件配置文件,以描述程序模块之间的关系. 在一个系统软件中,为提高系统的灵活性,它所启动的模块通常由其配置文件决定 例 ...

  5. XML语言基础1

    这学期选修了XML技术这门课,没有发课本,于是参考了W3school教程,整理一下上课的内容. 1.XML简介 XML是一种标记语言,很类似HTML,它不是对HTML的替代,而是对HTML的补充.在大 ...

  6. XML语言:可扩展的标记语言;

    作用:1. 解决跨语言的数据交换,C#与Javascript 语言的数据交换:. 2.XML:用于数据的存储以及传输:1.新建方法: 在解决方案资源管理器----选中网站名---右击添加新建项---- ...

  7. XML语言学习随笔

    XML和HTML都是W3C的定制的标准,XML的诞生本身是为了替代不成熟的HTML,但是因为现实的环境,XML替代HTML并未成功.之后W3C为了代码严谨性的决心,又发布了升级版的标记语言XHTML, ...

  8. 可扩展标记语言XML之二:XML语言格式规范、文档组成

    大家好,小乐又来了,好久不见!这次接着上次可扩展标记语言XML之一:XML概念,作用,示例,继续讲述XML. 一.格式良好的 xml 1.语法规范: 1).必须有 XML 文档声明: <?xml ...

  9. XML语言基础3--Schema

    1.什么是Schema XML Schema是用一套预先规定的XML元素和属性创建的,这些元素和属性定义了XML文档的结构和内容模式. XML Schema规定XML文档实例的结构和每个元素/属性的数 ...

随机推荐

  1. 【linux】Cache和Buffer的区别

  2. SQL执行效率和性能测试方法

    对于做管理系统和分析系统的程序员,复杂SQL语句是不可避免的,面对海量数据,有时候经过优化的某一条语句,可以提高执行效率和整体运行性能.如何选择SQL语句,本文提供了两种方法,分别对多条SQL进行量化 ...

  3. 多用less命令,不会输入h查看对应的详细文档

    在开发项目时候,难免要查看日志排查错误.之前只会用cat , more, less, tac, tail的简单功能, 但在实际工程中还是不够用的,至少效率很低.今天抽空看了下以下的博客,并实际进行了简 ...

  4. 验证视图状态 MAC 失败

    起因: 最近在做一个项目需要用到生成多个Html页,采用一下方法动态生成. WebRequest request = WebRequest.Create(pageurl); WebResponse r ...

  5. Perl调用外部命令的方式和区别

    主要的方式简述如下:1. system("command");使用该命令将开启一个子进程执行引号中的命令,父进程将等待子进程结束并继续执行下面的代码. 2. exec(" ...

  6. 通过xib创建View

    1 创建一个xib并使之与一个自定义的View相关联 2 在自定义的View中参考如下代码: - (id)initWithFrame:(CGRect)frame { self = [super ini ...

  7. [Android实例] Scroll原理-附ScrollView源码分析

    想象一下你拿着放大镜贴很近的看一副巨大的清明上河图, 那放大镜里可以看到的内容是很有限的, 而随着放大镜的上下左右移动,就可以看到不同的内容了 android中手机屏幕就相当于这个放大镜, 而看到的内 ...

  8. PLSQL_闪回操作5_Flashback Table

    2014-12-09 Created By BaoXinjian

  9. JAVA数据类型自动转换,与强制转换

    一.数据类型自动转换 public class Test{ public static void main(String[] args){ int a = 1; double b = 1.5; dou ...

  10. java8 JDK8 元空间

    一. JDK8 元空间概念 二. PermGen vs. Metaspace 运行时的比较     一. JDK8 元空间概念         很多开发者都在其系统中见过“java.lang.OutO ...