
XMLファイルがあり、(client_23.xml)
他のXMLファイルの内容に基づいて特定のセクションに数行を追加する必要があります(abc_lop.xml)
。
ここに私のファイルに、およびを含むabc_lop.xml
多くの行を見ることができます。ClientField
name
pptype
dataType
<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
。そうでない場合は、pptype
各aligning
名前に対してこの行を構成する必要があります。以下は2つの名前の例です。最初の値だけが異なります。ただし、他の2つの値は常に同じです。
<eval>upsert("category_3652_0_count", 0, $calty_doubles)</eval>
<eval>upsert("category_3652_2_count", 0, $calty_doubles)</eval>
それでは、次pptype
のaligning
ような行を作成してください。
<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>
答え2
しかし、Perlの代わりにPythonを使用してXMLをすばやく変更することを好みます。たとえば、
import xml.etree.ElementTree as ET
file1 = sys.argv[1]
file2 = sys.argv[2]
abc = ET.parse(file1).getroot()
xml2 = ET.parse(file2).getroot()
# For ClientField[name] properties
l = []
block = xml2.find('block')
for node in abc.findall("*/ClientField"):
if node.attrib['pptype'] == 'aligning':
ET.SubElement(block, 'eval').text = 'upsert("' + node.get('name') + '", "NA", $calty_strings)'
else:
ET.SubElement(block, 'eval').text = 'upsert("' + node.get('name') + '", 0, $calty_doubles)'
print(ET.tostring(xml2))
これにより、以下が提供されます。
<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>
編集する:shellスクリプトは次のとおりです。
client_id=23
for word in $client_types
do
python converter.py $path/${word}_lop.xml client_"$client_id".xml
done