Java stax-将xml节点作为字符串获取
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
<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>
'