2020-5-6 前端達人
XML(Extensible Markup Language 可擴展標記語言),XML是一個以文本來描述數(shù)據(jù)的文檔。
<?xml version="1.0" encoding="UTF-8"?> <people> <person personid="E01"> <name>Tony</name> <address>10 Downing Street, London, UK</address> <tel>(061) 98765</tel> <fax>(061) 98765</fax> <email>tony@everywhere.com</email> </person> <person personid="E02"> <name>Bill</name> <address>White House, USA</address> <tel>(001) 6400 98765</tel> <fax>(001) 6400 98765</fax> <email>bill@everywhere.com</email> </person> </people>
(1)充當顯示數(shù)據(jù)(以XML充當顯示層)
(2)存儲數(shù)據(jù)(存儲層)的功能
(3)以XML描述數(shù)據(jù),并在聯(lián)系服務器與系統(tǒng)的其余部分之間傳遞。(傳輸數(shù)據(jù)的一樣格式)
從某種角度講,XML是數(shù)據(jù)封裝和消息傳遞技術。
3.解析XML:// 創(chuàng)建SAX解析器工廠對象 SAXParserFactory spf = SAXParserFactory.newInstance(); // 使用解析器工廠創(chuàng)建解析器實例 SAXParser saxParser = spf.newSAXParser(); // 創(chuàng)建SAX解析器要使用的事件偵聽器對象 PersonHandler handler = new PersonHandler(); // 開始解析文件 saxParser.parse( new File(fileName), handler);
3.2. DOM解析XML:
DOM:Document Object Model(文檔對象模型)
DOM的特性:
定義一組 Java 接口,基于對象,與語言和平臺無關將 XML 文檔表示為樹,在內(nèi)存中解析和存儲 XML 文檔,允許隨機訪問文檔的不同部分。
DOM解析XML
DOM的優(yōu)點,由于樹在內(nèi)存中是持久的,因此可以修改后更新。它還可以在任何時候在樹中上下導航,API使用起來也較簡單。
DocumentBuilderFactory builder = DocumentBuilderFactory.newInstance(); DocumentBuilder db = builder.newDocumentBuilder(); db.parse("person.xml"); NodeList node_person = doc.getElementsByTagName("person");
3.3. JDOM解析XML:
JDOM是兩位著名的 Java 開發(fā)人員兼作者,Brett Mclaughlin 和 Jason Hunter 的創(chuàng)作成果, 2000 年初在類似于Apache協(xié)議的許可下,JDOM作為一個開放源代碼項目正式開始研發(fā)了。
JDOM 簡化了與 XML 的交互并且比使用 DOM 實現(xiàn)更快,JDOM 與 DOM 主要有兩方面不同。首先,JDOM 僅使用具體類而不使用接口。這在某些方面簡化了 API,但是也限制了靈活性。第二,API 大量使用了 Collections 類,簡化了那些已經(jīng)熟悉這些類的 Java 開發(fā)者的使用。
解析步驟: (1)SAXBuilder sax = new SAXBuilder(); (2)Document doc = sax.build(….); (3)Element el = doc.getRootElement();(4)List list = el.getChildren(); (5)遍歷內(nèi)容
解析步驟: (1)SAXReader sax = new SAXReader(); (2)Document doc = sax.read(Thread.currentThread().getContextClassLoader() .getResourceAsStream("person.xml")); (3)Element root = doc.getRootElement(); (4)Iterator iterator = root.elementIterator(); (5)遍歷迭代器
public class Person { private String personid; private String name; private String address; private String tel; private String fax; private String email; @Override public String toString() { return "Person{" + "personid='" + personid + '\'' + ", name='" + name + '\'' + ", address='" + address + '\'' + ", tel='" + tel + '\'' + ", fax='" + fax + '\'' + ", email='" + email + '\'' + '}'; } public String getPersonid() { return personid; } public void setPersonid(String personid) { this.personid = personid; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getTel() { return tel; } public void setTel(String tel) { this.tel = tel; } public String getFax() { return fax; } public void setFax(String fax) { this.fax = fax; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }
<?xml version="1.0" encoding="UTF-8"?> <people> <person personid="E01"> <name>Tony Blair</name> <address>10 Downing Street, London, UK</address> <tel>(061) 98765</tel> <fax>(061) 98765</fax> <email>blair@everywhere.com</email> </person> <person personid="E02"> <name>Bill Clinton</name> <address>White House, USA</address> <tel>(001) 6400 98765</tel> <fax>(001) 6400 98765</fax> <email>bill@everywhere.com</email> </person> </people>
import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import java.util.ArrayList; import java.util.List; /** * Created by Hu Guanzhong * SAX解析的特點: * 1、基于事件驅動 * 2、順序讀取,速度快 * 3、不能任意讀取節(jié)點(靈活性差) * 4、解析時占用的內(nèi)存小 * 5、SAX更適用于在性能要求更高的設備上使用(Android開發(fā)中) * */ public class PersonHandler extends DefaultHandler{ private List<Person> persons = null; private Person p;//當前正在解析的person private String tag;//用于記錄當前正在解析的標簽名 public List<Person> getPersons() { return persons; } //開始解析文檔時調(diào)用 @Override public void startDocument() throws SAXException { super.startDocument(); persons = new ArrayList<>(); System.out.println("開始解析文檔..."); } //在XML文檔解析結束時調(diào)用 @Override public void endDocument() throws SAXException { super.endDocument(); System.out.println("解析文檔結束."); } /** * 解析開始元素時調(diào)用 * @param uri 命名空間 * @param localName 不帶前綴的標簽名 * @param qName 帶前綴的標簽名 * @param attributes 當前標簽的屬性集合 * @throws SAXException */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { super.startElement(uri, localName, qName, attributes); if ("person".equals(qName)){ p = new Person(); String personid = attributes.getValue("personid"); p.setPersonid(personid); } tag = qName; System.out.println("startElement--"+qName); } //解析結束元素時調(diào)用 @Override public void endElement(String uri, String localName, String qName) throws SAXException { super.endElement(uri, localName, qName); if ("person".equals(qName)) { persons.add(p); } tag = null; System.out.println("endElement--"+qName); } //解析文本內(nèi)容時調(diào)用 @Override public void characters(char[] ch, int start, int length) throws SAXException { super.characters(ch, start, length); if (tag != null) { if ("name".equals(tag)) { p.setName(new String(ch,start,length)); }else if("address".equals(tag)){ p.setAddress(new String(ch,start,length)); }else if("tel".equals(tag)){ p.setTel(new String(ch,start,length)); }else if("fax".equals(tag)){ p.setFax(new String(ch,start,length)); }else if("email".equals(tag)){ p.setEmail(new String(ch,start,length)); } System.out.println(ch); } } }
public class XMLDemo { /** * 使用第三方xstream組件實現(xiàn)XML的解析與生成 */ @Test public void xStream(){ Person p = new Person(); p.setPersonid("1212"); p.setAddress("北京"); p.setEmail("vince@163.com"); p.setFax("6768789798"); p.setTel("13838389438"); p.setName("38"); XStream xStream = new XStream(new Xpp3Driver()); xStream.alias("person",Person.class); xStream.useAttributeFor(Person.class,"personid"); String xml = xStream.toXML(p); System.out.println(xml); //解析XML Person person = (Person)xStream.fromXML(xml); System.out.println(person); } /** * 從XML文件中讀取對象 */ @Test public void xmlDecoder() throws FileNotFoundException { BufferedInputStream in = new BufferedInputStream(new FileInputStream("test.xml")); XMLDecoder decoder = new XMLDecoder(in); Person p = (Person)decoder.readObject(); System.out.println(p); } /** * 把對象轉成XML文件寫入 */ @Test public void xmlEncoder() throws FileNotFoundException { BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("test.xml")); XMLEncoder xmlEncoder = new XMLEncoder(bos); Person p = new Person(); p.setPersonid("1212"); p.setAddress("北京"); p.setEmail("vince@163.com"); p.setFax("6768789798"); p.setTel("13838389438"); p.setName("38"); xmlEncoder.writeObject(p); xmlEncoder.close(); } /** * DOM4J解析XML * 基于樹型結構,第三方組件 * 解析速度快,效率更高,使用的JAVA中的迭代器實現(xiàn)數(shù)據(jù)讀取,在WEB框架中使用較多(Hibernate) * */ @Test public void dom4jParseXML() throws DocumentException { //1 創(chuàng)建DOM4J的解析器對象 SAXReader reader = new SAXReader(); InputStream is = Thread.currentThread().getContextClassLoader() .getResourceAsStream("com/vince/xml/person.xml"); org.dom4j.Document doc = reader.read(is); org.dom4j.Element rootElement = doc.getRootElement(); Iterator<org.dom4j.Element> iterator = rootElement.elementIterator(); ArrayList<Person> persons = new ArrayList<>(); Person p = null; while(iterator.hasNext()){ p = new Person(); org.dom4j.Element e = iterator.next(); p.setPersonid(e.attributeValue("personid")); Iterator<org.dom4j.Element> iterator1 = e.elementIterator(); while(iterator1.hasNext()){ org.dom4j.Element next = iterator1.next(); String tag = next.getName(); if("name".equals(tag)){ p.setName(next.getText()); }else if("address".equals(tag)){ p.setAddress(next.getText()); }else if("tel".equals(tag)){ p.setTel(next.getText()); }else if("fax".equals(tag)){ p.setFax(next.getText()); }else if("email".equals(tag)){ p.setEmail(next.getText()); } } persons.add(p); } System.out.println("結果:"); System.out.println(Arrays.toString(persons.toArray())); } /** * JDOM解析 XML * 1、與DOM類似基于樹型結構, * 2、與DOM的區(qū)別: * (1)第三方開源的組件 * (2)實現(xiàn)使用JAVA的Collection接口 * (3)效率比DOM更快 */ @Test public void jdomParseXML() throws JDOMException, IOException { //創(chuàng)建JDOM解析器 SAXBuilder builder = new SAXBuilder(); InputStream is = Thread.currentThread().getContextClassLoader() .getResourceAsStream("com/vince/xml/person.xml"); org.jdom2.Document build = builder.build(is); Element rootElement = build.getRootElement(); List<Person> list = new ArrayList<>(); Person person = null; List<Element> children = rootElement.getChildren(); for(Element element: children){ person = new Person(); String personid = element.getAttributeValue("personid"); person.setPersonid(personid); List<Element> children1 = element.getChildren(); for (Element e: children1){ String tag = e.getName(); if("name".equals(tag)){ person.setName(e.getText()); }else if("address".equals(tag)){ person.setAddress(e.getText()); }else if("tel".equals(tag)){ person.setTel(e.getText()); }else if("fax".equals(tag)){ person.setFax(e.getText()); }else if("email".equals(tag)){ person.setEmail(e.getText()); } } list.add(person); } System.out.println("結果:"); System.out.println(Arrays.toString(list.toArray())); } /** * DOM解析XML * 1、基于樹型結構,通過解析器一次性把文檔加載到內(nèi)存中,所以會比較占用內(nèi)存,可以隨機訪問 * 更加靈活,更適合在WEB開發(fā)中使用 */ @Test public void domParseXML() throws ParserConfigurationException, IOException, SAXException { //1、創(chuàng)建一個DOM解析器工廠對象 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); //2、通過工廠對象創(chuàng)建解析器對象 DocumentBuilder documentBuilder = factory.newDocumentBuilder(); //3、解析文檔 InputStream is = Thread.currentThread().getContextClassLoader() .getResourceAsStream("com/vince/xml/person.xml"); //此代碼完成后,整個XML文檔已經(jīng)被加載到內(nèi)存中,以樹狀形式存儲 Document doc = documentBuilder.parse(is); //4、從內(nèi)存中讀取數(shù)據(jù) //獲取節(jié)點名稱為person的所有節(jié)點,返回節(jié)點集合 NodeList personNodeList = doc.getElementsByTagName("person"); ArrayList<Person> persons = new ArrayList<>(); Person p = null; //此循環(huán)會迭代兩次 for (int i=0;i<personNodeList.getLength();i++){ Node personNode = personNodeList.item(i); p = new Person(); //獲取節(jié)點的屬性值 String personid = personNode.getAttributes().getNamedItem("personid").getNodeValue(); p.setPersonid(personid); //獲取當前節(jié)點的所有子節(jié)點 NodeList childNodes = personNode.getChildNodes(); for (int j = 0;j<childNodes.getLength();j++){ Node item = childNodes.item(j); String nodeName = item.getNodeName(); if ("name".equals(nodeName)) { p.setName(item.getFirstChild().getNodeValue()); }else if("address".equals(nodeName)){ p.setAddress(item.getFirstChild().getNodeValue()); }else if("tel".equals(nodeName)){ p.setTel(item.getFirstChild().getNodeValue()); }else if("fax".equals(nodeName)){ p.setFax(item.getFirstChild().getNodeValue()); }else if("email".equals(nodeName)){ p.setEmail(item.getFirstChild().getNodeValue()); } } persons.add(p); } System.out.println("結果:"); System.out.println(Arrays.toString(persons.toArray())); } /** * SAX解析的特點: * 1、基于事件驅動 * 2、順序讀取,速度快 * 3、不能任意讀取節(jié)點(靈活性差) * 4、解析時占用的內(nèi)存小 * 5、SAX更適用于在性能要求更高的設備上使用(Android開發(fā)中) * @throws ParserConfigurationException * @throws SAXException * @throws IOException */ @Test public void saxParseXML() throws ParserConfigurationException, SAXException, IOException { //1、創(chuàng)建一個SAX解析器工廠對象 SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); //2、通過工廠對象創(chuàng)建SAX解析器 SAXParser saxParser = saxParserFactory.newSAXParser(); //3、創(chuàng)建一個數(shù)據(jù)處理器(需要我們自己來編寫) PersonHandler personHandler = new PersonHandler(); //4、開始解析 InputStream is = Thread.currentThread().getContextClassLoader() .getResourceAsStream("com/vince/xml/person.xml"); saxParser.parse(is,personHandler); List<Person> persons = personHandler.getPersons(); for (Person p:persons){ System.out.println(p); } } }