XMLファイルを解析してコンテンツを別のファイルの特定の場所にコピーしますか?

XMLファイルを解析してコンテンツを別のファイルの特定の場所にコピーしますか?

XMLファイルがあり、(client_23.xml)他のXMLファイルの内容に基づいて特定のセクションに数行を追加する必要があります(abc_lop.xml)

ここに私のファイルに、およびを含むabc_lop.xml多くの行を見ることができます。ClientFieldnamepptypedataType

<Hello version="100">
 <DataHolder numberOfFields="67">
  <ClientField name="target" pptype="aligning" dataType="string">
   <Value value="panel_3646"/>
   <Value value="panel_3653"/>
  </ClientField>
  <ClientField name="category_3652_0_count" pptype="symetrical" dataType="double"/>
  <ClientField name="category_3652_2_count" pptype="symetrical" dataType="double"/>
  <ClientField name="category_3646_0_count" pptype="symetrical" dataType="double"/>
  <ClientField name="pme.cdert" pptype="symetrical" dataType="double"/>
  <ClientField name="pme.age" pptype="symetrical" dataType="double"/>
  <ClientField name="category_3648_1_count" pptype="symetrical" dataType="double"/>
  <ClientField name="pme.number" pptype="symetrical" dataType="double"/>
  <ClientField name="pme.gender" pptype="aligning" dataType="string">
   <Value value=""/>
   <Value value="F   "/>
   <Value value="NA"/>
  </ClientField>
  <ClientField name="pme.status" pptype="aligning" dataType="string">
   <Value value=""/>
   <Value value="A"/>
   <Value value="S"/>
   <Value value="NA"/>
  </ClientField>
  <ClientField name="pme.selling_id" pptype="aligning" dataType="string">
   <Value value="c0"/>
   <Value value="c1"/>
   <Value value="NA"/>
  </ClientField>
 </DataHolder>
</Hello>

このファイルを読み、nameこの行から抽出する必要がありますClientField。そうでない場合は、pptypealigning名前に対してこの行を構成する必要があります。以下は2つの名前の例です。最初の値だけが異なります。ただし、他の2つの値は常に同じです。

<eval>upsert("category_3652_0_count", 0, $calty_doubles)</eval>
<eval>upsert("category_3652_2_count", 0, $calty_doubles)</eval>

それでは、次pptypealigningような行を作成してください。

<eval>upsert("target", "NA", $calty_strings)</eval>
<eval>upsert("pme.gender", "NA", $calty_strings)</eval>

client_23.xmlファイルにこれらのすべての変更を適用し、それを使用して新しいファイルを作成する必要がある場合は、新しいファイルが次のように表示されます。名前付きの関数があり、上記のdata_values内容をタグに追加する必要があります。<block>下の写真。

    <function>
        <name>data_values</name>
        <variables>
            <variable>
            <name>temp</name>
            <type>double</type>
            </variable>
        </variables>
        <block>
            <eval>temp = 1</eval>
            <eval>upsert("category_3652_0_count", 0, $calty_doubles)</eval>
            <eval>upsert("category_3652_2_count", 0, $calty_doubles)</eval>
            <eval>upsert("target", "NA", $calty_strings)</eval>
            <eval>upsert("pme.gender", "NA", $calty_strings)</eval>             
        </block>
    </function>

これはclient_23.xml現在ファイル内の内容なので、追加すると次のようになります。

    <function>
        <name>data_values</name>
        <variables>
            <variable>
            <name>temp</name>
            <type>double</type>
            </variable>
        </variables>
        <block>
            <eval>temp = 1</eval>
        </block>
    </function>

以前、terdonが助けてくれた非常に単純なシェルスクリプトがあります。ここでは、以下のようにperlスクリプトを使用します。ファイルにヘッダーとフッターを追加してabc_lop.xml変数fileに保存し、そのファイル値を使用してclient_23.xmlファイルの特定のセクションに配置しますが、上記の操作を実行する方法がわかりません。

スクリプト:-

for word in $client_types
do
    ## Concatenate the header, the contents of the target file and the
    ## footer into the variable $file.
    file=$(printf '%s\n%s\n%s' "$header" "$(cat "$path/${word}_lop.xml")" "$footer")

    ## Edit the target file and print
    perl -0pe "s#<eval>planting_model = 0</eval>#<eval>planting_model = 1</eval> s#<trestra-config>.* </trestra-config>##sm;   s#<function>\s*<name>DUMMY_FUNCTION.+?</function>#$file#sm" client_"$client_id".xml > "$word"_new_file.xml
done

ここではclient_types次のようになります。 23abc def pqrです$client_id

さて、上記の機能を追加する必要がありますが、どのように簡単にできるか疑問に思います。

ベストアンサー1

重複する質問を削除する前にStack Overflowに投稿しようとしたPerlソリューションは次のとおりです。

use strict;
use warnings;

use XML::LibXML;

# Open the main XML file and locate the
# <block> element that we need to insert into
#
my $doc = XML::LibXML->load_xml(
    location => 'client_23.xml',
    no_blanks => 1,
);
my $block = $doc->find('/function/block')->get_node(1);

# Open the secondary XML file and find all the <ClientField> elements
# that contain the data we need to insert
#
my $abc = XML::LibXML->load_xml(location => 'abc_lop.xml');

for my $field ( $abc->find('/Hello/DataHolder/ClientField')->get_nodelist ) {

    my ($name, $pptype) = map $field->getAttribute($_), qw/ name pptype /;

    my $text = $pptype eq 'aligning' ?
        sprintf q{upsert("%s", "NA", $calty_strings)}, $name :
        sprintf q{upsert("%s", 0, $calty_doubles)}, $name;

    $block->appendTextChild('eval' , $text);
}

print $doc->toString(2);

出力

<?xml version="1.0"?>
<function>
  <name>data_values</name>
  <variables>
    <variable>
      <name>temp</name>
      <type>double</type>
    </variable>
  </variables>
  <block>
    <eval>temp = 1</eval>
    <eval>upsert("target", "NA", $calty_strings)</eval>
    <eval>upsert("category_3652_0_count", 0, $calty_doubles)</eval>
    <eval>upsert("category_3652_2_count", 0, $calty_doubles)</eval>
    <eval>upsert("category_3646_0_count", 0, $calty_doubles)</eval>
    <eval>upsert("pme.cdert", 0, $calty_doubles)</eval>
    <eval>upsert("pme.age", 0, $calty_doubles)</eval>
    <eval>upsert("category_3648_1_count", 0, $calty_doubles)</eval>
    <eval>upsert("pme.number", 0, $calty_doubles)</eval>
    <eval>upsert("pme.gender", "NA", $calty_strings)</eval>
    <eval>upsert("pme.status", "NA", $calty_strings)</eval>
    <eval>upsert("pme.selling_id", "NA", $calty_strings)</eval>
  </block>
</function>

おすすめ記事