当前位置: 首页 > 面试题库 >

使用SAX解析常见的XML元素

龚博涛
2023-03-14
问题内容

我目前正在使用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的事件处理程序 编写核心解析处理类 输出结果为: