![XML 파일을 구문 분석하여 콘텐츠를 다른 파일의 특정 위치에 복사하시겠습니까?](https://linux55.com/image/73168/XML%20%ED%8C%8C%EC%9D%BC%EC%9D%84%20%EA%B5%AC%EB%AC%B8%20%EB%B6%84%EC%84%9D%ED%95%98%EC%97%AC%20%EC%BD%98%ED%85%90%EC%B8%A0%EB%A5%BC%20%EB%8B%A4%EB%A5%B8%20%ED%8C%8C%EC%9D%BC%EC%9D%98%20%ED%8A%B9%EC%A0%95%20%EC%9C%84%EC%B9%98%EC%97%90%20%EB%B3%B5%EC%82%AC%ED%95%98%EC%8B%9C%EA%B2%A0%EC%8A%B5%EB%8B%88%EA%B9%8C%3F.png)
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
이름에 대해 이 줄을 구성해야 합니다. 아래는 두 이름의 예입니다. 첫 번째 값만 다릅니다. 단, 다른 두 값은 항상 같은.
<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
다음과 같습니다. 23 abc 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