2

大量の非常に大きな XML ファイルを処理し、各要素を深さ優先で読み取る必要があります。サイズが原因で、どのようなDOM解決策も論外であり、必要な実際の要素が「リーフ」で​​はなくその親であるという事実によって、事態はさらに複雑になります。

より具体的には、ファイルは次のような構造を持っています

    <Level 1>
        ...
        <Level 2>
            ...
            <Level N-1>
                <value>...</value>
                <value>...</value>
                ...
                <value>...</value>
            </Level N-1>
            <Level N-1>
                <value>...</value>
                <value>...</value>
                ...
                <value>...</value>
            </Level N-1>
            ...
            <Level N-1>
                <value>...</value>
                <value>...</value>
                ...
                <value>...</value>
            </Level N-1>
            ...
        </Level 2>
    </Level 1>

上記のような各ファイルから、<Level N-1>要素を個別に読み取る必要があります (それぞれに対応するすべての<value>要素が含まれます)。深さ はN、各ファイル内およびファイル間で異なるため、XMLタグ名と同様に本質的に不明です。より高いレベルにも要素が存在するという事実によって、事態はさらに複雑<value>になります (つまり、それらLevel Nは達成された保証を構成するものではありません)。

特定の深さで XML 要素全体を文字列として読み取るための簡単な解決策は、次のようなものです。

int level = 0;  // The base level of the element, could be at any depth
Reader in = ... // The reader to the input
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
PrintStream out = new PrintStream(outStream);
XMLEventReader reader = XMLInputFactory.newInstance().createXMLEventReader(in);
XMLEventWriter writer = XMLOutputFactory.newInstance().createXMLEventWriter(out);
XMLEvent event;

while ((level > 0) && reader.hasNext());
{
    event = reader.nextEvent();

    if (event.isStartElement())
    {
        level++;
    }
    else if (event.isEndElement())
    {
        level--;
    }

    writer.add(event);
}

writer.flush();

String element = new String(outStream.toByteArray());

ただし、呼び出し元のコードがLevel N-1要素に到達したことを認識せず、次の要素に進む場合、上記は役に立ちません。Level N<value>

SAXソリューションは理想的ですが、XSLTテンプレートを介してファイルを前処理することさえ許容されます。

何か案は?

4

2 に答える 2

3

XSLT プロセッサ (1.0 または 2.0) は通常、メモリ内の XML ドキュメント全体の表現 (必ずしも DOM ではない) を生成するため、純粋な XSLT 1.0 または XSLT 2.0 では必要な XSLT 前処理は実行できません。

XSLT 3.0 (まだ WD)では、言語の一部としてストリーミングがありますが、これはまだ W3C XSLT WG によって活発に開発されており、仕様はまだ安定していません。

Saxon には、「ストリーミング可能モード」のストリーミング テンプレートの形式でストリーミング拡張機能があります。

<xsl:mode name="s" streamable="yes"/>

これを使用すると、「レベル N-1」要素をルートとするサブツリーのみを含む XML ドキュメントを作成できます。

于 2012-09-19T13:03:32.300 に答える
1

私があなたの問題を正しく理解していれば、タグに到達したとき<value>とレベルタグを読み終わったときを区別するのが難しいでしょう。

イベントを認識すると、名前などの詳細情報を取得できます。

  if (event.isStartElement()) {
    StartElement element = (StartElement) event;
    System.out.println("Start Element: " + element.getName());
  }

本当に欲しいのがこの前の最後のレベルである場合は、もちろんそれを保持する必要があります.

于 2012-09-19T13:45:36.027 に答える