以下是我对类似问题 (Skipping nodes with 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 {
}
}