簡體   English   中英

使用SAX解析常見的XML元素

[英]Using SAX to parse common XML elements

我目前正在使用SAX(Java)來解析一些不同的XML文檔,每個文檔代表不同的數據並且結構略有不同。 因此,每個XML文檔都由不同的SAX類(子類化DefaultHandler )處理。

但是,有一些XML結構可以出現在所有這些不同的文檔中。 理想情況下,我想告訴解析器“嘿,當你到達complex_node元素時,只需使用ComplexNodeHandler來讀取它,然后給我回復結果。如果你到達some_other_node ,請使用OtherNodeHandler來讀取它然后給我回復結果”。

但是,我看不出一個明顯的方法來做到這一點。

我應該只是創建一個單片處理程序類,它可以讀取我擁有的所有不同文檔(並根除代碼重復),還是有更聰明的方法來處理它?

下面是我對類似問題的回答( 使用sax跳過節點 )。 它演示了如何在XMLReader上交換內容處理程序。

在此示例中,交換的ContentHandler只是忽略所有事件,直到它放棄控制,但您可以輕松地調整概念。


您可以執行以下操作:

import javax.xml.parsers.SAXParser; 
import javax.xml.parsers.SAXParserFactory; 
import org.xml.sax.XMLReader; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
        SAXParserFactory spf = SAXParserFactory.newInstance(); 
        SAXParser sp = spf.newSAXParser(); 
        XMLReader xr = sp.getXMLReader(); 
        xr.setContentHandler(new MyContentHandler(xr)); 
        xr.parse("input.xml"); 
    } 
} 

MyContentHandler

該類負責處理XML文檔。 當您點擊要忽略的節點時,可以交換IgnoringContentHandler,它將吞下該節點的所有事件。

import org.xml.sax.Attributes; 
import org.xml.sax.ContentHandler; 
import org.xml.sax.Locator; 
import org.xml.sax.SAXException; 
import org.xml.sax.XMLReader; 

public class MyContentHandler implements ContentHandler { 

    private XMLReader xmlReader; 

    public MyContentHandler(XMLReader xmlReader) { 
        this.xmlReader = xmlReader; 
    } 

    public void setDocumentLocator(Locator locator) { 
    } 

    public void startDocument() throws SAXException { 
    } 

    public void endDocument() throws SAXException { 
    } 

    public void startPrefixMapping(String prefix, String uri) 
            throws SAXException { 
    } 

    public void endPrefixMapping(String prefix) throws SAXException { 
    } 

    public void startElement(String uri, String localName, String qName, 
            Attributes atts) throws SAXException { 
        if("sodium".equals(qName)) { 
            xmlReader.setContentHandler(new IgnoringContentHandler(xmlReader, this)); 
        } else { 
            System.out.println("START " + qName); 
        } 
    } 

    public void endElement(String uri, String localName, String qName) 
            throws SAXException { 
        System.out.println("END " + qName); 
    } 

    public void characters(char[] ch, int start, int length) 
            throws SAXException { 
        System.out.println(new String(ch, start, length)); 
    } 

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

    public void processingInstruction(String target, String data) 
            throws SAXException { 
    } 

    public void skippedEntity(String name) throws SAXException { 
    } 

} 

IgnoringContentHandler

當IgnoringContentHandler完成吞咽事件時,它會將控制權傳遞給您的主ContentHandler。

import org.xml.sax.Attributes; 
import org.xml.sax.ContentHandler; 
import org.xml.sax.Locator; 
import org.xml.sax.SAXException; 
import org.xml.sax.XMLReader; 

public class IgnoringContentHandler implements ContentHandler { 

    private int depth = 1; 
    private XMLReader xmlReader; 
    private ContentHandler contentHandler; 

    public IgnoringContentHandler(XMLReader xmlReader, ContentHandler contentHandler) { 
        this.contentHandler = contentHandler; 
        this.xmlReader = xmlReader; 
    } 

    public void setDocumentLocator(Locator locator) { 
    } 

    public void startDocument() throws SAXException { 
    } 

    public void endDocument() throws SAXException { 
    } 

    public void startPrefixMapping(String prefix, String uri) 
            throws SAXException { 
    } 

    public void endPrefixMapping(String prefix) throws SAXException { 
    } 

    public void startElement(String uri, String localName, String qName, 
            Attributes atts) throws SAXException { 
        depth++; 
    } 

    public void endElement(String uri, String localName, String qName) 
            throws SAXException { 
        depth--; 
        if(0 == depth) { 
           xmlReader.setContentHandler(contentHandler); 
        } 
    } 

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

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

    public void processingInstruction(String target, String data) 
            throws SAXException { 
    } 

    public void skippedEntity(String name) throws SAXException { 
    } 

} 

您可以使用一個處理程序(ComplexNodeHandler)來處理文檔的某些部分(complex_node),並將所有其他部分傳遞給另一個處理程序。 ComplexNodeHandler的構造函數將另一個處理程序作為參數。 我的意思是這樣的:

class ComplexNodeHandler {

    private ContentHandler handlerForOtherNodes;

    public ComplexNodeHandler(ContentHandler handlerForOtherNodes) {
         this.handlerForOtherNodes = handlerForOtherNodes;
    }

    ...

    public startElement(String uri, String localName, String qName, Attributes atts) {
        if (currently in complex node) {
            [handle complex node data] 
        } else {
            // pass the event to the document specific handler
            handlerForOtherNodes.startElement(uri, localName, qName, atts);
       }
    } 

    ...

}

因為我不熟悉SAX,所以還有更好的選擇。 為公共部分編寫基礎處理程序並繼承它也可以工作,但我不確定在這里使用繼承是一個好主意。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM