![](/img/trans.png)
[英]Unable to Parse Parent / Child Elements using SAX XML Parser (Android)
[英]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.