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

 

XML是指可扩展标记语言(eXtensible MarkupLanguage),它是一种标记语言。它被设计的宗旨是描述数据(XML),而非显示数据(HTML)。

 

目前遵循的是W3C组织于2000年发布的XML1.0规范

 

应用场景:

1、描述数据

2、作为配置文件存在

二、XML的基本语法

 

 

1、文档声明:很重要

 

在编写XML文档时,需要先使用文档声明来声明XML文档。且必须出现在文档的第一行。

作用:告知解析器,我是一个XML文档。

 

最简单的声明语法:

<?xml version="1.0"?>     中间不要加空格,后面加?号

当我们写好的一个xml文件写入内存的时候会转换为二进制保存,这个时候会查码表,记事本保存的时候是gbk,而保存的时候默认查码表时用的是utf-8,

这个时候我们就可以用encoding属性:默认是UTF-8    <?xml version="1.0" encoding="GBK"?>,这样就可以解决乱码等问题。

standlone属性:该xml文件是否独立存在。

2、元素(标签)

XML语法非常严格。不能够省略结束标签。

一个XML文档必须有且仅有一个根标签

XML中不会忽略主体内容中出现的空格和换行

元素(标签)的名称可以包含字母、数字、减号、下划线和英文句点,但必须遵守下面的一些规范:

l  严格区分大小写;<P> <p>

l  只能以字母或下划线开头;abc _abc

l  不能以xml(或XML、Xml等)开头----W3C保留日后使用;

l  名称字符之间不能有空格或制表符;ab

l  名称字符之间不能使用冒号; (有特殊用途)   

 

3、元素的属性

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

 元素中属性不允许重复

4、注释

XML中的注释语法为:<!--这是注释-->

XML声明之前不能有注释       不允许第一行写注释(不同于java)

5、CDATA区

Character Data:字符数据。

语法:

<![CDATA[

内容

]]>

作用:

被CDATA包围的内容,都是普通的文本字符串。

 

6、特殊字符

特殊字符       替代符号
&                    &
<                  <
>                  >
"                    "
'                     &apos

7、处理指令(PI:ProcessingInstruction)(了解)

XML声明就是一种处理指令

处理指令:<?指令名称 属性?>


 

1. <?xml version="1.0" encoding="GBK"?>  
2. <?xml-stylesheet type="text/css" href="main.css"?>  
3. <world>  
4.     <chinese>中国</chinese>  
5.     <america>美国</america>  
6.     <japan>小日本</japan>  
7. </world>

 

 

三、XML的约束

 

XML可以自定义。如果作为配置文件。

 

格式良好的XML文档:遵循XML语法的。

有效的XML文档:遵守约束的XML文档。

有效的XML文档必定是格式良好的,但良好的不一定是有效的。

 

1、DTD约束:(能看懂DTD即可)

a、DTD(Document Type Definition):文档类型定义

作用:约束XML的书写规范

 

注意:dtd可以写在单独的文件中,扩展名是dtd,且必须使用UTF-8编码进行保存。

 

b、XML文档中如何导入DTD约束文档(XML外部)

l  dtd文档在本地:

<!DOCTYPE 根元素 SYSTEM "dtd文件的路径">

l  dtd文档在网络上:

<!DOCTYPE 根元素 PUBLIC "dtd名称" "DTD文档的URL链接地址">

 

c、了解:也可以把DTD的内容直接写在XML文档内部。

写在XML文档内部,dtd没有编码要求。(了解)

 

 

 


1. <?xml version="1.0" encoding="GBK"?>  
2. <!DOCTYPE 书架 [  
3.     <!ELEMENT 书架 (书+)>  
4.     <!ELEMENT 书 (书名,作者,售价)>                
5.     <!ELEMENT 书名 (#PCDATA)>  
6.     <!ELEMENT 作者 (#PCDATA)>  
7.     <!ELEMENT 售价 (#PCDATA)>  
8.     <!ATTLIST 书  
9.         ISBN ID #REQUIRED  
10.         COMMENT CDATA #IMPLIED   
11. "指令汇公司"  
12.         >  
13. "指令汇公司">  
14. ]>  
15. <书架>  
16. "a" COMMENT="ddd" 出版社="指令汇公司">  
17.         <书名>Java就业培训教程</书名>  
18.         <作者>©right;</作者>  
19. 39.00元</售价>  
20.     </书>    
21. "b">  
22.         <书名>JavaScript网页开发</书名>  
23.         <作者>张孝祥</作者>  
24. 28.00元</售价>  
25.     </书>  
26. </书架>



练习:

 

 

 

1. <?xml version="1.0" encoding="GBK"?>  
2. <!DOCTYPE TVSCHEDULE [  
3.     <!ELEMENT TVSCHEDULE (CHANNEL+)>  
4.     <!ELEMENT CHANNEL (BANNER,DAY+)>  
5.     <!ELEMENT BANNER (#PCDATA)>  
6.     <!ELEMENT DAY (DATE,(HOLIDAY|PROGRAMSLOT+)+)>  
7.     <!ELEMENT HOLIDAY (#PCDATA)>  
8.     <!ELEMENT DATE (#PCDATA)>  
9.     <!ELEMENT PROGRAMSLOT (TIME,TITLE,DESCRIPTION?)>  
10.     <!ELEMENT TIME (#PCDATA)>  
11.     <!ELEMENT TITLE (#PCDATA)>   
12.     <!ELEMENT DESCRIPTION (#PCDATA)>  
13.       
14.     <!ATTLIST TVSCHEDULE NAME CDATA #REQUIRED>  
15.     <!ATTLIST CHANNEL CHAN CDATA #REQUIRED>  
16.     <!ATTLIST PROGRAMSLOT VTR CDATA #IMPLIED>  
17.     <!ATTLIST TITLE RATING CDATA #IMPLIED>  
18.     <!ATTLIST TITLE LANGUAGE CDATA #IMPLIED>  
19. ]>  
20.   
21. <TVSCHEDULE NAME="NN">  
22. "CC">  
23.          <BANNER>AAA</BANNER>  
24.          <DAY>  
25. 2015</DATE>  
26.             <PROGRAMSLOT>  
27.                 <TIME>ee</TIME>  
28.                 <TITLE>bb</TITLE>  
29.                 <DESCRIPTION>cc</DESCRIPTION>  
30.             </PROGRAMSLOT>      
31.          </DAY>  
32.     </CHANNEL>       
33. </TVSCHEDULE>


 

 

2、Schema约束(新,有替换DTD的趋势)



 



四、利用Java代码解析XML文档

1、解析方式

l  DOM:Document Object Model,文档对象模型。这种方式是W3C推荐的处理XML的一种标准方式。

缺点:必须读取整个XML文档,才能构建DOM模型,如果XML文档过大,造成资源的浪费。

优点:适合对XML中的数据进行操作(CRUD)。

l  SAX:Simple API for XML。这种方式不是官方标准,属于开源社区XML-DEV,几乎所有的XML解析器都支持它。

 

2、解析工具

JAXP:

DOM或SAX方式进行解析XML。API在JDK之中。

Dom4J:(推荐)

是开源组织推出的解析开发包。(牛,大家都在用,包括SUN公司的一些技术的实现都在用)

五、JAXP进行DOM方式解析XML基本练习

1、JAXP简介:

开发包:(JDK中)

DOM:W3C。org.w3c.dom.*   DOM规范。(接口/抽象类)

SAX:开源组织。org.xml.sax.*  SAX规范。(接口/抽象类)

JAXP:javax.xml.* 

2、利用JAXP进行DOM方式解析




1. //JAXP进行DOM方式解析的基本操作  
2. public class JaxpDemo1 {  
3.   
4. public static void main(String[] args) throws Exception {  
5. //得到解析器  
6.         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  
7.         DocumentBuilder builder = factory.newDocumentBuilder();  
8. //通过解析器就可以得到代表整个内存中XML的Document对象  
9. "src/book.xml");  
10.         test8(document);  
11.     }  
12. //  1、得到某个具体的节点内容:  刘丰  
13. private static void test1(Document document){  
14. "作者");  
15. 0);  
16.         System.out.println(authorNode.getTextContent());  
17.     }  
18. //  2、遍历所有元素节点:打印元素的名称  
19. private static void test2(Node node){  
20. //确定node的类型  
21. //方式一  
22. //      if(node.getNodeType()==Node.ELEMENT_NODE){  
23. //          //是元素  
24. //      }  
25. //方式二  
26. if(node instanceof Element){  
27. //是元素  
28.             Element e = (Element)node;  
29. //打印元素名称  
30.         }  
31. //判断有没有子节点  
32.         NodeList nl = node.getChildNodes();  
33. for(int i=0;i<nl.getLength();i++){  
34.             Node n = nl.item(i);  
35.             test2(n);  
36.         }  
37.     }  
38. //  3、修改某个元素节点的主体内容:<售价>39.00元</售价>--->10元  
39. private static void test3(Document document) throws Exception{  
40. //得到售价  
41. "售价").item(0);  
42. "10元");  
43. //更新XML文件  
44.         TransformerFactory tf = TransformerFactory.newInstance();  
45.         Transformer t = tf.newTransformer();  
46. //构建输入源:  
47. new DOMSource(document);  
48. //构建目标:  
49. new StreamResult("src/book.xml");  
50.           
51.         t.transform(source, result);  
52.     }  
53.       
54. //  4、向指定元素节点中增加子元素节点:第一本书添加子元素 <出版社>黑马程序员</出版社>  
55. private static void test4(Document document) throws Exception{  
56. //创建:<出版社>黑马程序员</出版社>  
57. "出版社");  
58. "黑马程序员");  
59. //得到书,把新节点挂上去  
60. "书").item(0);  
61.         bookNode.appendChild(e);  
62. //更新XML文件  
63.         TransformerFactory tf = TransformerFactory.newInstance();  
64.         Transformer t = tf.newTransformer();  
65. //构建输入源:  
66. new DOMSource(document);  
67. //构建目标:  
68. new StreamResult("src/book.xml");  
69.           
70.         t.transform(source, result);  
71.     }  
72. //  5、向指定元素节点上增加同级元素节点:第一本书<售价>前面添加<批发价>30</批发价>  
73. private static void test5(Document document) throws Exception{  
74. //创建新节点  
75. "批发价");  
76. "30元");  
77. //找到<售价>  
78. "售价").item(0);  
79. //父标签:调用insertBefore(新节点,参考节点);  
80.           
81.         Node bookNode = priceNode.getParentNode();  
82.         bookNode.insertBefore(e, priceNode);  
83. //更新XML文件  
84.         TransformerFactory tf = TransformerFactory.newInstance();  
85.         Transformer t = tf.newTransformer();  
86. //构建输入源:  
87. new DOMSource(document);  
88. //构建目标:  
89. new StreamResult("src/book.xml");  
90.           
91.         t.transform(source, result);  
92.     }  
93. //  6、删除指定元素节点:删除批发价  
94. private static void test6(Document document) throws Exception{  
95. "批发价").item(0);  
96.         priceNode.getParentNode().removeChild(priceNode);  
97. //更新XML文件  
98.         TransformerFactory tf = TransformerFactory.newInstance();  
99.         Transformer t = tf.newTransformer();  
100. //构建输入源:  
101. new DOMSource(document);  
102. //构建目标:  
103. new StreamResult("src/book.xml");  
104.           
105.         t.transform(source, result);  
106.     }  
107. //  7、操作XML文件属性:书籍添加一个属性:ISBN=“ABC”  
108. private static void test7(Document document) throws Exception{  
109. "书").item(0);  
110. if(bookNode instanceof Element){  
111.             Element e = (Element)bookNode;  
112. "ISBN", "ABC");  
113.         }  
114. //更新XML文件  
115.         TransformerFactory tf = TransformerFactory.newInstance();  
116.         Transformer t = tf.newTransformer();  
117. //构建输入源:  
118. new DOMSource(document);  
119. //构建目标:  
120. new StreamResult("src/book.xml");  
121.           
122.         t.transform(source, result);  
123.     }  
124. //  8、操作XML文件属性:获取ISBN=“ABC”  
125. private static void test8(Document document) throws Exception{  
126. "书").item(0);  
127. if(bookNode instanceof Element){  
128.             Element e = (Element)bookNode;  
129. "ISBN"));  
130.         }  
131.     }  
132. }




3、DOM小案例

a、建立xml文件

 


 


1. <?xml version="1.0" encoding="UTF-8" standalone="no"?><exam>  
2. "222" idcard="111">  
3.         <name>刘丰</name>  
4.         <location>湖北</location>  
5. 100</grade>  
6.     </student>  
7. <student examid="dsf" idcard="2342"><name>dsf</name><location>435</location><grade>654.0</grade></student></exam>


 

b、代码要精细。要分层。

 

DAO:com.zhilinghui.dao

VIEW:com.zhilinghui.view

JavaBean:com.zhilinghui.domain(领域)

 

c、设计JavaBean

 

 

1. public class Student {  
2. private String idcard;  
3. private String examid;  
4. private String name;  
5. private String location;  
6. private float grade;  
7.       
8. public Student(){}  
9.       
10. public Student(String idcard, String examid, String name, String location,  
11. float grade) {  
12. super();  
13. this.idcard = idcard;  
14. this.examid = examid;  
15. this.name = name;  
16. this.location = location;  
17. this.grade = grade;  
18.     }  
19. public String getIdcard() {  
20. return idcard;  
21.     }  
22. public void setIdcard(String idcard) {  
23. this.idcard = idcard;  
24.     }  
25. public String getExamid() {  
26. return examid;  
27.     }  
28. public void setExamid(String examid) {  
29. this.examid = examid;  
30.     }  
31. public String getName() {  
32. return name;  
33.     }  
34. public void setName(String name) {  
35. this.name = name;  
36.     }  
37. public String getLocation() {  
38. return location;  
39.     }  
40. public void setLocation(String location) {  
41. this.location = location;  
42.     }  
43. public float getGrade() {  
44. return grade;  
45.     }  
46. public void setGrade(float grade) {  
47. this.grade = grade;  
48.     }  
49. @Override  
50. public String toString() {  
51. return "Student [idcard=" + idcard + ", examid=" + examid + ", name="  
52. ", location=" + location + ", grade=" + grade + "]";  
53.     }  
54.       
55. }

 

 

d、开发DAO

数据访问对象

 

 

1. public class StudentDao {  
2. /** 
3.      * 保存学生信息到XML文件中 
4.      * @param student 封装要保存的信息 
5.      * @return 成功返回true,否则false 
6.      * @throws Exception  
7.      */  
8. public boolean save(Student student) throws Exception{  
9.           
10. if(student==null)  
11. throw new IllegalArgumentException("学生参数不能为null");  
12.           
13. boolean result = false;  
14. /* 
15.          * <student idcard="111" examid="222"> 
16.                 <name>刘丰</name> 
17.                 <location>湖北</location> 
18.                 <grade>100</grade> 
19.             </student> 
20.          */  
21.           
22. //得到Document  
23.             Document document = JaxpUtil.getDocument();  
24. //创建一个student元素:设置属性  
25. "student");//<student></student>  
26. "idcard", student.getIdcard());  
27. "examid", student.getExamid());//<student idcard="111" examid="222"></student>  
28. //创建name,location,grade元素,挂到student上  
29. "name");  
30. //<name>刘丰</name>  
31. "location");  
32. //<location>湖北</location>  
33. "grade");  
34. "");//<grade>100</grade>  
35.             studentE.appendChild(nameE);  
36.             studentE.appendChild(locationE);  
37.             studentE.appendChild(gradeE);  
38. //把student挂接到exam上  
39. "exam").item(0);  
40.             examNode.appendChild(studentE);  
41. //写到xml中  
42.             JaxpUtil.wirte2xml(document);  
43. //更改result的取值为true  
44. true;  
45.           
46. return result;  
47.     }  
48. /** 
49.      * 根据姓名删除信息 
50.      * @param name 
51.      * @return  成功返回true,否则false 
52.      */  
53. public boolean delete(String name){  
54. boolean result = false;  
55. try {  
56.             Document document = JaxpUtil.getDocument();  
57. //得到所有的name元素  
58. "name");  
59. //遍历:比对文本内容是否和参数一样  
60. for(int i=0;i<nl.getLength();i++){  
61. if(nl.item(i).getTextContent().equals(name)){  
62. //如果找到了一样的:爷爷干掉爸爸  
63.                     nl.item(i).getParentNode().getParentNode().removeChild(nl.item(i).getParentNode());  
64. //写回xml  
65.                     JaxpUtil.wirte2xml(document);  
66. break;  
67.                 }  
68.                   
69.             }  
70. true;  
71. catch (Exception e) {  
72. throw new RuntimeException(e);//异常转译  
73.         }  
74. return result;  
75.     }  
76. /** 
77.      * 根据准考证号查询学生信息 
78.      * @param examid 
79.      * @return 没有返回null 
80.      */  
81. public Student findByExamId(String examid){  
82. null;  
83. try {  
84.             Document document = JaxpUtil.getDocument();  
85. //得到所有的student元素  
86. "student");  
87. //遍历:比对examid属性  
88. for(int i=0;i<nl.getLength();i++){  
89.                 Element e = (Element) nl.item(i);  
90. if(e.getAttribute("examid").equals(examid)){  
91. // 找到了:创建student对象,并设置相应的值  
92. new Student();  
93. "idcard"));  
94.                     student.setExamid(examid);  
95. "name").item(0).getTextContent());  
96. "location").item(0).getTextContent());  
97. "grade").item(0).getTextContent()));  
98. break;  
99.                 }  
100.             }  
101. catch (Exception e) {  
102. throw new RuntimeException(e);//异常转译  
103.         }  
104. return student;  
105.     }  
106. }

 

e、测试DAO的功能

 

1. public class StudentDaoTest {  
2.   
3. public static void main(String[] args) {  
4. new StudentDao();  
5.           
6. //      Student student = new Student();  
7. //      student.setIdcard("333");  
8. //        
9. //      dao.save(student);  
10.           
11. //      Student s = dao.findByExamId("444");  
12. //      System.out.println(s);  
13.           
14. "阿娇"));  
15.     }  
16.   
17. }


 

f、开发界面

 

 

1. ublic class Main {  
2.   
3. public static void main(String[] args) throws Exception {  
4. new StudentDao();  
5.           
6. "a、添加用户\tb、查询成绩\tc、删除用户");  
7. "请输入操作类型:");  
8. new BufferedReader(new InputStreamReader(System.in));  
9. //读取用户输入的a|b|c  
10. if("a".equals(op)){  
11. //添加  
12. "请输入学生姓名:");  
13.             String name = br.readLine();  
14. "请输入学生准考证号:");  
15.             String examid = br.readLine();  
16. "请输入学生身份证号:");  
17.             String idcard = br.readLine();  
18. "请输入学生所在地:");  
19.             String location = br.readLine();  
20. "请输入学生成绩:");  
21.             String grade = br.readLine();  
22.               
23. //封装数据  
24. new Student(idcard, examid, name, location, Float.parseFloat(grade));  
25. //调用dao  
26. boolean b = dao.save(student);  
27. if(b){  
28. "------添加成功------");  
29. else{  
30. "------服务器忙------");  
31.             }  
32. else if("b".equals(op)){  
33. //查询  
34. "请输入学生准考证号:");  
35.             String examid = br.readLine();  
36.             Student s = dao.findByExamId(examid);  
37. if(s==null)  
38. "------查无此人------");  
39. else  
40.                 System.out.println(s);  
41. else if("c".equals(op)){  
42. //删除  
43. "请输入要删除的学生姓名:");  
44.             String name = br.readLine();  
45. boolean b = dao.delete(name);  
46. if(b){  
47. "------删除成功------");  
48. else{  
49. "------服务器忙------");  
50.             }  
51. else{  
52. "你傻呀,输错了");  
53.         }  
54.     }  
55.   
56. }



sax解析原理

在使用 DOM 解析 XML 文档时,需要读取整个 XML 文档,在内存中构架代表整个 DOM 树的Doucment对象,从而再对XML文档进行操作。此种情况下,如果 XML 文档特别大,就会消耗计算机的大量内存,并且容易导致内存溢出。

SAX解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才会文档进行操作。


SAX采用事件处理的方式解析XML文件,利用 SAX 解析 XML 文档,涉及两个部分:解析器和事件处理器: 解析器可以使用JAXP的API创建,创建出SAX解析器后,就可以指定解析器去解析某个XML文档。 解析器采用SAX方式在解析某个XML文档时,它只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器。 事件处理器由程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松地得到sax解析器解析到的数据,从而可以决定如何对数据进行处理

基本解析操作

//1解析器
    SAXParser parse = SAXParserFactory.newInstance().newSAXParser();
    //2获取xml读取器
    XMLReader reader = parse.getXMLReader();
    //3注册内容处理器
    reader.setContentHandler(new ContentHandler1());
    //4读取xml文档
    reader.parse("src/book.xml");

封装读取书

封装到BOOK.java

public class sax3 {

//封装读取书
    public static void main(String[] args) throws Exception {

        SAXParser parse=SAXParserFactory.newInstance().newSAXParser();

        XMLReader reader=parse.getXMLReader();

        final List<Book> books=new ArrayList<Book>();
        reader.setContentHandler(new DefaultHandler(){

           private Book b=null;
           private String currentTagName=null;
            public void startElement(String uri, String localName,
                    String qName, Attributes attributes) throws SAXException {

                if("书".equals(qName)){
                    b=new Book();
                }
                currentTagName=qName;
            }

            public void endElement(String uri, String localName, String qName)
                    throws SAXException {
                if("书".equals(qName)){
                    books.add(b);
                    b=null;
                }
                currentTagName=null;
            }
            @Override
            public void characters(char[] ch, int start, int length)
                    throws SAXException {
                if("书名".equals(currentTagName)){
                    b.setName(new String(ch,start,length));
                }
                if("作者".equals(currentTagName)){
                    b.setAuthor(new String(ch,start,length));
                }
                if("售价".equals(currentTagName)){
                    b.setPrice(new String(ch,start,length));
                }
            }
        });
        reader.parse("src/book.xml");

        for(Book book:books)
            System.out.println(book);
    }
}

dom4j解析原理

Dom4j是一个简单、灵活的开放源代码的库。Dom4j是由早期开发JDOM的人分离出来而后独立开发的。与JDOM不同的是,dom4j使用接口和抽象基类,虽然Dom4j的API相对要复杂一些,但它提供了比JDOM更好的灵活性。 Dom4j是一个非常优秀的Java XML API,具有性能优异、功能强大和极易使用的特点。现在很多软件采用的Dom4j,例如Hibernate,包括sun公司自己的JAXM也用了Dom4j。 使用Dom4j开发,需下载dom4j相应的jar文件。


1、基本练习 a、拷贝jar包: 把dom4j-1.6.1.jar加入到你的classpath中 b、基本操作

// 1、得到某个具体的节点内容:jinpingmei

@Test
public void test1() throws Exception{
    SAXReader reader = new SAXReader();
    Document document = reader.read("src/book.xml");
    //首先要得到根元素
    Element root = document.getRootElement();
    List<Element> bookElements = root.elements();
//      Element bookName = (Element) bookElements.get(0).elements().get(0);
//      System.out.println(bookName.getText());
    System.out.println(bookElements.get(0).elementText("书名"));
}

// 2、遍历所有元素节点:名称

@Test
public void test2()throws Exception{
    SAXReader reader = new SAXReader();
    Document document = reader.read("src/book.xml");
    //首先要得到根元素
    Element root = document.getRootElement();
    treeWalk(root);
}
public void treeWalk(Element rootElement){//递归
    System.out.println(rootElement.getName());
    int nodeCount = rootElement.nodeCount();//子节点的数量
    for(int i=0;i<nodeCount;i++){
        Node node = rootElement.node(i);//得到一个子节点
        if(node instanceof Element){
            treeWalk((Element)node);
        }
    }
}

// 3、修改某个元素节点的主体内容:<售价>10元---20

@Test
public void test3()throws Exception{
    SAXReader reader = new SAXReader();
    Document document = reader.read("src/book.xml");
    //首先要得到根元素
    Element root = document.getRootElement();
    //得售价
    Element priceElement = root.element("书").element("售价");
    priceElement.setText("21元");
    //写回XML文档
//      OutputFormat format = OutputFormat.createCompactFormat();//去除空格回车换行,适合运行期间
    OutputFormat format = OutputFormat.createPrettyPrint();//漂亮的格式 默认编码是UTF-8
    XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"), format);
    writer.write(document);
    writer.close();
}

// 4、向指定元素节点中增加子元素节点:<出版社>黑马程序员

@Test
public void test4()throws Exception{
    SAXReader reader = new SAXReader();
    Document document = reader.read("src/book.xml");
    //首先要得到根元素
    Element root = document.getRootElement();
    //得售价
    Element bookElement = root.element("书");
    //创建新元素
    Element publisherElement = DocumentHelper.createElement("出版社");
    publisherElement.setText("黑马程序员");

    bookElement.add(publisherElement);
    //写回XML文档
//      OutputFormat format = OutputFormat.createCompactFormat();//去除空格回车换行,适合运行期间
    OutputFormat format = OutputFormat.createPrettyPrint();//漂亮的格式 默认编码是UTF-8
    XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"), format);
    writer.write(document);
    writer.close();
}

// 5、向指定元素节点上增加同级元素节点:<售价>21元 添加<批发价>

@Test
public void test5()throws Exception{
    SAXReader reader = new SAXReader();
    Document document = reader.read("src/book.xml");
    //首先要得到根元素
    Element root = document.getRootElement();
    //得售价
    Element bookElement = root.element("书");
    //创建新元素
    Element priceElement = DocumentHelper.createElement("批发价");
    priceElement.setText("30元");

    List<Element> bookChildren = bookElement.elements();//得到书的子元素
    bookChildren.add(2, priceElement);

    //写回XML文档
//      OutputFormat format = OutputFormat.createCompactFormat();//去除空格回车换行,适合运行期间
    OutputFormat format = OutputFormat.createPrettyPrint();//漂亮的格式 默认编码是UTF-8
    XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"), format);
    writer.write(document);
    writer.close();
}

// 6、删除指定元素节点:批发价

@Test
public void test6()throws Exception{
    SAXReader reader = new SAXReader();
    Document document = reader.read("src/book.xml");
    //首先要得到根元素
    Element root = document.getRootElement();
    Element priceElement = root.element("书").element("批发价");

    priceElement.getParent().remove(priceElement);

    //写回XML文档
//      OutputFormat format = OutputFormat.createCompactFormat();//去除空格回车换行,适合运行期间
    OutputFormat format = OutputFormat.createPrettyPrint();//漂亮的格式 默认编码是UTF-8
    XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"), format);
    writer.write(document);
    writer.close();
}

// 7、操作XML文件属性

@Test
public void test7()throws Exception{
    SAXReader reader = new SAXReader();
    Document document = reader.read("src/book.xml");
    //首先要得到根元素
    Element root = document.getRootElement();
    Element book = root.element("书");
    System.out.println(book.attributeValue("ISBN"));
}
@Test
public void test8()throws Exception{
    SAXReader reader = new SAXReader();
    Document document = reader.read("src/book.xml");
    //首先要得到根元素
    Element root = document.getRootElement();
    Element book = root.element("书");
    book.addAttribute("A", "B");
    //写回XML文档
//      OutputFormat format = OutputFormat.createCompactFormat();//去除空格回车换行,适合运行期间
    OutputFormat format = OutputFormat.createPrettyPrint();//漂亮的格式 默认编码是UTF-8
    XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"), format);
    writer.write(document);
    writer.close();
}

Xpath

XPath是一个努力为XSL转换XSLT和XPointer [ ] [ ]之间共享一个共同的XPointer功能语法和语义的结果。它的主要目的是解决一个XML XML文档部分[ ]。为了支持这一功能,还提供用于处理字符串的基本设施、数字和布尔值。XPath使用一个紧凑的、非XML语法方便使用在uri和XML属性值的XPath。XPath操作基于XML文档的逻辑结构,而不是其表面的语法。Xpath的名字来自其使用的符号在URL路径通过一个XML文档的层次结构导航。 除了用于定位,XPath还设计有一个真子集,可用于匹配(测试一个节点是否符合一个模式);使用XPath进行XSLT。

XPath模型的XML文档的节点树。有不同类型的节点,包括元素节点、属性节点和文本节点。XPath定义了一个方法来计算每个节点类型字符串值。某些类型的节点也有名字。XPath完全支持XML命名空间的XML名称] [。因此,一个节点的名称被建模为一个地方的部分和一个可能的空命名空间URI;这就是所谓的扩展名。在[ 5数据模型]中详细描述了数据模型。

@Test//Xpath
public void test11() throws Exception{
    SAXReader reader = new SAXReader();
    Document document = reader.read("src/book.xml");
    Node n = document.selectSingleNode("//书[1]/书名");
    System.out.println(n.getText());
}
@Test//Xpath:第一本书的ISBN的值
public void test12() throws Exception{
    SAXReader reader = new SAXReader();
    Document document = reader.read("src/book.xml");
    Node n = document.selectSingleNode("//书[1]");
    System.out.println(n.valueOf("@ISBN"));
}

xml约束之schema

XML Schema 也是一种用于定义和描述 XML 文档结构与内容的模式语言,其出现是为了克服 DTD 的局限性

XML Schema 文件自身就是一个XML文件,但它的扩展名通常为.xsd。支持名称空间。 一个XML Schema文档通常称之为模式文档(约束文档),遵循这个文档书写的xml文件称之为实例文档。

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

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

学习目标:不需要我们编写xsd 重点:根据xsd编写出xml文档。 难点:在xml中引入xsd约束

基本操作步骤:

a、根据xsd文件,找到根元素

<?xml version="1.0" encoding="UTF-8"?>
<书架>

</书架>

b、根元素来在哪个名称空间 使用xmlns关键字来声明名称空间。

<?xml version="1.0" encoding="UTF-8"?>
<tf:书架 xmlns:tf="http://www.zhilinghui.com">

</tf:书架>

c、名称空间和哪个xsd文件对应

<?xml version="1.0" encoding="UTF-8"?>
<tf:书架 xmlns:tf="http://www.zhilinghui.com"
    schemaLocation="http://www.zhilinghui.com book.xsd">

</tf:书架>

d、schemaLocation来自一个标准的名称空间:固定写法

<?xml version="1.0" encoding="UTF-8"?>
<tf:书架 xmlns:tf="http://www.zhilinghui.com"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.zhilinghui.com book.xsd">

</tf:书架>
==============================================================================================================================
DOM4J的另一种深度解读:

DOM4J

 

    与利用DOM、SAX、JAXP机制来解析xml相比,DOM4J 表现更优秀,具有性能优异、功能强大和极端易用使用的特点,只要懂得DOM基本概念,就可以通过dom4j的api文档来解析xml。dom4j是一套开源的api。实际项目中,往往选择dom4j来作为解析xml的利器。

 

先来看看dom4j中对应XML的DOM树建立的继承关系

 

java两个文档属性对比系统 java比对两个xml 的内容_人工智能

 

针对于XML标准定义,对应于图2-1列出的内容,dom4j提供了以下实现:

 

java两个文档属性对比系统 java比对两个xml 的内容_java两个文档属性对比系统_02

 

同时,dom4j的NodeType枚举实现了XML规范中定义的node类型。如此可以在遍历xml文档的时候通过常量来判断节点类型了。

 

常用API

 

class org.dom4j.io.SAXReader

 

  • read  提供多种读取xml文件的方式,返回一个Domcument对象

 

interface org.dom4j.Document

 

  • iterator  使用此法获取node
  • getRootElement  获取根节点

 

interface org.dom4j.Node

 

  • getName  获取node名字,例如获取根节点名称为bookstore
  • getNodeType  获取node类型常量值,例如获取到bookstore类型为1——Element
  • getNodeTypeName  获取node类型名称,例如获取到的bookstore类型名称为Element

 

interface org.dom4j.Element

 

  • attributes  返回该元素的属性列表
  • attributeValue  根据传入的属性名获取属性值
  • elementIterator  返回包含子元素的迭代器
  • elements  返回包含子元素的列表

 

interface org.dom4j.Attribute

 

  • getName  获取属性名
  • getValue  获取属性值

 

interface org.dom4j.Text

 

  • getText  获取Text节点值

 

interface org.dom4j.CDATA

 

  • getText  获取CDATA Section值

 

interface org.dom4j.Comment

 

  • getText  获取注释 

 

 

实例一:

1 //先加入dom4j.jar包   2 import java.util.HashMap;  3 import java.util.Iterator;
  4 import java.util.Map;
  5 
  6 import org.dom4j.Document;
  7 import org.dom4j.DocumentException;
  8 import org.dom4j.DocumentHelper;
  9 import org.dom4j.Element;
 10 
 11 /**   
 12 * @Title: TestDom4j.java
 13 * @Package 
 14 * @Description: 解析xml字符串
 15 * @author 无处不在
 16 * @date 2012-11-20 下午05:14:05
 17 * @version V1.0   
 18 */
 19 public class TestDom4j {
 20 
 21     public void readStringXml(String xml) {
 22         Document doc = null;
 23         try {
 24 
 25             // 读取并解析XML文档
 26             // SAXReader就是一个管道,用一个流的方式,把xml文件读出来
 27             // 
 28             // SAXReader reader = new SAXReader(); //User.hbm.xml表示你要解析的xml文档
 29             // Document document = reader.read(new File("User.hbm.xml"));
 30             // 下面的是通过解析xml字符串的
 31             doc = DocumentHelper.parseText(xml); // 将字符串转为XML
 32 
 33             Element rootElt = doc.getRootElement(); // 获取根节点
 34             System.out.println("根节点:" + rootElt.getName()); // 拿到根节点的名称
 35 
 36             Iterator iter = rootElt.elementIterator("head"); // 获取根节点下的子节点head
 37 
 38             // 遍历head节点
 39             while (iter.hasNext()) {
 40 
 41                 Element recordEle = (Element) iter.next();
 42                 String title = recordEle.elementTextTrim("title"); // 拿到head节点下的子节点title值
 43                 System.out.println("title:" + title);
 44 
 45                 Iterator iters = recordEle.elementIterator("script"); // 获取子节点head下的子节点script
 46 
 47                 // 遍历Header节点下的Response节点
 48                 while (iters.hasNext()) {
 49 
 50                     Element itemEle = (Element) iters.next();
 51 
 52                     String username = itemEle.elementTextTrim("username"); // 拿到head下的子节点script下的字节点username的值
 53                     String password = itemEle.elementTextTrim("password");
 54 
 55                     System.out.println("username:" + username);
 56                     System.out.println("password:" + password);
 57                 }
 58             }
 59             Iterator iterss = rootElt.elementIterator("body"); ///获取根节点下的子节点body
 60             // 遍历body节点
 61             while (iterss.hasNext()) {
 62 
 63                 Element recordEless = (Element) iterss.next();
 64                 String result = recordEless.elementTextTrim("result"); // 拿到body节点下的子节点result值
 65                 System.out.println("result:" + result);
 66 
 67                 Iterator itersElIterator = recordEless.elementIterator("form"); // 获取子节点body下的子节点form
 68                 // 遍历Header节点下的Response节点
 69                 while (itersElIterator.hasNext()) {
 70 
 71                     Element itemEle = (Element) itersElIterator.next();
 72 
 73                     String banlce = itemEle.elementTextTrim("banlce"); // 拿到body下的子节点form下的字节点banlce的值
 74                     String subID = itemEle.elementTextTrim("subID");
 75 
 76                     System.out.println("banlce:" + banlce);
 77                     System.out.println("subID:" + subID);
 78                 }
 79             }
 80         } catch (DocumentException e) {
 81             e.printStackTrace();
 82 
 83         } catch (Exception e) {
 84             e.printStackTrace();
 85 
 86         }
 87     }
 88 
 89     /**
 90      * @description 将xml字符串转换成map
 91      * @param xml
 92      * @return Map
 93      */
 94     public static Map readStringXmlOut(String xml) {
 95         Map map = new HashMap();
 96         Document doc = null;
 97         try {
 98             // 将字符串转为XML
 99             doc = DocumentHelper.parseText(xml); 
100             // 获取根节点
101             Element rootElt = doc.getRootElement(); 
102             // 拿到根节点的名称
103             System.out.println("根节点:" + rootElt.getName()); 
104 
105             // 获取根节点下的子节点head
106             Iterator iter = rootElt.elementIterator("head"); 
107             // 遍历head节点
108             while (iter.hasNext()) {
109 
110                 Element recordEle = (Element) iter.next();
111                 // 拿到head节点下的子节点title值
112                 String title = recordEle.elementTextTrim("title"); 
113                 System.out.println("title:" + title);
114                 map.put("title", title);
115                 // 获取子节点head下的子节点script
116                 Iterator iters = recordEle.elementIterator("script"); 
117                 // 遍历Header节点下的Response节点
118                 while (iters.hasNext()) {
119                     Element itemEle = (Element) iters.next();
120                     // 拿到head下的子节点script下的字节点username的值
121                     String username = itemEle.elementTextTrim("username"); 
122                     String password = itemEle.elementTextTrim("password");
123 
124                     System.out.println("username:" + username);
125                     System.out.println("password:" + password);
126                     map.put("username", username);
127                     map.put("password", password);
128                 }
129             }
130 
131             //获取根节点下的子节点body
132             Iterator iterss = rootElt.elementIterator("body"); 
133             // 遍历body节点
134             while (iterss.hasNext()) {
135                 Element recordEless = (Element) iterss.next();
136                 // 拿到body节点下的子节点result值
137                 String result = recordEless.elementTextTrim("result"); 
138                 System.out.println("result:" + result);
139                 // 获取子节点body下的子节点form
140                 Iterator itersElIterator = recordEless.elementIterator("form"); 
141                 // 遍历Header节点下的Response节点
142                 while (itersElIterator.hasNext()) {
143                     Element itemEle = (Element) itersElIterator.next();
144                     // 拿到body下的子节点form下的字节点banlce的值
145                     String banlce = itemEle.elementTextTrim("banlce"); 
146                     String subID = itemEle.elementTextTrim("subID");
147 
148                     System.out.println("banlce:" + banlce);
149                     System.out.println("subID:" + subID);
150                     map.put("result", result);
151                     map.put("banlce", banlce);
152                     map.put("subID", subID);
153                 }
154             }
155         } catch (DocumentException e) {
156             e.printStackTrace();
157         } catch (Exception e) {
158             e.printStackTrace();
159         }
160         return map;
161     }
162 
163     public static void main(String[] args) {
164 
165         // 下面是需要解析的xml字符串例子
166         String xmlString = "<html>" + "<head>" + "<title>dom4j解析一个例子</title>"
167                 + "<script>" + "<username>yangrong</username>"
168                 + "<password>123456</password>" + "</script>" + "</head>"
169                 + "<body>" + "<result>0</result>" + "<form>"
170                 + "<banlce>1000</banlce>" + "<subID>36242519880716</subID>"
171                 + "</form>" + "</body>" + "</html>";
172 
173         /*
174          * Test2 test = new Test2(); test.readStringXml(xmlString);
175          */
176         Map map = readStringXmlOut(xmlString);
177         Iterator iters = map.keySet().iterator();
178         while (iters.hasNext()) {
179             String key = iters.next().toString(); // 拿到键
180             String val = map.get(key).toString(); // 拿到值
181             System.out.println(key + "=" + val);
182         }
183     }
184 
185 }

  

实例二:

1 /** 2  * 解析包含有DB连接信息的XML文件 3  * 格式必须符合如下规范:
 4  * 1. 最多三级,每级的node名称自定义;
 5  * 2. 二级节点支持节点属性,属性将被视作子节点;
 6  * 3. CDATA必须包含在节点中,不能单独出现。
 7  *
 8  * 示例1——三级显示:
 9  * <db-connections>
10  *         <connection>
11  *            <name>DBTest</name>
12  *            <jndi></jndi>
13  *            <url>
14  *                <![CDATA[jdbc:mysql://localhost:3306/db_test?useUnicode=true&characterEncoding=UTF8]]>
15  *             </url>
16  *            <driver>org.gjt.mm.mysql.Driver</driver>
17  *             <user>test</user>
18  *            <password>test2012</password>
19  *            <max-active>10</max-active>
20  *            <max-idle>10</max-idle>
21  *            <min-idle>2</min-idle>
22  *            <max-wait>10</max-wait>
23  *            <validation-query>SELECT 1+1</validation-query>
24  *         </connection>
25  * </db-connections>
26  *
27  * 示例2——节点属性:
28  * <bookstore>
29  *         <book category="cooking">
30  *            <title lang="en">Everyday Italian</title>
31  *            <author>Giada De Laurentiis</author>
32  *            <year>2005</year>
33  *            <price>30.00</price>
34  *         </book>
35  *
36  *         <book category="children" title="Harry Potter" author="J K. Rowling" year="2005" price="$29.9"/>
37  * </bookstore>
38  *
39  * @param configFile
40  * @return
41  * @throws Exception
42  */
43 public static List<Map<String, String>> parseDBXML(String configFile) throws Exception {
44     List<Map<String, String>> dbConnections = new ArrayList<Map<String, String>>();
45     InputStream is = Parser.class.getResourceAsStream(configFile);
46     SAXReader saxReader = new SAXReader();
47     Document document = saxReader.read(is);
48     Element connections = document.getRootElement();
49 
50     Iterator<Element> rootIter = connections.elementIterator();
51     while (rootIter.hasNext()) {
52         Element connection = rootIter.next();
53         Iterator<Element> childIter = connection.elementIterator();
54         Map<String, String> connectionInfo = new HashMap<String, String>();
55         List<Attribute> attributes = connection.attributes();
56         for (int i = 0; i < attributes.size(); ++i) { // 添加节点属性
57             connectionInfo.put(attributes.get(i).getName(), attributes.get(i).getValue());
58         }
59         while (childIter.hasNext()) { // 添加子节点
60             Element attr = childIter.next();
61             connectionInfo.put(attr.getName().trim(), attr.getText().trim());
62         }
63         dbConnections.add(connectionInfo);
64     }
65 
66     return dbConnections;
67 }