DOM解析原理:一次性把xml文檔加載成Document樹,通過Document對象得到節點對象,通過節點對象訪問xml文檔內容(標籤,屬性,文本,註釋)。
缺點:不適合讀取大容量xml文件,導致內存溢出。
xml對象的一些方法:
節點:
Iterator Element.nodeIterator(); //獲取當前標籤節點下的所有子節點
標籤:
Element Document.getRootElement(); //獲取xml文檔的根標籤
Element ELement.element("標籤名") //指定名稱的第一個子標籤
Iterator<Element> Element.elementIterator("標籤名");// 指定名稱的所有子標籤
List<Element> Element.elements(); //獲取所有子標籤
屬性:
String Element.attributeValue("屬性名") //獲取指定名稱的屬性值
Attribute Element.attribute("屬性名");//獲取指定名稱的屬性對象
Attribute.getName() //獲取屬性名稱
Attibute.getValue() //獲取屬性值
List<Attribute> Element.attributes(); //獲取所有屬性對象
Iterator<Attribute> Element.attibuteIterator(); //獲取所有屬性對象
文本:
Element.getText(); //獲取當前標籤的文本
Element.setText(); //設置當前標籤的文本
Element.elementText("標籤名") //獲取當前標籤的指定名稱的子標籤的文本內容
xml讀取(查)
public static void main(String[] args) throws Exception{
List<Contact> list = new ArrayList<Contact>();
//獲得xml文件
SAXReader reader = new SAXReader();
Document doc = reader.read(new File("./src/contact.xml"));
//獲得聯繫人xml的根標籤
Iterator<Element> it = doc.getRootElement().elementIterator("contact");
while(it.hasNext()){
Element elem = it.next();
//遍歷Contact,並創建聯繫人對象且賦值
Contact contact = new Contact();
contact.setId(elem.attributeValue("id"));
contact.setName(elem.elementText("name"));
contact.setPhone(elem.elementText("phone"));
contact.setEmail(elem.elementText("email"));
list.add(contact);
}
//遍歷打印
for (Contact contact : list) {
System.out.println(contact);
}
}
xml的增刪改
1 寫出內容到xml文檔
XMLWriter writer = new XMLWriter(OutputStream, OutputForamt)
wirter.write(Document);
2 修改xml文檔的API
增加:
DocumentHelper.createDocument() 增加文檔
addElement("名稱") 增加標籤
addAttribute("名稱",“值”) 增加屬性
修改:
Attribute.setValue("值") 修改屬性值
Element.addAtribute("同名的屬性名","值") 修改同名的屬性值
Element.setText("內容") 修改文本內容
刪除
Element.detach(); 刪除標籤
Attribute.detach(); 刪除屬性
public void fun() throws Exception{
//1.創建doc
//2.添加標籤,屬性
//3.寫xml
//4.修改
//創建doc並寫xml
//創建Document對象
// Document doc = DocumentHelper.createDocument();
//獲得根標籤
// Element rootElem = doc.addElement("students");
//添加數據
// addStudent(rootElem,"1","張三","男","計算機1班","中山東區");
// addStudent(rootElem,"2","李四","女","計算機2班","廣州");
// addStudent(rootElem,"3","傻逼","男","計算機3班","深圳");
//修改id爲2的學生的名字爲"莉莉"
//獲得已經存在的xml文件
// SAXReader reader = new SAXReader();
// Document doc= reader.read("E:/student.xml");
//
// Element rootElem = doc.getRootElement();
// List stuElems= rootElem.elements();
//找到id爲2的student標籤
// for (Object object : stuElems) {
// Element stuElem = (Element)object;
// //獲得student標籤的屬性id
// if(stuElem.attribute("id").getValue().equals("2")){
//修改student標籤下的name標籤的文本
// stuElem.element("name").setText("莉莉");
// }
// }
//刪除id爲2的學生
//獲得已經存在的xml文件
SAXReader reader = new SAXReader();
Document doc= reader.read("E:/student.xml");
Element rootElem = doc.getRootElement();
List stuElems= rootElem.elements();
//找到id爲2的student標籤
for (Object object : stuElems) {
Element stuElem = (Element)object;
//找到id爲2的student標籤
if(stuElem.attribute("id").getValue().equals("2")){
//將id爲2的學生標籤刪除
stuElem.detach();
}
}
//獲得漂亮格式的OutputFormat對象
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding("utf-8");
//用XMLWriter寫xml文件
XMLWriter writer = new XMLWriter(new FileOutputStream("E:/student.xml"),format);
//調用wirte()方法就能夠寫xml
writer.write(doc);
//記得關流
writer.close();
}
public void addStudent(Element elem,String id,String name,String gender,String grade,String address){
Element stu = elem.addElement("student");
stu.addAttribute("id", id);
Element nameElem = stu.addElement("name");
nameElem.setText(name);
stu.addElement("gender").setText(gender);
stu.addElement("grade").setText(grade);
stu.addElement("address").setText(address);
}
xpath 技術
用於快速獲取所需的節點對象
使用xpath方法
List<Node> selectNodes("xpath表達式"); 查詢多個節點對象
Node selectSingleNode("xpath表達式"); 查詢一個節點對象
3.4 xPath語法
/ 絕對路徑 表示從xml的根位置開始或子元素(一個層次結構)
// 相對路徑 表示不分任何層次結構的選擇元素。
* 通配符 表示匹配所有元素
[] 條件 表示選擇什麼條件下的元素
@ 屬性 表示選擇屬性節點
and 關係 表示條件的與關係(等價於&&)
text() 文本 表示選擇文本內容
xml–SAX解析
1.創建SAXParser對象
SAXParser parser=SAXParserFactory.newInstance().newSAXParser();
2.調用parse方法
parser.parse(new File("./src/contact.xml"), new MyDefaultHandler());
[一個類繼承class 類名(extends DefaultHandler) 在調用是創建傳進去
DefaultHandler類的API:
void startDocument() : 在讀到文檔開始時調用
void endDocument() :在讀到文檔結束時調用
void startElement(String uri, String localName, String qName, Attributes attributes) :讀到開始標籤時調用
void endElement(String uri, String localName, String qName) :讀到結束標籤時調用
void characters(char[] ch, int start, int length) : 讀到文本內容時調用
dom解析 和 SAX解析 的區別
============DOM解析 vs SAX解析 ========
DOM解析 SAX解析
原理: 一次性加載xml文檔,不適合大容量的文件讀取 原理: 加載一點,讀取一點,處理一點。適合大容量文件的讀取
DOM解析可以任意進行增刪改成 SAX解析只能讀取
DOM解析任意讀取任何位置的數據,甚至往回讀 SAX解析只能從上往下,按順序讀取,不能往回讀
DOM解析面向對象的編程方法(Node,Element,Attribute) SAX解析基於事件的編程方法
DTD 約束
1)導入dtd方式
內部導入
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
外部導入
本地文件系統:
<!DOCTYPE note SYSTEM "note.dtd">
公共的外部導入:
<!DOCTYPE 根元素 PUBLIC "http://gz.itcast.cn/itcast.dtd">
2)DTD語法
約束標籤
<!ELEMENT 元素名稱 類別> 或 <!ELEMENT 元素名稱 (元素內容)>
類別:
空標籤: EMPTY。 表示元素一定是空元素。
普通字符串: (#PCDATA)。表示元素的內容一定是普通字符串(不能含有子標籤)。
任何內容: ANY。表示元素的內容可以是任意內容(包括子標籤)
(元素內容):
順序問題:
<!ELEMENT 元素名稱 (子元素名稱 1,子元素名稱 2,.....)>: 按順序出現子標籤
次數問題:
標籤 : 必須且只出現1次。
標籤+ : 至少出現1次
標籤* : 0或n次。
標籤? : 0或1次。
約束屬性
<!ATTLIST 元素名稱 屬性名稱 屬性類型 默認值>
默認值:
#REQUIRED 屬性值是必需的
#IMPLIED 屬性不是必需的
#FIXED value 屬性不是必須的,但屬性值是固定的
屬性類型:控制屬性值的
CDATA :表示普通字符串
(en1|en2|..): 表示一定是任選其中的一個值
ID:表示在一個xml文檔中該屬性值必須唯一。值不能以數字開頭