天天看點

(轉)使用Apache Xerces解析XML文檔

一、技術概述   在用Java解析XML時候,一般都使用現成XML解析器來完成,自己編碼解析是一件很棘手的問題,對程式員要求很高,一般也沒有專業廠商或者開源組織實作的好。   Java解析XML的原理圖如下:   目前Java XML解析器有十多種之多,解析原理有二:使用基于事件的XML簡單API(Simple API for XML)稱為SAX和基于樹和節點的文檔對象模型(Document Object Module)稱為DOM。Sun公司提供了Java API for XML Parsing(JAXP)接口來使用SAX和DOM,通過JAXP,我們可以使用任何與JAXP相容的XML解析器。但并不是所有的Java XML解析工具都實作了SUN提供的接口。DOM4J就沒有遵循SUN的JAXP規範,但非常優秀。   DOM 采用建立樹形結構的方式通路 XML 文檔,而 SAX 采用的事件模型。   DOM 是W3C組織推薦的處理XML的标準接口,DOM 解析器把 XML 文檔轉化為一個包含其内容的樹,并可以對樹進行周遊。用 DOM 解析模型的優點是程式設計容易,開發人員隻需要調用建樹的指令,然後利用navigation APIs通路所需的樹節點來完成任務。可以很容易的添加和修改樹中的元素。然而由于使用 DOM 解析器的時候需要處理整個 XML 文檔,是以對性能和記憶體的要求比較高,尤其是遇到很大的 XML 檔案的時候。由于它的周遊能力,DOM 解析器常用于 XML 文檔需要頻繁的改變的服務中。   SAX是由XML_DEV郵件清單的成員開發的,它不是某個官方機構的标準,也不由W3C組織或其他任何官方機構維護,但它是XML社群事實上的标準。雖然SAX隻是“民間”标準,但是它在XML中的應用絲毫不比DOM少,幾乎所有的XML解析器都支援它。SAX 解析器采用了基于事件的模型,它在解析 XML 文檔的時候可以觸發一系列的事件,當發現給定的tag的時候,它可以激活一個回調方法,告訴該方法制定的标簽已經找到。SAX 對記憶體的要求通常會比較低,因為它讓開發人員自己來決定所要處理的tag。特别是當開發人員隻需要處理文檔中所包含的部分資料時,SAX 這種擴充能力得到了更好的展現。但用 SAX 解析器的時候編碼工作會比較困難,而且很難同時通路同一個文檔中的多處不同資料。   DOM和SAX隻是定義了一些接口,以及某些接口的預設實作,一個應用程式要想利用DOM或SAX通路XML文檔,還需要一個實作了DOM或SAX的解析器(實作DOM和SAX中定義的接口,提供DOM和SAX定義的功能)。   Apache的Xerces是一個使用非常廣泛的解析其,它提供了DOM和SAX的調用接口,并有多種語言的實作版本,要利用Xerces通路XML文檔,隻需要在應用程式中構造一個解析器實作類的對象。   這裡面還存在一個問題,雖然使用的是标準的DOM和SAX接口,由于不同的XML解析器的實作類是不同的,如果使用另外一種解析器,仍然需要修改應用程式,隻不過修改的代碼量較小,需要更改XML解析器實作類的類名,然後重新編譯、釋出。   然而,對于相容JAXP的XML解析器,我們可以選用JAXP API,這樣在更換相容JAXP解析器的時候,就不用對已釋出的程式做任何的改動。   JAXP開發包由javax.xml包、org.w3c.dom包、org.xml.sax包及其子包組成。在javax.xml.parsers包中,定義了幾個工廠類,用于加載DOM和SAX的實作類。     使用JAXP API解析XML的原理如下:   二、使用DOM解析XML   DOM的核心概念就是NODE(節點)。DOM在分析XML文檔時,将組成XML文檔的各個部分(元素,屬性,文本,注釋,處理指令等)映射成一個對象,這個對象就叫做節點。在記憶體中這些節點形成一棵樹。整棵樹就是一個節點,樹中的每一個節點也是一棵樹(子樹)。DOM就是對這棵樹的一個對象描述,我們通過通路樹中的節點來存取XML文檔的内容。   DOM定義了一個Node接口,用于表示文檔樹中一個節點。從這個接口派生出來更多的具體的接口。例如,表示整個文檔的Document接口,表示XML文檔中的一個元素的Element接口,表示元素屬性的Attr接口,都是從Node接口派生而來的。在org.w3c.dom包中,表示XML文檔各組成部分的接口的繼承關系如圖:     舉個例子,引用java web開發大全,有改動:   students.xml ----------------------------------------------------------------------

        張三

        18

        李四

        20

----------------------------------------------------------------------   public class DOMStudentsInfo {

    public static void main(String[] args) {

        //擷取生成 DOM 對象樹的解析器

        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();         try {

            //從 DocumentBuilderFactory擷取 DocumentBuilder執行個體

            DocumentBuilder db = dbf.newDocumentBuilder();

            File file = new File(\"students.xml\");

            從 XML 文檔擷取 DOM 文檔執行個體

            Document doc = db.parse(file);             //擷取某節點的集合

            NodeList nl = doc.getElementsByTagName(\"student\");             int len = nl.getLength();

            for (int i = 0; i < len; i++) {

                Element eltStu = (Element) nl.item(i);

                Node eltName = eltStu.getElementsByTagName(\"name\").item(0);

                Node eltAge = eltStu.getElementsByTagName(\"age\").item(0);                 String name = eltName.getFirstChild().getNodeValue();

                String age = eltAge.getFirstChild().getNodeValue();                 System.out.print(\"姓名:\");

                System.out.println(name);                 System.out.print(\"年齡:\");

                System.out.println(age);

                System.out.println(\"----------------------------\\n\");

            }

        }

        catch (ParserConfigurationException e) {

            e.printStackTrace();

        }

        catch (SAXException e) {

            e.printStackTrace();

        }

        catch (IOException e) {

            e.printStackTrace();

        }

    }

}

  運作結果:  

        a1234

        四川省xx縣xx鎮xx路x段xx号

        b1234

        四川省xx市xx鄉xx村xx組

----------------------------------------------------------------------   public class MyXMLReader2 extends DefaultHandler {

    java.util.Stack tags = new java.util.Stack();     public MyXMLReader2() {

        super();

    }     public static void main(String args[]) {

        long lasting = System.currentTimeMillis();

        try {

            SAXParserFactory sf = SAXParserFactory.newInstance();

            SAXParser sp = sf.newSAXParser();

            MyXMLReader2 reader = new MyXMLReader2();

            sp.parse(new InputSource(\"data_10k.xml\"), reader);

        } catch (Exception e) {

            e.printStackTrace();

        }

        System.out.println(\"運作時間:\" + (System.currentTimeMillis() - lasting) + \" 毫秒\");

    }     public void characters(char ch[], int start, int length) throws SAXException {

        String tag = (String) tags.peek();

        if (tag.equals(\"no\")) {

            System.out.print(\"車牌号碼:\" + new String(ch, start, length));

        }

        if (tag.equals(\"addr\")) {

            System.out.println(\" 位址:\" + new String(ch, start, length));

        }

    }     public void startElement(

            String uri,

            String localName,

            String qName,

            Attributes attrs) {

        tags.push(qName);

    }

}   運作結果:               SAXReader reader = new SAXReader();

            Document doc = reader.read(f);

            Element root = doc.getRootElement();

            Element foo;

            for (Iterator i = root.elementIterator(\"value\"); i.hasNext();) {

                foo = (Element) i.next();

                System.out.print(\"車牌号碼:\" + foo.elementText(\"no\"));

                System.out.println(\" 車主位址:\" + foo.elementText(\"addr\"));

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

        System.out.println(\"運作時間:\" + (System.currentTimeMillis() - lasting) + \" 毫秒\");

    }

}   五、使用JDOM解析xml   public class MyXMLReader3 {

    public static void main(String arge[]) {

        long lasting = System.currentTimeMillis();

        try {

            SAXBuilder builder = new SAXBuilder();

            Document doc = builder.build(new File(\"data_10k.xml\"));

            Element foo = doc.getRootElement();

            List allChildren = foo.getChildren();

            for (int i = 0; i < allChildren.size(); i++) {

                System.out.print(\"車牌号碼:\" + ((Element) allChildren.get(i)).getChild(\"no\").getText());

                System.out.println(\" 車主位址:\" + ((Element) allChildren.get(i)).getChild(\"addr\").getText());

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

        System.out.println(\"運作時間:\" + (System.currentTimeMillis() - lasting) + \" 毫秒\");

    }

}

  六、使用JAXP解析XML   public class MyXMLReader1 {

    public static void main(String arge[]) {

        long lasting = System.currentTimeMillis();

        try {

            File f = new File(\"data_10k.xml\");

            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

            DocumentBuilder builder = factory.newDocumentBuilder();

            Document doc = builder.parse(f);

            NodeList nl = doc.getElementsByTagName(\"value\");

            for (int i = 0; i < nl.getLength(); i++) {

                System.out.print(\"車牌号碼:\" + doc.getElementsByTagName(\"no\").item(i).getFirstChild().getNodeValue());

                System.out.println(\" 車主位址:\" + doc.getElementsByTagName(\"addr\").item(i).getFirstChild().getNodeValue());

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

        System.out.println(\"運作時間:\" + (System.currentTimeMillis() - lasting) + \" 毫秒\");

    }

}