我对 Perl 还很陌生。我想更新此 XML 文件中与我从文本文件中读取的值相匹配的特定节点值 LocationID
。
示例 XML 文件
<?xml version="1.0" encoding="UTF-8"?>
<TestImportFile xmlns="urn:TestImportFile-schema">
<LOCATION SOURCEID="Yes">
<LOCATIONID>F16-000100</LOCATIONID>
<LOCATIONCATEGORY>UFO ABDUCTEE</LOCATIONCATEGORY>
<LOCAL BIT="Test Case File">
<LOCALNAME>DTG2QP</LOCALNAME>
<ASSIGNEDTO>BearmanJ</ASSIGNEDTO>
<ASSIGNEDTODATETIME>2016-02-02T07:59:00</ASSIGNEDTODATETIME>
<CASE>
<CASEVALUE>21</CASEVALUE>
</CASE>
<CASE>
<CASEVALUE>35</CASEVALUE>
</CASE>
</LOCAL>
<LOCAL BIT="Test Case File">
<LOCALNAME>F4T2557</LOCALNAME>
<READINGBY>BearmanJ</READINGBY>
<READINGDATETIME>2016-04-03T06:48:00</READINGDATETIME>
<CASE>
<CASEVALUE>83</CASEVALUE>
</CASE>
<CASE>
<CASEVALUE>40</CASEVALUE>
</CASE>
</LOCAL>
</LOCATION>
<LOCATION SOURCEID="Yes">
<LOCATIONID>F16-000101</LOCATIONID>
<LOCATIONCATEGORY>UFO ABDUCTEE</LOCATIONCATEGORY>
<LOCAL BIT="Test Case File">
<LOCALNAME>ZGV4TF</LOCALNAME>
<ASSIGNEDTO>BearmanJ</ASSIGNEDTO>
<ASSIGNEDTODATETIME>2016-02-02T07:59:00</ASSIGNEDTODATETIME>
<CASE>
<CASEVALUE>34</CASEVALUE>
</CASE>
<CASE>
<CASEVALUE>67</CASEVALUE>
</CASE>
</LOCAL>
<LOCAL BIT="Test Case File">
<LOCALNAME>E5Y7456</LOCALNAME>
<READINGBY>BearmanJ</READINGBY>
<READINGDATETIME>2016-04-03T06:48:00</READINGDATETIME>
<CASE>
<CASEVALUE>53</CASEVALUE>
</CASE>
<CASE>
<CASEVALUE>20</CASEVALUE>
</CASE>
</LOCAL>
</LOCATION>
<LOCATION SOURCEID="Yes">
<LOCATIONID>F16-000102</LOCATIONID>
<LOCATIONCATEGORY>UFO ABDUCTEE</LOCATIONCATEGORY>
<LOCAL BIT="Test Case File">
<LOCALNAME>ZGV4TF</LOCALNAME>
<ASSIGNEDTO>BearmanJ</ASSIGNEDTO>
<ASSIGNEDTODATETIME>2016-02-02T07:59:00</ASSIGNEDTODATETIME>
<CASE>
<CASEVALUE>34</CASEVALUE>
</CASE>
<CASE>
<CASEVALUE>67</CASEVALUE>
</CASE>
</LOCAL>
<LOCAL BIT="Test Case File">
<LOCALNAME>E5Y7456</LOCALNAME>
<READINGBY>BearmanJ</READINGBY>
<READINGDATETIME>2016-04-03T06:48:00</READINGDATETIME>
<CASE>
<CASEVALUE>53</CASEVALUE>
</CASE>
<CASE>
<CASEVALUE>20</CASEVALUE>
</CASE>
</LOCAL>
</LOCATION>
</TestImportFile>
示例文本文件
F16-000100:2B-16-NOR-0005-J3
F16-000101:2B-16-NOR-0005-J4
F16-000102:2B-16-NOR-0005-J5
我可以将测试文件读入数组,但无法确定如何在 XML 文件中搜索匹配项,然后使用所需的值更新 XML 文件中的值。
我的脚本读取文本文件:
my $filename = '1TestData.txt';
open(FILE, $filename) or die "Could not read from $filename, program halting.";
my $output = '1TestOutput.txt';
open(OUTPUT, '>'.$output) or die "Can't create $output.\n";
while(<FILE>){
chomp;
@fields = split(':', $_);
print "$fields[0]\n";
}
close FILE;
我想将 LOCATIONID
值更新为文本文件中找到的匹配值的第二个值。
<LOCATIONID>F16-000100</LOCATIONID>
期望的结果:
<LOCATIONID>2B-16-NOR-0005-J3</LOCATIONID>
不触及 XML 文件中的任何其他内容。
最佳答案
请不要使用正则表达式。 XML 是上下文相关的,而正则表达式……则不是。
因此考虑到这一点 - 使用解析器。我喜欢XML::Twig
( XML::LibXML
也很不错。XML::Simple
是 discouraged )
但是您确实有可用的 xpath
,它很相似,但更适合它。
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
use Data::Dumper;
#parse your file.
my $xml = XML::Twig -> new -> parsefile('sample1.xml');
#open the replacements file for reading
open ( my $input, '<', 'file2.txt') or die $!;
#turn it into key-values for replacement
#probably a bit overkill, as you can just do this iteratively instead.
my %replace = map { s/\s+//g; split /:/ } <$input>;
close ( $input );
#print for debug
print "Using for replacement:\n ";
print Dumper \%replace;
#iterate all of the search terms
foreach my $search ( keys %replace ) {
#use XPATH to find location ID that matches.
#note - this only finds the _first_ location ID. To do 'all' you'd
#need to loop.
$xml -> get_xpath("//LOCATIONID[string()=\"$search\"]",0) -> set_text($replace{$search});
}
#set output formatting
$xml -> set_pretty_print('indented_a');
#print to screen
$xml -> print;
#for output:
open ( my $output, '>', 'transformed.xml' ) or die $!;
print {$output} $xml -> sprint;
close ( $output );
如果特定位置 ID 存在多个实例,您需要:
$_ -> set_text($replace{$search}) for $xml -> get_xpath("//LOCATIONID[string()=\"$search\"]");
相反,因为这将搜索与该特定 ID 匹配的所有节点并替换所有节点。
关于xml - 根据数组中数据的匹配更新 XML 文件的特定节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42673128/