XML即Extensible Markup Language,可擴展標記語言,主要的應用有三方面:
1.存儲數據,這個沒什么好說的
2.傳輸數據,純文本文件,不存在轉換格式的麻煩
3.軟件配置,比如今后學的配置tomcat虛擬目錄映射等就用到了
那么直奔主題:
一、XML文件結構
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<!DOCTYPE root SYSTEM "path.dtd">
<root>
.......
</root>
version是告訴瀏覽器使用什么版本的XML解析器,encoding是來設置文件的編碼,standalone表明XML是否引入了其他非XML文件如css、dtd文件
<!DOCTYPE ...>為內部或外部引入的DTD文件,DTD為Document Type Definition,用來定義合法的XML文件結構
<root></root>為XML的根節點,只能有一個,里面存儲自定義的標簽元素
1.標簽的書寫規范
XML語法嚴格,對大小寫敏感,不可間接嵌套;標簽名不能以數字、_下劃線、xml開頭;標簽名中不能出現空格、:
在XML中<,>,&,“,及逗號都是特殊字符,如要在標簽內部使用需要使用內部實體代替
<label attr=""></label>←跟html書寫很像不再贅述
<?xml version="1.1" encoding="UTF-8"?>
<studentList>
<student id="A01" class="A">
<name>小明</name>
<age>19</age>
<gender>man</gender>
<score>
<subject name="Advanced Mathematics">90</>
<subject name="College English">85</>
<subject name="C++Programming">88</>
</score>
</student>
<student id="A02" class="B">
<name>小紅</name>
<age>20</age>
<gender>woman</gender>
<score>
<subject name="Data Structure">80</subject>
<subject name="JavaProgramming">90</subject>
</score>
</student>
</studentList>
一個簡單的XML文件
2.CDATA區
所有 XML 文檔中的文本均會被解析器解析,只有 CDATA(Unparsed Character Data) 區段中的文本會被解析器忽略。
作用:因為XML中有特殊字符的存在(< > &等),所以我們在用XML傳送JavaScript代碼或者其他數據時,只要將內容聲明在CDATA區中就不會被瀏覽器解析,出錯。
使用方法:
<![CDATA[your data]]>
3.處理指令
<?xml-stylesheet type="text/css" href="path.css"?>
<?xml-stylesheet type="text/xsl href="path.xsl"?>
↑沒什么好說的
二、DTD語法
在XML文件內使用DTD格式為:
<!DOCTYPE 根標簽名稱 [
<!ELEMENT>
<!ATTLIST>
<!ENTITY>
]>
在外部引入為:
<!DOCTYPE 根標簽名字 SYSTEM ”path.dtd“>
1.<!ELEMENT>定義元素
書寫格式:<!ELEMENT 標簽名 類別/(內容)>
其中類別值有EMPTY、ANY
()內填寫子標簽數量、順序描述,或對文本內容描述(#PCDATA)
對于子標簽數量,有+、*、?、|修飾,類似正則表達式不再贅述
對于順序描述,(name,age,gender,score)即表達了子標簽必須以此順序定義
PCDATA為Parsed Character Data可解析的字符內容,當標簽內只有文本內容(不含嵌套的標簽時)可以使用(#PCDATA)
EMPTY,ANY表示標簽內容可以是空的,空的或純文本
對上述XML文件進行定義
<!DOCTYPE studentList [
<!ELEMENT studenList (student+)>
<!ELEMENT student (name,(age?),(gender?),(score?))> //名字最重要,其他信息可有可無
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT gender (#PCDATA)>
<!ELEMENT score (subject*)>
<!ELEMENT subject ANY> //這樣就表示支持<s></s>、<s>100</s>這兩種寫法
]>
DTD定義中必須將所有標簽元素全部定義完、屬性也是一樣的,上述DTD定義不完整,還缺少屬性定義
2.<!ATTLIST>定義屬性
<!ATTLIST 標簽名 屬性名 屬性類型 屬性約束>
屬性類型有
CDATA 屬性值是字符數據
ID 屬性值是唯一的一個以英文字母開頭的ID值
IDREF 屬性值與同一標簽內ID型屬性的值相等
(en1|en2...) 屬性值是枚舉中的一個
<!ATTLIST label name ID #REQUIRED nickname IDREF #REQUIRED>
則說明屬性nickname的值必須與name屬性的值相同
屬性約束有
“ ” 如果屬性為空,則默認等于“ ”內值
#REQUIRED 屬性值是必需要填寫的,不能為空
#IMPLIED 不必需,可空
#FIXED “ ” 屬性值必填,必須與“ ”內值一樣
<!ATTLIST student id ID #REQUIRED class (A|B) #REQUIRED>
id屬性值為必填的ID類型,class屬性值為必填的、值只能為A或B的枚舉類型
<!ATTLIST subject name CDATA #IMPLIED>
name屬性的值為選填的字符類型
所以對開頭XML的完整DTD定義為
<!DOCTYPE root [
<!ELEMENT>
...
<!ATTLIST>
...
]>
3.<!ENTITY>定義實體
類似c語言#define
引用實體
<!ENTITY d "doctor">
<occupation>&d;</occupation> → 即為<occupation>doctor</occupation>
使用方法: &+實體+;
預定義好的引用實體:
& \& < \< > \> " \" ' \'
參數實體
<!ENTITY % order "name,age,gender,score">
顧名思義,參數實體只能用來替換DTD定義標簽中的參數
<!ELEMENT student (%order;)> → <!ELEMENT student (name,age,gender,score)>
參數實體定義位置必須位于使用之前,參數實體無法在內部DTD使用,只能在外部使用,一個XML文件只能有一個DTD文件約束
三、使用java解析XML
java不像js一樣提供對XML文檔的原生支持,我們通過使用dom4j的API來對XML進行操作
0.提前做好的準備工作
寫好一份XML文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE studentList SYSTEM "Demo.dtd">
<studentList>
<student id="A01" class="A">
<name>小明</name>
<age>19</age>
<gender>man</gender>
<score>
<averageScore>84.8</averageScore>
<subject name="AdvancedMathematics">82</subject>
<subject name="CollegeEnglish">86</subject>
<subject name="C++">94</subject>
<subject name="DataStructure">77</subject>
<subject name="Java">85</subject>
</score>
<identity minority="">
<position>monitor</position>
<politicalStatus>communist youth league member</politicalStatus>
</identity>
</student>
<student id="A02" class="B">
<name>小紅</name>
<age>20</age>
<gender>woman</gender>
<score>
<averageScore>91</averageScore>
<subject name="AdvencedMathematics">97</subject>
<subject name="CollegeEnglish">89</subject>
<subject name="C++">82</subject>
<subject name="DataStructure">95</subject>
<subject name="Java">92</subject>
</score>
<identity minority="壯族">
<position></position>
<politicalStatus>party member</politicalStatus>
</identity>
</student>
</studentList>
1.讀取XML文件
SAXReader saxReader = new SAXReader();
Document xml = saxReader.read(XMLparse.class.getClassLoader().getResource("Demo.xml"));
//使用類加載器可以避免復雜的路徑。。。其實也沒方便多少
//saxReader.read(new File("C:\Users\15421\eclipse-workspace\XMLparse\src\Demo.xml"))
System.out.println(xml==null?"加載失敗":"加載成功");
2.實現增功能
/*--------創建小剛同學的XML結構--------*/
Element rootElement = xml.getRootElement();
System.out.println(rootElement.getName());
Element newElement = DocumentHelper.createElement("student");
newElement.addAttribute("id", "A03");
newElement.addAttribute("class", "A");
newElement.addElement("name").setText("小剛");
System.out.println("id: "+newElement.attributeValue("id")+" class: "+newElement.attributeValue("class")+" name: "+newElement.element("name").getText());
/*----------獲取節點列表,在小紅前添加小剛---------*/
List<Element> list = rootElement.elements("student");
Iterator<Element> iterator = list.iterator(); //使用集合類的迭代器iterator進行遍歷
int index = 0;
while(iterator.hasNext()) {
Element element = iterator.next();
if(element.elementText("name").equals("小紅")) {
System.out.println("小紅在第"+index+"個上");
list.add(index,newElement); //插入小剛
break; //注意,在某些情況下不break會造成無限循環的后果(因為list已經變化了),這里倒沒有影響
}
++index;
}
System.out.println("添加后:");
iterator = list.iterator(); //迭代器用完了就要換一個(不管原來List變化沒有),這里重新加載了一遍
while(iterator.hasNext()) {
System.out.println(iterator.next().elementText("name"));
}
3.實現刪功能
iterator = list.iterator();
int index = 0;
while(iterator.hasNext()) {
if(iterator.next().elementText("name").equals("小剛")) {
list.remove(index);
break;
}
++index;
}
iterator = list.iterator();
System.out.println("刪除后:");
for(Element element:list){
System.out.println(element.elementText("name"));
}
4.實現查、改功能
/*--------------查找----------------*/
//使用xpath快速定位標簽
System.out.println("Java成績:");
String xpath = "http://subject[@name='Java']"; //在全體人員中查找name屬性為Java的subject標簽
List<Node> subjects = xml.selectNodes(xpath);
for(Node node:subjects) {
System.out.println(node.getText());
}
//使用迭代器遍歷(霧) 你喜歡就好
iterator = list.iterator();
for(;iterator.hasNext();) {
List<Element> list2 = iterator.next().elements();
Iterator<Element> iterator2 = list2.iterator();
for(;iterator2.hasNext();) {
Element element = iterator2.next();
if(element.getName().equals("score")) {
List<Element> list3 = element.elements();
Iterator<Element> iterator3 = list3.iterator();
for(;iterator3.hasNext();) {
Element element2 = iterator3.next();
if(element2.getName().equals("subject")&&element2.attributeValue("name").equals("Java")) {
System.out.println(element2.getText());
}
}
}
}
}
/*-------------修改標簽屬性值/內容-------------*/
//1.修改小明少數民族為苗族
//2.修改全體人員職位為student
xpath = "student[@id='A01']//identity";
Element identity = (Element)xml.selectSingleNode(xpath);
identity.addAttribute("minority", "苗族");
//↑這里失敗了,原因是select方法返回的是Node類型,強制轉換后雖然能使用addAttribute方法但是報錯空指針
//以后再研究吧
xpath = "http://position";
List<Node> position_list = xml.selectNodes(xpath);
for(Node node:position_list) {
node.setText("student");
}
5.向硬盤中輸出修改的XML
OutputStream os = new FileOutputStream(new File("C:\\Users\\15421\\Desktop\\demo_out.xml"));
\\是轉義符哦
OutputFormat of = OutputFormat.createPrettyPrint();
//createCompactPrint 將去掉所有縮進
XMLWriter xml_out = new XMLWriter(os,of);
xml_out.write(xml);
xml_out.close();
小結
最近學的好雜啊。。。快爆炸了,我要寫物理實驗了。