0

私は巨大なXMLを持っています。そのファイルを解析し、すべて<elem/>を単一の文字列として取得してデータベースに保存する必要がありますが、ファイルが巨大になる可能性があるため(〜500MB)、メモリフットプリントの低いメソッドを使用します。どうやってするか ?私はそれを行う使用可能な例を探しています。以下の例と私のあまり良くない解決策:

<?xml version="1.0" encoding="UTF-8"?>
<doc>
  <header>...<header>
  <elem>
     <a/><b/><c>...</c>
  </elem>
  <elem>
     <a>...</a><b/><c>...</c>
  </elem>
  <elem>
     <a>...</a>
  </elem>
  ...
</doc>

分割後:

{'<elem/>', '<elem/>', ...}

今、私は以下のようにSAX DefaultHandlerを使用していますが、良い解決策ではないと思います:

class DataFileParser extends DefaultHandler {

        StringBuffer sb; 
        boolean sElem = false; // is elem

        ...

        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
                if(sElem) {
                    sb.append("<"+qName+">");
                }
                if (qName.equalsIgnoreCase("elem")) {
                    sb = new StringBuffer();
                    sb.append("<"+qName+">");
                    sElem = true;
                }
                ...
        }               

        public void endElement(String uri, String localName, String qName) throws SAXException {
                if (qName.equalsIgnoreCase("elem")) {
                    sElem = false;
                    sb.append("</"+qName+">");
                }
                ...
        }

        public void characters(char ch[], int start, int length) throws SAXException {
              if(sElem) {
                   sb.append(new String(ch, start, length));
               }
        }


 ...
}
4

2 に答える 2

1

実際、SAX パーサーを使用することは優れたソリューションです。でデータベースに直接書き込むことを検討することもできますendElement。ただし、すべてを一度に書き込む必要がある場合 (単一の CLOB など)、使用するパーサーに関係なく、どこかに保存する必要があります。そのために一時ファイルを入れることができます。

いずれにせよ、SAX パーサーは最も効率的なソリューションです。メモリ フットプリントは、パーサーの実装ではなく、処理するデータの量に大きく依存するためです。

于 2012-04-26T04:54:46.700 に答える
1

低レベルの Java コードを書きたくない場合は、他の解決策があります。たとえば、Saxon-EE では、次のストリーミング変換でうまくいきます。

<xsl:stylesheet xmlns="http://www.w3.org/1999/XSL/Transform"
   xmlns:saxon="http://saxon.sf.net/" 
   version="3.0">

<xsl:template name="main">
  <xsl:for-each select="saxon:stream(doc('big.xml'))/*/elem">
    <xsl:result-document href="out{position()}.xml">
      <xsl:copy-of select="."/>
    </xsl:result-document>
  </xsl:for-each>
</xsl:template>

</xsl:stylesheet>
于 2012-04-26T08:31:59.407 に答える