1

その場で XSD を使用して最終結果を検証しながら、いくつかの CSV ファイル (それぞれが 600 MB を超える) を XML に変換する必要があります。

各ファイルのサイズのため、InputStreams を使用してコンテンツを読み取り、OutpuStreams を使用して結果をクライアントに XML としてストリーミングしています。

それでは、簡単な部分から始めましょう... (疑似コード)

void transform(final InputStream CSVCustomerStream, final OutputStream outputStream) {
       outputStream.write("<customers>")
       foreach csvCustomerRow in CSVCustomerStream {
            String xmlCustomerRow = csvCustomerRow.toXML();
            outputStream.write(xmlCustomerRow.getBytes();
       }
       outputStream.write("</customers>")

       **MISSING_XMLVALIDATOR.parse(outputStream);**
}

これまでのところ、ソース CSV ファイルの各行は xml に変換されてから、出力ストリームに書き込まれます。

簡単です。

ただし、xml が実際に検証される部分はまだありません。

このために、私はXMLReaderの parse() メソッドを調べました。それに関する唯一の問題は、parse() が InputSources のみを受け入れるという事実ですが、同時に、検証したいコンテンツを OutputStream にストリーミングしています。

もちろん、CSV コンテンツ全体を読み取った後、次の方法で OutputStream を InputStream に変換できます。

 new ByteArrayInputStream((outputstream).toByteArray())

しかし、それではすぐに 600 MB 相当の XML がメモリに戻され、ストリーミングの目的全体に逆らってしまいます。

PS: コードは REST Web サービスとして実行されるため、OutputStream の正確な実装を制御することはできません。

    return Response.ok(new StreamingOutput() {
        @Override
        public void write(OutputStream output) throws Exception {
            ....     loading and transforming csv ...

        }
    }).build();
4

2 に答える 2

1

あなたのコメントに基づいて、XSDがロシア人形として作成される「最悪の」シナリオを提案させてください(つまり、ドキュメントルートを除いて、他のすべての要素とタイプはローカルで定義されます)。このスタイルのため、XSD に対して xmlCustomerRow を検証する方法はありません。これは、タグに一致するグローバル要素宣言がないためです (想定customer)。

<?xml version="1.0" encoding="utf-8" ?>
<!-- XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com) -->
<xsd:schema targetNamespace="http://tempuri.org/XMLSchema.xsd" xmlns="http://tempuri.org/XMLSchema.xsd" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="customers">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="customer" minOccurs="0" maxOccurs="unbounded">
                    <xsd:complexType>

                    </xsd:complexType>
                </xsd:element>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

それでも、解決策はそれほど複雑ではありません。この変更された XSD を見てください。

<?xml version="1.0" encoding="utf-8" ?>
<!-- XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com) -->
<xsd:schema targetNamespace="http://tempuri.org/XMLSchema.xsd" xmlns="http://tempuri.org/XMLSchema.xsd" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="customers">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="customer" minOccurs="0" maxOccurs="unbounded">
                    <xsd:complexType>

                    </xsd:complexType>
                </xsd:element>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
    <xsd:element name="customer">
        <xsd:complexType>

        </xsd:complexType>
    </xsd:element>
</xsd:schema>

このセットアップでは、元の XSD を XML として開き、customer要素を複製し、その minOccurs/maxOccurs 属性を削除してから、それを の子として挿入するだけですschema(XML のドキュメント要素になります)。ここでのアイデアは、リファクタリングをその場で、または手動で行うことができるということです。

何もする必要がない可能性が常にあります。つまり、customer要素がすでにグローバルである場合は、次のようになります。

<?xml version="1.0" encoding="utf-8" ?>
<!-- XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com) -->
<xsd:schema targetNamespace="http://tempuri.org/XMLSchema.xsd" xmlns="http://tempuri.org/XMLSchema.xsd" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="customers">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="customer" minOccurs="0" maxOccurs="unbounded"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
    <xsd:element name="customer">
        <xsd:complexType>

        </xsd:complexType>
    </xsd:element>
</xsd:schema>

XSD が実際にどのように見えるかによっては、他の複雑な問題が発生する可能性がありますが、目的を正確に達成するために必要なリファクタリングを実行することを妨げるものは何もないことを保証できます。

私はむしろ、各レコードを個別に検証する機能を持つことは、他の何よりも優れているという意見です. さらに、マルチコア/CPU マシンで実行されている大規模なファイルの場合、検証を並列化できます。これにより、リソースをより効率的に使用してスループットを向上させることができます。

于 2013-02-23T14:49:17.400 に答える
1

変換によって、指定された XSD で検証される XML が生成されるか、(Petru Gardea がコメントで述べたように) 一時的な文字列を使用して断片的に検証できることを確認するには、テストで十分である可能性があります。

しかし、実際にオンザフライで検証する必要があると仮定すると、基本的にストリームを操作することで、いくつかのトリックを試すことができます。

OutputStreamおそらくクライアントに送信したい を作成しており、 を必要とする方法を知っているプロセスがありますInputStream(実際には、Readerインターフェイスによって一部が簡単になる場合がありますが、修正は並行しています)。

つまりOutputStream、1 つのストリームをクライアントに送信し、そのコピーを検証解析に使用できるように、オンザフライで複製する必要があります。InputStreamそして、コピーした からを取得する必要がありますOutputStream

「tee」プロセスについては、Apache Commons TeeOutputStreamを検討する必要があり、出力から入力への変換については、おそらくPipedInputStreamおよびPipedOutputStreamを検討する必要があります。

于 2013-02-23T00:14:50.960 に答える