2017-10-14 11 views
0

ファイルをXSLTで変換したいです。 私が作っ:この理由は何OutOfMemoryError:XSLT変換を使用したJavaヒープスペース

transformer.transform(text, new StreamResult(new File(getOutputFileName()))); 

とそれができる:この行で

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 
at com.sun.org.apache.xml.internal.utils.FastStringBuffer.append(FastStringBuffer.java:682) 
at com.sun.org.apache.xml.internal.dtm.ref.sax2dtm.SAX2DTM.characters(SAX2DTM.java:2111) 
at com.sun.org.apache.xalan.internal.xsltc.dom.SAXImpl.characters(SAXImpl.java:863) 
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.characters(AbstractSAXParser.java:546) 
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:455) 
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:841) 
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:770) 
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141) 
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213) 
at com.sun.org.apache.xalan.internal.xsltc.dom.XSLTCDTMManager.getDTM(XSLTCDTMManager.java:421) 
at com.sun.org.apache.xalan.internal.xsltc.dom.XSLTCDTMManager.getDTM(XSLTCDTMManager.java:215) 
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.getDOM(TransformerImpl.java:556) 
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:739) 
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:351) 
at ru.magnit.task.utils.AbstractXmlUtil.transformXML(AbstractXmlUtil.java:66) 
at ru.magnit.task.EntryPoint.main(EntryPoint.java:72) 

:入力ファイルを約10000000ラインを持っている

TransformerFactory factory = TransformerFactory.newInstance(); 
    InputStream is = 
this.getClass().getResourceAsStream(getPathToXSLTFile()); 
    Source xslt = new StreamSource(is); 
    Transformer transformer = factory.newTransformer(xslt); 
    Source text = new StreamSource(new File(getInputFileName())); 
    transformer.transform(text, new StreamResult(new File(getOutputFileName()))); 

が、私はエラーを持っています何とか、ヒープのサイズなしで最適化されますか?

UPDATE: マイXSLTファイル:完全なXPathナビゲーションを可能にするために、ツリーモデルに完全なXML入力を引っ張るデータモデルと一般的なXSLT 1.0と2.0の仕事で

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:output method="xml" indent="yes"/> 

<xsl:template match="entries"> 
    <entries> 
     <xsl:apply-templates/> 
    </entries> 
</xsl:template> 

<xsl:template match="entry"> 
    <entry> 
     <xsl:attribute name="field"> 
      <xsl:apply-templates select="*"/> 
     </xsl:attribute> 
    </entry> 
</xsl:template> 

答えて

2

その結果、入力文書のサイズとともに増加するメモリ使用量が生じる。

現在のドキュメントサイズがメモリ不足につながる場合は、ヒープスペースを増やさない限り、あまり一般的ではありませんが、具体的なXSLTに応じてXSLTプロセッサ固有のものとXSLT固有のものがありますコードを作成することはできますが、最初に完全な文書をプルすることは避けられません。 XSLTを最適化できるかどうかを調べるには、XSLTを確認する必要があります。スタイルシートのプロファイリングは、最適化する領域を特定するのに役立ちます。私は、Xalanがそれをサポートしているかどうかはわかりません。スタックトレースは、大量の入力用にDTM(ツリーモデル)を構築するときにXalanがすでにメモリ不足になっていることを意味しているわけではありません。その場合、XSLTコードを最適化することは実行されない。

あなたのスタイルシートからSAXフィルタを作成し、それをデフォルトのTransformerでチェーン化してフィルタの結果をシリアル化する代わりに、https://docs.oracle.com/javase/8/docs/api/javax/xml/transform/sax/SAXTransformerFactory.htmlを使用することができます。 Transformerを使用した従来のアプローチよりも少ないメモリを消費します。

XSLT 3.0は新しいストリーミングアプローチ(https://www.w3.org/TR/xslt-30/#streaming-concepts)でメモリ問題を解決しようとしていますが、これまでのところ商用製品であるSaxon 9 EEでは実装が1つしかありません。一般に、スタイルシートは必ずしもストリーミング可能ではなく、ストリーミング可能にするために書き直す必要があります(ストリーミングで入力ノードのソートが不可能な場合など)。

例えば、(唯一のストリーミングとしてデフォルトモードを設定するために必要な必要がない書き換え、)ストリーミングを使用するXSLT 3.0に変換し、あなたの投稿スタイルシートが

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:math="http://www.w3.org/2005/xpath-functions/math" 
    exclude-result-prefixes="xs math" 
    version="3.0"> 

    <xsl:mode streamable="yes"/> 

    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="entries"> 
     <entries> 
      <xsl:apply-templates/> 
     </entries> 
    </xsl:template> 

    <xsl:template match="entry"> 
     <entry> 
      <xsl:attribute name="field"> 
       <xsl:apply-templates select="*"/> 
      </xsl:attribute> 
     </entry> 
    </xsl:template> 

</xsl:stylesheet> 

とサクソン9.8 EEとExseltのベータ版ですそれをストリーミング可能と評価する。

+0

私は 'XSLT'ファイルを追加しました。pleaseを参照してください –

+1

Saxon-EEでこの作業を行うには、Javaコードを少し変更して、使用するTransformerFactoryがSaxonのインスタンス'StreamableTransformerFactory'クラスです。 –

関連する問題