Java stax-将xml节点作为字符串获取

Java stax-将xml节点作为字符串获取,java,xml,extract,stax,Java,Xml,Extract,Stax,xml看起来是这样的: <statements> <statement account="123"> ...stuff... </statement> <statement account="456"> ...stuff... </statement> </statements> 我一直在谷歌上搜索,这似乎非常困难 考虑到我的xml,我认为它可能更简单: StringBuil

xml看起来是这样的:

<statements>
   <statement account="123">
      ...stuff...
   </statement>
   <statement account="456">
      ...stuff...
   </statement>
</statements>

我一直在谷歌上搜索,这似乎非常困难

考虑到我的xml,我认为它可能更简单:

StringBuilder buffer = new StringBuilder();
for each line in file {
   buffer.append(line)
   if(line.equals(STMT_END_TAG)){
      parse(buffer.toString())
      buffer.delete(0,buffer.length)
   }
 }

 private void parse(String statement){
    //saxParser.parse( new InputSource( new StringReader( xmlText ) );
    // do stuff
    // save string
 }

为什么不直接使用xpath呢

您可以使用相当简单的xpath来获取所有“语句”节点

像这样:

//statement
编辑#1:如果可能,请查看。您可以非常简单地读取字符串并获取所有“statement”节点

编辑#2:使用dom4j,您可以这样做: (来自他们的食谱)


Stax是一种低级访问API,它既没有查找功能,也没有递归访问内容的方法。但你到底想做什么?你为什么要考虑斯塔克斯

除了使用树模型(DOM、XOM、JDOM、Dom4j)之外,处理数据时的最佳选择通常是像JAXB这样的数据绑定库。有了它,您可以将Stax或SAX读取器传递给它,让它将xml数据绑定到javabean中,而不是与xml进程Java对象混为一谈。这通常更方便,而且通常是相当高的性能。 使用较大文件的唯一诀窍是,您不希望一次绑定整个文件,而是绑定每个子树(在您的情况下,一次只绑定一个“语句”)。
最简单的方法是迭代staxxmlstreamreader,然后使用JAXB进行绑定。

您可以使用Stax进行绑定。您只需要将XMLStreamReader提前到语句的start元素。检查account属性以获取文件名。然后使用javax.xml.transform API将StatxSource转换为封装文件的StreamResult。这将推进XMLStreamReader,然后重复这个过程

import java.io.File;
import java.io.FileReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stax.StAXSource;
import javax.xml.transform.stream.StreamResult;

public class Demo {

    public static void main(String[] args) throws Exception  {
        XMLInputFactory xif = XMLInputFactory.newInstance();
        XMLStreamReader xsr = xif.createXMLStreamReader(new FileReader("input.xml"));
        xsr.nextTag(); // Advance to statements element

        while(xsr.nextTag() == XMLStreamConstants.START_ELEMENT) {
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer t = tf.newTransformer();
            File file = new File("out" + xsr.getAttributeValue(null, "account") + ".xml");
            t.transform(new StAXSource(xsr), new StreamResult(file));
        }
    }

}

我有一个类似的任务,虽然最初的问题已经超过一年了,但我找不到满意的答案。到目前为止,最有趣的答案是Blaise Doughan的答案,但我无法在我期望的XML上运行它(可能底层解析器的一些参数会改变这一点?)。这里的XML非常简单:

<many-many-tags>
    <description>
        ...
        <p>Lorem ipsum...</p>
        Devils inside...
        ...
    </description>
</many-many-tags>
请注意,提取的XML片段将包含完整的提取正文内容,包括空格和注释。为了代码简洁起见,没有按需过滤这些内容,也没有将缓冲区大小参数化:

'
    <description>
        ...
        <p>Lorem ipsum...</p>
        Devils inside...
        ...
    </description>
    '
'
...
同侧眼线

里面的魔鬼。。。 ... '
你的问题到底是什么?JDK/JRE中也有标准的XPath库:海报明确提到了StAX,所以我认为指向dom4j或其他库的指针对他没有多大帮助……鉴于OP从未提出过问题,使用XPath的建议是最好的。也许更好。使用while(xsr.nextTag…)将失败。xsr.nextTag()的stax文档声明,如果xsr.hasNext()为false并且调用了next标记,将引发异常。另外,当使用xsr.nextTag()时,如果遇到除空格字符以外的其他字符、注释、处理_指令、开始_元素、结束_元素,则会引发异常。当我使用上述代码时,我在线程“main”中得到以下错误异常net.sf.saxon.trans.XPathException:org.w3c.dom.DOMException:HIERARCHY\u REQUEST\u ERR:尝试在不允许的位置插入节点。有什么想法吗?概念上调用xsr.nextTag()是错误的,因为如果“input.xml”不包含标题,XMLStreamReader可能已经从正确的标记开始。尝试所有可能的情况我总是收到错误:java.lang.IllegalStateException:尝试输出没有匹配开始标记的结束标记@t0r0X解决方案是唯一一个对meIs有效的没有名称空间的字符串打印方法?我不确定我是否理解您的问题,什么名称空间?你能举个例子吗?
<many-many-tags>
    <description>
        ...
        <p>Lorem ipsum...</p>
        Devils inside...
        ...
    </description>
</many-many-tags>
public static String readElementBody(XMLEventReader eventReader)
    throws XMLStreamException {
    StringWriter buf = new StringWriter(1024);

    int depth = 0;
    while (eventReader.hasNext()) {
        // peek event
        XMLEvent xmlEvent = eventReader.peek();

        if (xmlEvent.isStartElement()) {
            ++depth;
        }
        else if (xmlEvent.isEndElement()) {
            --depth;

            // reached END_ELEMENT tag?
            // break loop, leave event in stream
            if (depth < 0)
                break;
        }

        // consume event
        xmlEvent = eventReader.nextEvent();

        // print out event
        xmlEvent.writeAsEncodedUnicode(buf);
    }

    return buf.getBuffer().toString();
}
XMLEventReader eventReader = ...;
while (eventReader.hasNext()) {
    XMLEvent xmlEvent = eventReader.nextEvent();
    if (xmlEvent.isStartElement()) {
        StartElement elem = xmlEvent.asStartElement();
        String name = elem.getName().getLocalPart();

        if ("DESCRIPTION".equals(name)) {
            String xmlFragment = readElementBody(eventReader);
            // do something with it...
            System.out.println("'" + fragment + "'");
        }
    }
    else if (xmlEvent.isEndElement()) {
        // ...
    }
}
'
    <description>
        ...
        <p>Lorem ipsum...</p>
        Devils inside...
        ...
    </description>
    '