XML 可擴展的標記語言
XML 通用的數據格式標準
在沒有XML標準時代
1 數據可以任意格式存儲:二進制,文本格式
2 數據的交換和分享出現麻煩
XML 是一種通用的標準格式
1 XML 數據格式標準
2 可以用於文件的格式:XML 格式的文件稱爲XML 文件
3 XML文件本身是文本文件,非常便於編輯和處理
任何的文本編輯器都可以處理XML文件。
在解析xml之前要導入相應的jar包;
XML 的語法結構:
<?xml version="1.0" encoding="UTF-8"?>
<!-- <?xml> 處理節點。處理指令, 建議在XML中第一行使用!處理節點之前不能用註釋! -->
<!-- 註釋節點 Comment Node -->
<!-- 標記(標籤)tag:<標記名> 稱爲標記
標記有3種: <標記名>開始標記, </標記名>結束標記, <標記名/>稱爲自結束標記
XML 中標記必須配對出現 有開始標記一定有結束標記
<標記名/>自結束標記是 無內容的<標記名></標記名>簡寫形式
<標記名/> == <標記名></標記名> -->
<!-- 元素(Element): 開始標記+內容+結束標記 的整體稱爲元素
如: <book>老夫子</book> 稱爲元素
元素的內容:
可以文本節點
可以是其他元素
可以是文本和元素的混合體
可以是元素的嵌套 -->
<!--
文本節點: 元素中出現的文本稱爲文本節點
-->
<!--
屬性:在元素的開始標記上可以定義元素的屬性
屬性:屬性名=“屬性值”
屬性值必須使用引用
屬性是無順序的。 -->
<!--
格式良好的XML(良構)
1 XML文檔只能有一個根元素。
2 元素的嵌套要合理,不能交叉嵌套
如下是錯誤的
<book>
<authors>
</book>
</authors>
3 標記要配對
-->
<!--
因爲XML的標記和內容定義沒有約定,可以任意的擴展使用,稱爲可以擴展的標記語言!
-->
<!--
實體替換:XML的轉移字符, 當在文本節點中使用特殊符號時候,需要使用實體符號替換
& = &
< = <
> = >
空格=
-->
<!-- CDATA 段:用於聲明大段的文字,可以不進行實體替換 -->
<!-- XML 中的大小寫是敏感的。 -->
<books>
<book id="b01" lang="cn">老夫子
<authors>
<author><佚名></author>
<author>V&A</author>
<author><![CDATA[
<p>測試</p>
]]></author>
</authors>
</book>
<book></book>
</books>
下面是java操作xml:
/**
* Java 中 XML 文件的處理
* 1 直接使用文本流處理XML文件。
* 使用BufferedReader讀取,使用PrintWriter寫出。
* 缺點:無法識別XML語法,不能按照元素進行處理
* 優點:快!
* 2 使用XML API 處理XML文檔,W3C 提供了兩種標準的XML API
* SAX:
* 優點:支持XML的語法,只支持讀取操作,速度快, 佔用內存小
* 缺點:不能寫XML,使用繁瑣
* DOM:支持XML語法,速度沒有SAX快,佔用內存大,支持讀寫操作
*
* DOM4j:是第三方提供的API,不是W3C的標準,底層封裝了 W3C DOM,
* DOM4j API 簡潔方便(比W3C DOM 方便!)
*/
//@Test
public void testSAXAPI(){
//利用SAX API 讀取書籍的名字
// 1 打開文件流 Class getResource;
// 2 創建SAX 處理器(過濾器)
// 3 創建SAX API 讀取XML文件,並且利用處理器過濾XML文件
// 4 在SAX處理期間,就得到了數據
InputStream in = getClass().getResourceAsStream("books.xml");
DefaultHandler handler = new DefaultHandler(){
boolean foundName = false;
@Override
public void startElement(String uri, String localName,
String qName, Attributes attributes) throws SAXException {
foundName = qName.equals("name");
//讀取book元素的id屬性
if (qName.equals("book")) {
String id = attributes.getValue("id");
System.out.println("Book ID:"+id);
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if (foundName) {
String bookName = new String(ch, start, length);
System.out.println(bookName);
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
foundName = false;
if(qName.equals("books")){
throw new SAXException("結束了");
}
}
};
//使用 SAXParser 使用handler掃描讀取XML文件,
// SAXParser: 需要使用工廠模式創建SAXParser對象
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
parser.parse(in, handler);
//parse 方法會從流in中讀取XML文檔,當遇到XML文檔的結構時候,執行handler中適當
// 事件處理方法 startElement endElement 等。
// 異常: IOException 文檔讀取時候發送IO錯誤
// SAXException 文檔不是格式良好,時候發送
// 解析器拋出 SAX異常結束文件的讀取
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* DOM4j API 演示
*/
@Test
public void testReadDoc(){
try {
InputStream in = TestCase.class.getResourceAsStream("books.xml");
SAXReader reader = new SAXReader();
//DOM4j 提供SAXReader,可將流讀取爲XML Doc
//如果流讀取失敗,XML 不是良好格式,將出現異常
Document doc = reader.read(in);
in.close();
//顯示讀取結果
// Dom4j 的幾乎所有API都有方法 asXML() 可以顯示XML文檔數據
System.out.println(doc.asXML());
//在doc中檢索 全部的書名
// dom4j 提供了樹型結構的導航查詢API方法
// getRootElement() 獲取文檔的根元素
// Element 代表內存中一個元素節點對象
Element root = doc.getRootElement();
//elements() 方法,可以獲取一個元素的全部子元素節點
// 重載的 elements(元素名) 獲取一個元素的全都指定名稱的子元素
//List<Element> list = root.elements();
List<Element> list = root.elements("book");
for(Element e: list){
//element(元素名) 獲取一個元素的指定名稱的子元素,如果重複,發回第一個子元素
//Element n = e.element("name");
//元素上一個方法 getText() 用於獲取當前元素中文本內容
//String name = n.getText();
//getTextTrim() 方法可以獲取文本,並且取出前後空白
//name = n.getTextTrim();
//dom4j 提供了更加便捷的API用於直接讀取子元素中的文本
String name = e.elementTextTrim("name");
System.out.println(name);
//dom4j 可以讀取元素的屬性
String id = e.attributeValue("id");
System.out.println("book id:"+id);
//讀取元素的全部屬性
//List<Attribute> attributes = e.attributes();
}
//修改內存中的DOC對象
Element lastBook = list.get(list.size()-1);
//setText() 方法可以修改元素節點的文本內容
lastBook.element("price").setText("80.00");
System.out.println(doc.asXML());
//添加新元素等
// 1 爲根元素增加子元素book, addElement(元素名稱) 返回新元素對象。
Element newBook = root.addElement("book");
// 2 增加元素
newBook.addAttribute("id", "B03");
newBook.addAttribute("lang", "CN");
// 2 book增加子name元素,並且爲name增加文本內容
newBook.addElement("name").setText("紅樓夢");
newBook.addElement("price").setText("88.90");
Element authors = newBook.addElement("authors");
authors.addElement("author").setText("曹雪芹");
//...
System.out.println(doc.asXML());
//寫出Document 對象到文件, dom4j 提供的功能
FileOutputStream out = new FileOutputStream("myBooks.xml");
//設置輸出格式: createPrettyPrint()創建漂亮的打印格式
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter writer = new XMLWriter(out, format);
writer.write(doc);//XML Docuemnt 編碼序列化到流
writer.close();
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
/**
* XML 是數據格式,不僅僅是文件
*
* 讀取 寫出
* 字符流 無語法支持,繁瑣 無語法支持,快 寫出大規模的XML,要注意編碼和語法結構
* SAX 有語法支持,簡便 不能寫出 適合大規模的XML讀取,佔用內存小
* DOM4j 有語法支持,支持讀取 有語法支持,寫出 適合小規模XML讀寫,佔用內存大
* W3C DOM 可以讀 可以寫 API非常繁瑣,Java業界使用DOM4j替代之
* pull解析 有語法支持,簡便 不能寫 適合大規模的XML讀取,佔用內存小
*
* pull解析: 特點是可以任意的暫停繼續, 完全可以代替 SAX
*/
//@Test
public void testXmlPull() throws Exception{
InputStream in = new BufferedInputStream(new FileInputStream("myBooks.xml"));
//XmlPullParser 是接口,事例需要使用工廠創建
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser pullParser = factory.newPullParser();
//將被解析的流交給 pullParser, 不發送解析操作
pullParser.setInput(new InputStreamReader(in, "utf-8"));
//解析獲取全部的書名
boolean found = false;
Scanner scanner = new Scanner(System.in);
//COMMENT 遇到了註釋
//循環一直持續到 發生文件末尾事件爲止
main:
for(int event = pullParser.getEventType();
event !=END_DOCUMENT;
event = pullParser.nextToken()){
//event = START_DOCUMENT COMMENT START_TAG TEXT START_TAG TEXT
switch (event) {
case COMMENT:
System.out.println(pullParser.getText());//抓取註釋的文本
break ;
case START_TAG:
//從 XmlPullParser中拉取元素的開始標記名
String name = pullParser.getName();
if(name.equals("book")){
String id = pullParser.getAttributeValue(0);
System.out.println(id);
}
found = name.equals("name");
break;
case TEXT:
if (found) {
//拉取文本
String text = pullParser.getText().trim();
System.out.println(text);
}
break;
case END_TAG:
found = false;
}
}
in.close();
}
/** 靜態導入 */
//@Test
public void testStaticImport(){
double x = sin(PI);
System.out.println(x);
}
/**
* w3school.com.cn 中文
* w3schools.com 英文
* xpath 是XML 的一種查詢語法
* myBooks.xml
* 抓取全部的 書名 節點的集合
* String xpath = "/books/book/name"
* 在DOM對象上查找,就可以獲取全部滿足xpath的 Element對象
* dom4j 支持 xpath查找,在內存的Dom對象中查找 子節點
*
* 1 xpath 的語法
* 2 dom4j API 支持xpath 查詢
* 1 支持根部絕對路徑查詢
* doc.selectNodes(xpath) 返回一個集合,包含全部滿足條件的節點
* doc.selectSingleNode(xpath) 返回第一個匹配的節點
* 2 支持相對路徑查詢,從某個元素節點開始執行查詢
* 如 Element book 節點
* book.selectNodes(xpath)
* book.selectSingleNode(xpath)
*/
//@Test
public void testXpath() throws Exception{
//打開Dom4j DOM 對象
SAXReader reader = new SAXReader();
Document doc = reader.read(new File("myBooks.xml"));
//selectNodes 是在DOM 上執行xpath查詢,將滿足條件的元素 都作爲返回值返回
String xpath = "/books/book/name";
List<Element> list = doc.selectNodes(xpath);
//
for (Element e : list) {
System.out.println(e.asXML());
}
}
public void testSelectSingleNode(String xpath) throws Exception{
//打開Dom4j DOM 對象
SAXReader reader = new SAXReader();
Document doc = reader.read(new File("myBooks.xml"));
Node node = doc.selectSingleNode(xpath);
System.out.println(node.asXML());
}
public void testSelectNodes(String xpath) throws Exception{
SAXReader reader = new SAXReader();
Document doc = reader.read(new File("myBooks.xml"));
List<Node> list = doc.selectNodes(xpath);
for (Node node : list) {
System.out.println(node.asXML());
}
}
@Test
public void testXPath() throws Exception{
//testSelectSingleNode("/books");
//testSelectNodes("/books/book");
//testSelectNodes("//.");
//XPATH 可以理解爲 一層一層的過濾
// "//" 代表所有節點, //author 所有節點中名字爲author的節點。
//testSelectNodes("//author");//查詢結果節點是Element類型
//查詢所有節點中的 id屬性節點
//testSelectNodes("//@id");//查詢結果節點是Attribute類型
// DOM 節點的分類關係
/* Node 節點
* |-- Document 文檔節點
* | |-- 只能包含一個根元素
* |-- Element 元素節點
* | |-- 可以包含其他節點和文本
* |-- Comment 註釋節點
* |-- Text 文本節點
* |-- Attribute 屬性節點
*/
//testSelectNodes("/books/book[1]");
//testSelectNodes("/books/book[last()]");
//testSelectNodes("/books/book[1]/name");
//testSelectNodes("/books/book[last()]/name");
//testSelectNodes("/books/book[1]/authors/author[1]");
//testSelectNodes("/books/book[1]/authors/athor[1]");
//book有id屬性被查詢出來
//testSelectNodes("/books/book[@id]");
//testSelectNodes("/books/book[@id and price>85 and position()=1]");
testSelectNodes("//*[.>85]");
// /*/* 與 /books/book 區別
}