Java SAX:如何获取元素的内容

Java SAX:如何获取元素的内容,java,xml,sax,Java,Xml,Sax,我在理解用SAX解析XML结构时遇到一些困难。假设存在以下XML: <root> <element1>Value1</element1> <element2>Value2</element2> </root> 我想我只是想得太复杂了:-) Robert您应该通过characters()记录内容,为每次调用附加到StringBuilder,并且只在endElement()调用时存储连接的值 为什么??因为元素内容可以

我在理解用SAX解析XML结构时遇到一些困难。假设存在以下XML:

<root>
  <element1>Value1</element1>
  <element2>Value2</element2>
</root>
我想我只是想得太复杂了:-)


Robert

您应该通过
characters()
记录内容,为每次调用附加到StringBuilder,并且只在
endElement()
调用时存储连接的值


为什么??因为元素内容可以多次调用
characters()
,每次调用都引用该文本元素的连续子序列。

使用SAX,您需要维护自己的堆栈。对于非常基本的处理,您可以执行以下操作:

void startElement(...) {
    if (name.equals("element1")) {
        inElement1 = true;
        element1Content = new StringBuffer();
    }
}

void characters(...) {
    if (inElement1) {
        element1Content.append(characterData);
    }
}

void endElement(...) {
    if (name.equals("element2")) {
        inElement1 = false;
        processElement1Content(element1Content.toString());
    }
}
如果您想要像示例中那样的代码,那么您需要使用DOM模型而不是SAX。DOM更容易编码,但通常比SAX更慢,内存更昂贵


我建议使用第三方库而不是内置的JavaXML库来进行DOM操作。Dom4J看起来不错,但可能还有其他库。

此解决方案适用于包含文本内容的单个元素。当element1有更多的子元素时,需要做更多的工作。布赖恩的话很重要。 当您有多个元素或需要更通用的解决方案时,这可能会对您有所帮助。我用一个300+MB的xml文件测试了它,它仍然非常快:

final StringBuilder builder=new StringBuilder();
XMLReader saxXmlReader = XMLReaderFactory.createXMLReader();

DefaultHandler handler = new DefaultHandler() {
    boolean isParsing = false;

    public void startElement(String uri, String localName, String qName, Attributes attributes) {
        if ("element1".equals(localName)) {
            isParsing = true;
        }
        if (isParsing) {
            builder.append("<" + qName + ">");
        }
    }

    @Override
    public void characters(char[] chars, int i, int i1) throws SAXException {
        if (isParsing) {
            builder.append(new String(chars, i, i1));
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if (isParsing) {
            builder.append("</" + qName + ">");
        }
        if ("element1".equals(localName)) {
            isParsing = false;
        }
    }
};

saxXmlReader.setContentHandler(handler);
saxXmlReader.setErrorHandler(handler);

saxXmlReader.parse(new InputSource(new FileInputStream(input)));
final StringBuilder=新StringBuilder();
XMLReader saxXmlReader=XMLReaderFactory.createXMLReader();
DefaultHandler=新的DefaultHandler(){
布尔值isParsing=false;
public void startElement(字符串uri、字符串localName、字符串qName、属性){
if(“element1”.equals(localName)){
isParsing=真;
}
如果(isParsing){
生成器。追加(“”);
}
}
@凌驾
公共无效字符(char[]chars,int i,int i1)引发异常{
如果(isParsing){
append(新字符串(chars,i,i1));
}
}
@凌驾
public void endElement(字符串uri、字符串localName、字符串qName)引发SAXException{
如果(isParsing){
生成器。追加(“”);
}
if(“element1”.equals(localName)){
isParsing=false;
}
}
};
setContentHandler(handler);
setErrorHandler(handler);
parse(新的InputSource(新的FileInputStream(input));

谢谢Cameron,这正是我所期望的:-)由于我的应用程序将在Android智能手机上运行,我认为使用内置SAX解析器比切换到DOM更好。也许可以使用首选的StringBuilder
final StringBuilder builder=new StringBuilder();
XMLReader saxXmlReader = XMLReaderFactory.createXMLReader();

DefaultHandler handler = new DefaultHandler() {
    boolean isParsing = false;

    public void startElement(String uri, String localName, String qName, Attributes attributes) {
        if ("element1".equals(localName)) {
            isParsing = true;
        }
        if (isParsing) {
            builder.append("<" + qName + ">");
        }
    }

    @Override
    public void characters(char[] chars, int i, int i1) throws SAXException {
        if (isParsing) {
            builder.append(new String(chars, i, i1));
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if (isParsing) {
            builder.append("</" + qName + ">");
        }
        if ("element1".equals(localName)) {
            isParsing = false;
        }
    }
};

saxXmlReader.setContentHandler(handler);
saxXmlReader.setErrorHandler(handler);

saxXmlReader.parse(new InputSource(new FileInputStream(input)));