我目前正在使用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 {
}
}
忽略ContentHandler
当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 {
}
}
问题内容: 它很好用,但是我希望它返回一个包含所有字符串的数组,而不是最后一个元素返回一个字符串。 任何想法如何做到这一点? 问题答案: 因此,你想构建一个XML解析器来解析这样的RSS feed。 现在,你可以使用两个SAX实现。你可以使用org.xml.sax或android.sax实现。在发布简短的示例后,我将解释两者的优点和缺点。 android.sax Implementation 让我
问题内容: 它很好用,但是我希望它返回一个包含所有字符串的数组,而不是最后一个元素返回一个字符串。 任何想法如何做到这一点? 问题答案: 因此,你想构建一个XML解析器来解析这样的RSS feed。 现在,你可以使用两个SAX实现。你可以使用org.xml.sax或android.sax实现。在发布简短的示例后,我将解释两者的优点和缺点。 android.sax实现 让我们从实现开始。 你首先必须
问题内容: 我正在用SAX解析XML文件,有时需要元素的内部XML。例如,对于以下XML 我需要获取元素 a 的内部XML ,这将是 最简单的方法是什么? 谢谢。 伊万 问题答案: 对于这种情况,我建议使用2个内容处理程序。第一个负责查找文档的相关部分,第二个负责处理内容。我对类似问题的答案(请参见下面的链接)演示了如何实现此方法: 使用SAX解析常见的XML元素
问题内容: 我正在从REST服务接收XML文档,该文档将使用SAX进行解析。请参见以下示例,它是从XSD生成的。 设置解析器不是问题。我的主要问题是在实际的处理,方法等,我不知道如何提取我需要的项目,并将其作为他们有些“嵌套”。 例 所述可发生一次或两次,并且可以包含任意数量的其-in了转向有关于一个连接的信息的元素。基本上,我需要与他们的所有连接的列表,和。我必须为每个元素创建一个类吗? 就我所
问题内容: 我正在尝试分析堆栈溢出数据转储,其中一个表称为posts.xml,其中有大约1000万个条目。样本XML: 我想解析此xml,但仅加载xml的某些属性,例如ID,PostTypeId,AcceptedAnswerId和其他2个属性。SAX中是否有办法只加载这些属性?如果有的话怎么办?对于SAX来说我还很陌生,所以一些指导会有所帮助。 否则,加载整个程序只会很慢,而且某些属性也不会被使用
主要内容:Java SAX解析器 解析XML文档的示例Java SAX解析器 解析XML文档的示例 需要解析的文件input.xml 编写DefaultHandler的事件处理程序 编写核心解析处理类 输出结果为: