2 XML 以及XML解析
阿新 • • 發佈:2018-02-10
instance 一個 修改 字符 pretty 沒有 tom 元素 描述 一、XML
1.XML:傳輸數據和保存數據 特點:有且只有一個根元素,xml結構為樹形結構 2.XML文檔結構分析(一切皆節點) 接口Node 子接口 Document :描述所有的xml文件 Element :描述所有的元素 Text :描述xml所有的文本內容(換行也是文本內容) Attr :描述xml所有屬性 3.xml的CDATA 用CDATA括起來的內容不會被xml文件解析,而是當成字符串使用。 <![CDATA[ 中間的內容就是字符串<br> ]]>
二、XML解析
1.DOM解析(解析小型文件)
一次性將整個XML文件加載到內存中,形成一顆DOM樹對象,操作xml, 實際上就是操作(增刪改查)DOM對象即可, 操作完畢以後,要執行同步操作 ①獲取Document文檔對象: 1.創建DocumentBuilderFactory對象 DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance(); 2.創建DocumentBuilder對象 DocumentBulider builder=factory.newDocumentBuilder(); 3.創建Document對象 Document doc=builder.parse(f); Document doc=builder.newDocument(); ②常用API Node接口: getTextContent():獲取文本內容 setTextContent():設置文本內容 appendChild(Node newChild):添加子元素 removeChild(Node oldChild):刪除子元素 Document接口: getDocumentElement():獲取根元素 getElementsByTagName(""):根據指定的標簽名獲取所有子元素 createElement(""):創建元素 Element接口:(可以設置文本內容) getElementByTagName(""):獲取所有子元素 setAttribute("","");設置屬性和屬性值 getAttribute(""):獲取屬性值 ③修改後,要執行同步操作: 同步操作核心類:Transformer Transformer trans=TransformerFactory.newInstance().newTransformer(); 執行同步方法: trans.transform(Source xmlSource,Result outputTarget); xmlSource使用DOMSource outputTarget使用StreamResult trans.transform(new DOMSource(doc),new StreamResult(new File(filePath)));
public void testGet() throws Exception { // 步驟 // 1, 創建Document文檔對象 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(new File(filePath)); // 2,獲取根元素 <contacts> Element root = doc.getDocumentElement(); System.out.println(root); // 3,獲取第二個聯系人<linkman id="2"> NodeList linkmans = root.getElementsByTagName("linkman"); Element linkmanEL = (Element)linkmans.item(0); // 4,獲取第二個聯系人的<name>元素 Node nameEL = linkmanEL.getElementsByTagName("name").item(0); // 5, 獲取<name>元素的文本內容 String name = nameEL.getTextContent(); System.out.println(name); //6, 修改<name>的文本內容 nameEL.setTextContent("[email protected]"); //7, 創建聯系人元素 <linkman> Element linkmanEL = doc.createElement("linkman"); // 8,創建聯系人的子元素 <name><email><address><group> Element nameEL = doc.createElement("name"); Element emailEL = doc.createElement("email"); // 9, 設置子元素對應的文本內容 nameEL.setTextContent("虛竹"); emailEL.setTextContent("[email protected]"); // 10,將子元素添加到<linkman> linkmanEL.appendChild(nameEL); linkmanEL.appendChild(emailEL); // 11,將<linkman>元素添加到根元素<contacts>中 root.appendChild(linkmanEL); // 12, 同步操作 TransformerFactory factory = TransformerFactory.newInstance(); Transformer trans = factory.newTransformer(); //同步數據的數據來源 Source xmlSource = new DOMSource(doc); //同步數據的目標 Result outputTarget = new StreamResult(new File(filePath)); trans.transform(xmlSource, outputTarget); }
1.2 使用dom4j框架解析xml文件
//需求:獲取第一個聯系人的名稱
@Test
public void testGetName() throws Exception {
//1,獲取Document對象
SAXReader reader = new SAXReader();
String filePath = "C:/Users/YL/workspace/j1704/day05-xml-parse/contacts.xml";
Document doc = reader.read(new File(filePath));
//2. 獲取根元素
Element root = doc.getRootElement();
//3,獲取第一個聯系人 <linkman id="1">
List linkmans = root.elements("linkman");
Element linkmanEL = (Element)linkmans.get(0);
//4,獲取<name>元素
Element nameEL = linkmanEL.element("name");
String name = nameEL.getText();
String name = linkmanEL.elementText("name");
//5.獲取第一聯系人的id屬性
Attribute attr = linkmanEL.attribute("id");
System.out.println(attr.getName()+" ---- "+attr.getValue());
System.out.println(name);
}
//添加一個 聯系人
@Test
public void testAdd() throws Exception {
String filePath = "C:/Users/YL/workspace/j1704/day05-xml-parse/contacts.xml";
//1,獲取Document文檔和根元素
SAXReader reader = new SAXReader();
Document doc = reader.read(new File(filePath));
Element root = doc.getRootElement();
//2,創建一個linkman聯系人
Element linkmanEL = root.addElement("linkman").addAttribute("id", "4");
//3. 創建linkman聯系人的子元素
linkmanEL.addElement("name").addText("王姑娘");
linkmanEL.addElement("email").addText("[email protected]");
linkmanEL.addElement("addres").addText("河南");
linkmanEL.addElement("group").addText("少林");
//4. 同步操作(將修改的數據同步到磁盤)
//----------------普通的同步方法,同步到磁盤沒有格式-------------------
// 1)創建FiewWrite對象
//FileWriter writer = new FileWriter(filePath);
//2) 創建 XMLWrite 對象,用於同步Document文檔
//XMLWriter xmlWriter = new XMLWriter(writer);
//3)同步數據
//xmlWriter.write(doc);
//3)關閉流:一定要關閉
//xmlWriter.close();
//--------------漂亮的同步方法:有格式------------------
//1) 創建格式化對象
OutputFormat format = OutputFormat.createPrettyPrint();
//2)創建FiewWrite對象
FileWriter writer = new FileWriter(filePath);
//3)創建 XMLWrite 對象,用於同步Document文檔
XMLWriter xmlWriter = new XMLWriter(System.out, format);
//4)同步數據
xmlWriter.write(doc);
//5)關閉流:一定要關閉
xmlWriter.close();
}
2.SAX解析
SAX(simple API for XML):是一種XML解析的替代方法。相比於DOM,SAX是一種速度更快,更有效的方法。它逐行掃描文檔,一邊掃描一邊解析。而且相比於DOM,SAX可以在解析文檔的任意時刻停止解析,但任何事物都有其相反的一面,對於SAX來說就是操作復雜。
SAX是事件驅動型XML解析的一個標準接口不會改變 SAX的工作原理簡單地說就是對文檔進行順序掃描,當掃描到文檔(document)開始與結束、元素(element)開始與結束、文檔(document)結束等地方時通知事件處理函數,由事件處理函數做相應動作,然後繼續同樣的掃描,直至文檔結束。
大多數SAX都會產生以下類型的事件:
1.在文檔的開始和結束時觸發文檔處理事件。
2.在文檔內每一XML元素接受解析的前後觸發元素事件。
3.任何元數據通常由單獨的事件處理
4.在處理文檔的DTD或Schema時產生DTD或Schema事件。
5.產生錯誤事件用來通知主機應用程序解析錯誤。
需求:解析contacts.xml文件,將所有的linkman聯系人封裝到LinkMan對象中並且添加到list和中
SAX解析的核心類 : SAXParser
如何獲取SAXParser 對象?
1, 創建 SAXParserFactory 對象
SAXParserFactory factory = SAXParserFactory.newInstance();
2, 創建 SAXParser對象
SAXParser parser = factory.newSAXParser();
3, 進行SAX解析
parser.parse(File f, DefaultHandler hb)
f : 需要解析 xml文件
hb : 解析器,真正幹活解析的代碼全在 DefaultHandler 中
public class SAXParseTest {
String filePath = "C:/Users/YL/workspace/j1704/day05-xml-parse/contacts.xml";
//需求:解析contacts.xml文件,將所有的linkman聯系人封裝到LinkMan對象中並且添加到list和中
@Test
public void testParse() throws Exception {
// 1, 創建 SAXParserFactory 對象
SAXParserFactory factory = SAXParserFactory.newInstance();
// 2, 創建 SAXParser對象
SAXParser parser = factory.newSAXParser();
// 3, 進行SAX解析
//創建處理器對象
CustomeHanlder dh = new CustomeHanlder();
parser.parse(new File(filePath), dh);
//獲取處理器解析的list集合
List<LinkMan> list = dh.getList();
for (LinkMan linkMan : list) {
System.out.println("解析結果:"+linkMan);
}
}
public class CustomeHanlder extends DefaultHandler {
// 創建list集合,存放聯系人對象
@Getter
private List<LinkMan> list = new ArrayList<>();
//聯系人對象
private LinkMan linkman;
//保存上一次元素名稱
private String preTag;
// 元素開始時候調用
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// 判斷元素名稱是linkman時創建對象
if ("linkman".equals(qName)) {
linkman = new LinkMan();
// 獲取id屬性
String id = attributes.getValue("id");
linkman.setId(Integer.valueOf(id));
}
//將qName 賦值給 成員變量 preTage ,在解析文本的時候就能獲取上一次的元素名稱
preTag = qName;
}
// 解析文本內容調用
public void characters(char[] ch, int start, int length) throws SAXException {
String value = new String(ch,start,length);
//排除所有為空的文本,換行等等
if(value!=null){
if("name".equals(preTag)){
linkman.setName(value);
}else if("email".equals(preTag)){
linkman.setEmail(value);
}else if("address".equals(preTag)){
linkman.setAddress(value);
}else if("group".equals(preTag)){
linkman.setGroup(value);
//此時linkman對象所有的數據都封裝完畢可以添加list中去了
list.add(linkman);
}
}
}
// 元素結束時候調用
public void endElement(String uri, String localName, String qName) throws SAXException {
preTag = null;
}
// 文檔開始時候調用
public void startDocument() throws SAXException {
}
// 文檔結束時候調用
public void endDocument() throws SAXException {
}
}
2 XML 以及XML解析