2016-08-16 10 views
1

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の問題でエラータイプが与えられているように感じます。しかし、私のデバッグの試みはどこにも届かない。

答えて

0

これは、それはあなたが提示したコードよりもずっと簡単で直感的です... XPathとVTD-XMLで分割を行うための私のコードです....

import com.ximpleware.*; 
import java.io.*; 
public class splitXML { 
    public static void main(String[] args) throws VTDException, IOException { 
     VTDGen vg = new VTDGen(); 
     if (!vg.parseFile("d:\\xml\\input.xml", false)){ 
      System.out.println("error"); 
      return; 
     } 
     VTDNav vn = vg.getNav(); 
     AutoPilot ap = new AutoPilot(vn); 
     ap.selectXPath("/add/doc"); 
     int i=0,n=0; 
     FileOutputStream fos =null; 
     while((i=ap.evalXPath())!=-1){ 
      fos = new FileOutputStream("d:\\xml\\output"+(++n)+".xml"); 
      long l = vn.getElementFragment(); 
      fos.write(vn.getXML().getBytes(), (int)l, (int)(l>>32)); 
      fos.close(); 
     } 
    } 
} 
+0

私は、これは直感的に見つけることはありませんむしろ秘密です。また、これは見た目から、DOMツリー(ap.selectXPath(...)を指定)にドキュメント全体を解析するようです。それは大きなデータのためのオプションではないかもしれません。 –

関連する問題