StAXを使用して単純なinput.xml
ファイルをトラバースし、チャンクをDOM DocumentFragments
として取得して新しいファイル(output.xml
)に出力するテストJavaプログラムを作成しました。最近のサーバービルドで問題になっているのは、コード内の変換関数のNullPointerException
です。なぜ私は考えていない。次のようにStAX入力をDOM DocumentFragmentに変換できません
エラーがある:
java.lang.NullPointerException
at net.sf.saxon.dom.DOMWriter.characters(DOMWriter.java:218)
at net.sf.saxon.event.TreeReceiver.characters(TreeReceiver.java:277)
at net.sf.saxon.pull.PullPushTee.copyEvent(PullPushTee.java:117)
at net.sf.saxon.pull.PullPushTee.next(PullPushTee.java:72)
at net.sf.saxon.pull.PullConsumer.consume(PullConsumer.java:42)
at net.sf.saxon.pull.PullPushCopier.copy(PullPushCopier.java:44)
at net.sf.saxon.event.Sender.sendPullSource(Sender.java:542)
at net.sf.saxon.event.Sender.send(Sender.java:204)
at net.sf.saxon.jaxp.IdentityTransformer.transform(IdentityTransformer.java:366)
at XMLTest.getNextElement(XMLTest.java:66)
at XMLTest.main(XMLTest.java:45)
次のように(コンパイルすることができる)、その全体が私のテストプログラムのためのコードがある(75行):
import java.io.*;
import java.nio.file.*;
import javax.xml.parsers.*;
import javax.xml.stream.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stax.StAXSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.*;
public class XMLTest {
static XMLStreamWriter writer;
static XMLStreamReader reader;
static Document doc;
static Transformer transformer;
//main method
public static void main(String[] args) {
System.out.println("XML Test");
System.out.println("========");
try {
//create reader
XMLInputFactory inFactory = XMLInputFactory.newInstance();
BufferedReader input = new BufferedReader(new InputStreamReader(Files.newInputStream(Paths.get("./input.xml"))));
reader = inFactory.createXMLStreamReader(input);
//create writer
XMLOutputFactory outFactory = XMLOutputFactory.newInstance();
BufferedWriter output = new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(Paths.get("./output.xml"))));
writer = outFactory.createXMLStreamWriter(output);
writer.writeStartDocument();
writer.writeStartElement("documents");
writer.writeCharacters("\n");
//create document and transformer
doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
//loop through input.xml
for (int i=0; i<3; i++) {
//call method to get <doc> element
DocumentFragment docElement = getNextElement("doc");
//transform retreived <doc> xmlfragment into output.xml
transformer.transform(new DOMSource(docElement), new StreamResult(output)); //USING STREAMRESULT AS StAXResult WILL IGNORE TRANSFORMER PROPERTY
System.out.println(docElement);
}
}
catch (Exception e) { e.printStackTrace(); }
}
//method to retreive a fragment of xml identified by the elementTag passed to it, e.g. getNextElement("doc") should return a DocumentFragment <doc>....</doc>
static DocumentFragment getNextElement(String elementTag) {
try {
DocumentFragment frag = doc.createDocumentFragment();
while (reader.hasNext()) {
if (reader.getEventType() == XMLStreamReader.START_ELEMENT && reader.getLocalName().equals(elementTag)) {
System.out.println("Found: " + elementTag);
transformer.transform(new StAXSource(reader), new DOMResult(frag));
return frag;
}
reader.next();
}
System.out.println("Returned empty fragment");
return frag;
}
catch (Exception e) { e.printStackTrace(); }
return null;
}
}
マイサンプルinput.xml
ファイルは次のとおりです。
<?xml version="1.0" ?>
<add>
<doc>
<field name="UID">0000001</field>
<field name="company">New York Corp</field>
<field name="datetime">2000-01-01T07:00:00Z</field>
<field name="title">Research Update</field>
<field name="url">www.green.com</field>
<field name="notice">example notice example notice</field>
</doc>
<doc>
<field name="UID">0000002</field>
<field name="company">London Limited</field>
<field name="datetime">2001-01-01T07:00:00Z</field>
<field name="title">Warning</field>
<field name="url">www.purple.com</field>
<field name="notice">test 123</field>
</doc>
<doc>
<field name="UID">0000003</field>
<field name="company">Tokyo PLC</field>
<field name="datetime">2004-01-01T07:00:00Z</field>
<field name="title">Results</field>
<field name="url">www.red.com</field>
<field name="notice">These reults</field>
</doc>
</add>
なお、結果はMacによって異なりますハインズDebian Wheezy(7.8)では、Javaバージョン "1.8.0_45"を使用すると、結果は期待通りです。つまり、入力はチャンクで取得され、出力ファイルに供給されます。
Debian Jessie(8.5)では、Javaバージョン "1.8.0_101"を使用して、反復転送が発生するたびに上記のNullPointerExceptionを取得します。同じマシン上でJava 1.8.0_45をコンパイルして実行しても、壊れています。これは、OSに依存するのではなく、Javaの問題でエラータイプが与えられているように感じます。しかし、私のデバッグの試みはどこにも届かない。
私は、これは直感的に見つけることはありませんむしろ秘密です。また、これは見た目から、DOMツリー(ap.selectXPath(...)を指定)にドキュメント全体を解析するようです。それは大きなデータのためのオプションではないかもしれません。 –