2

バックグラウンド

XML ファイルを構成および設定情報の入力として使用する Perl アプリケーションを設計しています。ドキュメントの階層があり、グローバル データがよりローカルな情報によって上書きされます。

私のプログラムは、より一般的なファイルへのパスを含む最もローカルな設定ファイルで呼び出されます。一部のローカル設定は絶対的であり、これらはプログラムでハードコードされます。

初期化タスクは、最上位レベルから呼び出しの設定を取得し、それらを読み取ってから各レベルに進み、それらを単一の XML ドキュメントとしてマージ/結合することです。

サンプルデータ

Global_layouts_100.xml

<CONFIG>
    <GRP1>
        <FIELD foo="abs" format="%.4f">QTY</FIELD>
        <FIELD default="" format="%.2f">COST</FIELD>
        <FIELD default="0" format="%.2f">AMT</FIELD>
        <FIELD default="1960-01-01" format="YYYMMDD">TRANDATE</FIELD>
        <FIELD>ACCOUNT</FIELD>
        <FIELD default="0">ACCT_TYPE</FIELD>
    </GRP1>
    <GRP2>
        <FIELD> 1 </FIELD>
        <FIELD> 2 </FIELD>
        <FIELD> 3 </FIELD>
    </GRP2>
</CONFIG>

Global_properties_100.xml

<CONFIG>
    <CUS>
        <GRP>GRP1</GRP>
        <HDR>CUSTOMER</HDR>
        <TLR>TLR${cnt}</TLR>
    </CUS>
    <XYZ>
        <GRP>GRP2</GRP>
        <HDR>ACCOUNTS</HDR>
        <TLR>TLR${cnt}</TLR>
    </XYZ>
</CONFIG>

Global_70.xml

<CONFIG>
<PARENT_SETTINGS>Global_layouts_100</PARENT_SETTINGS>
<PARENT_SETTINGS>Global_properties_100</PARENT_SETTINGS>
    <LOOKUPS>
        <MAP type="file">
            <NAME>ACCT_TYPE_LOOKUP</NAME>
            <PATH>${PATH}acct_type.csv</PATH>
            <HEADERS>
                <COLUMN>ACCT_TYPE</COLUMN>
                <COLUMN>SOURCE_VALUE</COLUMN>
            </HEADERS>
            <KEYS>
                <COLUMN>SOURCE_VALUE</COLUMN>
            </KEYS>
        </MAP>
    </LOOKUPS>
</CONFIG>

local.xml

<CONFIG>
    <PARENT_SETTINGS>Global_70</PARENT_SETTINGS>
    <BATCH>
        <CUS>
            <SRCFILE type="csv" delimiter="|">/path/to/src_file</SRCFILE>
            <OUTFILE>/path/to/out_file</OUTFILE>
            <FIELDS>
                <CUSTOMER>&CUSTOMER;</CUSTOMER>
                <QTY default="0.0" col="23"></QTY>
                <COST format="%.4f" col="21"></COST>
                <FEE col="18"></FEE>
            </FIELDS>
        </CUS>
        <XYZ>
            <SRCFILE />
            <OUTFILE />
            <FIELDS>
                <FIELD_1 />
                <FIELD_2 />
                <FIELD_3 />
                <FIELD_4 />
                <FIELD_5 />
            </FIELDS>
        </XYZ>
    </BATCH>
</CONFIG>

ここで、プログラムを開始する local.xml と、処理する引数として CUS が与えられる場合、この XML (または同等の perl データ構造) を確認したいと思います。

<CONFIG>
    <HDR>CUSTOMER</HDR>
    <TLR>TLR${cnt}</TLR>
    <SRCFILE type="csv" delimiter="|">/path/to/src_file</SRCFILE>
    <OUTFILE>/path/to/out_file</OUTFILE>
    <LOOKUPS>
        <MAP type="file">
            <NAME>ACCT_TYPE_LOOKUP</NAME>
            <PATH>${PATH}acct_type.csv</PATH>
            <HEADERS>
                <COLUMN>ACCT_TYPE</COLUMN>
                <COLUMN>SOURCE_VALUE</COLUMN>
            </HEADERS>
            <KEYS>
                <COLUMN>SOURCE_VALUE</COLUMN>
            </KEYS>
        </MAP>
    </LOOKUPS>
    <CUS>
        <FIELD foo="abs" format="%.4f" default="0.0" col="23">QTY</FIELD>
        <FIELD default="" format="%.4f" col="21">COST</FIELD>
        <FIELD default="0" format="%.2f">AMT</FIELD>
        <FIELD default="1960-01-01" format="YYYMMDD">TRANDATE</FIELD>
        <FIELD>ACCOUNT</FIELD>
        <FIELD default="0">ACCT_TYPE</FIELD>
        <FIELDS>
            <CUSTOMER>&CUSTOMER;</CUSTOMER>
            <QTY default="0.0" col="23"></QTY>
            <COST format="%.4f" col="21"></COST>
            <FEE col="18"></FEE>
        </FIELDS>
    </CUS>
</CONFIG>

そして、プログラムが開始する local.xml と、処理する引数として XYZ が与えられる場合、私はこの XML (または同等の perl データ構造) を見たいと思います:

<CONFIG>
    <HDR>ACCOUNTS</HDR>
    <TLR>TLR${cnt}</TLR>
    <SRCFILE />
    <OUTFILE />
    <LOOKUPS>
        <MAP type="file">
            <NAME>ACCT_TYPE_LOOKUP</NAME>
            <PATH>${PATH}acct_type.csv</PATH>
            <HEADERS>
                <COLUMN>ACCT_TYPE</COLUMN>
                <COLUMN>SOURCE_VALUE</COLUMN>
            </HEADERS>
            <KEYS>
                <COLUMN>SOURCE_VALUE</COLUMN>
            </KEYS>
        </MAP>
    </LOOKUPS>
    <XYZ>
        <FIELD> 1 </FIELD>
        <FIELD> 2 </FIELD>
        <FIELD> 3 </FIELD>
        <FIELDS>
            <FIELD_1 />
            <FIELD_2 />
            <FIELD_3 />
            <FIELD_4 />
            <FIELD_5 />
        </FIELDS>
    </XYZ>
</CONFIG>

質問

これらの XML ドキュメントをマージする最も効率的な方法は何ですか?

によって返されたデータ構造を使用して自分で実行できますかXML::Simple、それとも他の XML ツールを使用する必要がありますか?

私の質問が十分に明確で、サンプル XML データを必要としないことを願っています。何かを見る必要がある場合は、サンプルのものを投稿できます。

簡単に言えば、個々の XML ドキュメントの階層をマージする最善の方法は何かということです。

4

2 に答える 2

2

序文: 私は Perl について何も知りませんが、1 つのオプションは、宣言型の専用言語である XSLT を使用して XML ドキュメントのスタイルを設定/変換することです。

PHP (やや Perl の子孫)、Python、Java、C# などのほとんどの言語は、XML ライブラリと同様に XSLT 変換を維持しています。したがって、 XSLT ファイルを使用してドキュメントをマージするPerl XSLTプロセッサを適用することを検討してください (特定のノードを指定できます)。

サンプル データを使用すると、以下のスタイルシートは CUS と XYZ の最終的な XML 構造をレンダリングします。すべての派生 XML を同じディレクトリに保持してください。

CUS バージョン

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

 <xsl:template match="CONFIG">

    <xsl:copy> 
         <xsl:copy-of select="document('Global_properties_100.xml')/CONFIG/CUS/HDR" />
         <xsl:copy-of select="document('Global_properties_100.xml')/CONFIG/CUS/TLR" />
         <xsl:copy-of select="BATCH/CUS/SRCFILE" />
         <xsl:copy-of select="BATCH/CUS/OUTFILE" />
         <xsl:copy-of select="document('Global_70.xml')/CONFIG/LOOKUPS" />
         <CUS>
            <xsl:copy-of select="document('Global_layouts_100.xml')/CONFIG/GRP1/*" />
            <xsl:copy-of select="BATCH/CUS/FIELDS" />
         </CUS>
    </xsl:copy>

 </xsl:template> 

</xsl:transform>

XYZバージョン

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

 <xsl:template match="CONFIG">

    <xsl:copy> 
         <xsl:copy-of select="document('Global_properties_100.xml')/CONFIG/XYZ/HDR" />
         <xsl:copy-of select="document('Global_properties_100.xml')/CONFIG/XYZ/TLR" />
         <xsl:copy-of select="BATCH/XYZ/SRCFILE" />
         <xsl:copy-of select="BATCH/XYZ/OUTFILE" />
         <xsl:copy-of select="document('Global_70.xml')/CONFIG/LOOKUPS" />
         <CUS>
            <xsl:copy-of select="document('Global_layouts_100.xml')/CONFIG/GRP2/*" />
            <xsl:copy-of select="BATCH/XYZ/FIELDS" />
         </CUS>
    </xsl:copy>

 </xsl:template> 

</xsl:transform>
于 2015-09-06T20:10:08.427 に答える
2

いくつかのサンプル データを使用してより具体的な例を示すことができますが、これに近づくときは を使用する傾向がありますXML::Twig

具体的には、 andXML::Twigのサポートが組み込まれているため、新しいドキュメント ツリーを構築し、必要な要素を必要な順序で保持できます。cutpaste

このようなもの:

#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;

my $twig = XML::Twig -> parse ( \*DATA );

my $newdoc = XML::Twig -> new ('pretty_print' => 'indented_a');
$newdoc -> set_root ( XML::Twig::Elt -> new ( 'new_root_here' ) );
$newdoc -> set_xml_version ('1.0');
$newdoc -> set_encoding('utf-8'); 

foreach my $value_elt ( $twig -> findnodes ( '//value' ) ) {
    $value_elt -> cut;
    $value_elt -> paste ( $newdoc -> root );
}


$newdoc -> print;

__DATA__
<root>
   <value>fish</value>
   <dont_copy>this thing</dont_copy>
</root>

(別の例があります: 2 つの XML ファイルのデータを同じ構造に結合するにはどうすればよいですか? )

于 2015-09-07T09:08:47.793 に答える