stax - 将xml节点作为字符串

Jas*_*son 6 java xml stax extract

xml看起来像这样:

<statements>
   <statement account="123">
      ...stuff...
   </statement>
   <statement account="456">
      ...stuff...
   </statement>
</statements>
Run Code Online (Sandbox Code Playgroud)

我正在使用stax一次处理一个" <statement>",然后我就开始工作了.我需要将整个语句节点作为字符串获取,这样我就可以创建"123.xml"和"456.xml",甚至可以将其加载到由account索引的数据库表中.

使用这种方法:http://www.devx.com/Java/Article/30298/1954

我想做这样的事情:

String statementXml = staxXmlReader.getNodeByName("statement");

//load statementXml into database
Run Code Online (Sandbox Code Playgroud)

t0r*_*r0X 7

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

<many-many-tags>
    <description>
        ...
        <p>Lorem ipsum...</p>
        Devils inside...
        ...
    </description>
</many-many-tags>
Run Code Online (Sandbox Code Playgroud)

我的解决方案

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();
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

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()) {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,提取的XML片段将包含完整的提取的正文内容,包括空格和注释.为了简洁起见,省略了按需过滤或使缓冲区大小可参数化的问题:

'
    <description>
        ...
        <p>Lorem ipsum...</p>
        Devils inside...
        ...
    </description>
    '
Run Code Online (Sandbox Code Playgroud)


bdo*_*han 6

你可以使用StAX.您只需要将XMLStreamReader推进到start元素for语句.检查帐户属性以获取文件名.然后使用javax.xml.transform API将StAXSource转换为包装文件的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));
        }
    }

}
Run Code Online (Sandbox Code Playgroud)


jav*_*y79 0

为什么不直接使用 xpath 呢?

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

就像这样:

//statement
Run Code Online (Sandbox Code Playgroud)

编辑#1:如果可能的话,看看dom4j。您可以相当简单地读取字符串并获取所有“语句”节点。

编辑#2:使用 dom4j,这就是你要做的:(来自他们的食谱)

String text = "your xml here";
Document document = DocumentHelper.parseText(text);

public void bar(Document document) {
   List list = document.selectNodes( "//statement" );
   // loop through node data
}
Run Code Online (Sandbox Code Playgroud)

  • 海报明确提到了 StAX,所以我认为指向 dom4j 或其他库的指针对他没有多大帮助...... (5认同)
  • 鉴于 OP 从未提出过问题,因此使用 xPath 的建议是最好的。可能更好。 (2认同)