我正在处理类似于xml 的gpx文件.这是该文件的摘录:
<trkpt lat="3.1398377" lon="101.6937661">
<ele>0.0</ele>
<time>2013-01-01T00:00:00.000Z</time>
<name>Position 1</name>
</trkpt>
<trkpt lat="3.1250538" lon="101.6783237">
<ele>0.0</ele>
<name>Position 460</name>
</trkpt>
Run Code Online (Sandbox Code Playgroud)
如您所见,某些<trkpt>元素包含<time>元素,而某些元素则不包含元素.如何添加<time>那些<trkpt>不包含它的元素?
在读取文件时,如果XML节点不包含,则会产生错误<time>:
foreach $points ( $root->getElementsByTagName('trkpt') ) {
my($lat) = $points->findvalue('@lat');
my($lon) = $pints->findvalue('@lon');
my($time) = $points->getElementsByTagName('time')->[0]->textContent();
my($pointName) = $points->getElementsByTagName('name')->[0]->textContent();
}
Run Code Online (Sandbox Code Playgroud)
无法在未定义的值上调用方法"textContent"...
我怎样才能让它变得更聪明?也就是说,如果遇到未定义的$time,它会将其写入<time>gpx文件,并且不会发生错误.
根据文件的大小,您可能希望使用它XML::LibXML,将整个XML文档读入内存,或者XML::Twig,这将允许您将XML作为流处理并最小化使用的内存.
出于测试目的,我<root>在输入数据中添加了一个根元素,使其成为格式良好的XML,就像这样
<root>
<trkpt lat="3.1398377" lon="101.6937661">
<ele>0.0</ele>
<time>2013-01-01T00:00:00.000Z</time>
<name>Position 1</name>
</trkpt>
<trkpt lat="3.1250538" lon="101.6783237">
<ele>0.0</ele>
<name>Position 460</name>
</trkpt>
</root>
Run Code Online (Sandbox Code Playgroud)
这是一个使用的解决方案 XML::LibXML
use strict;
use warnings;
use XML::LibXML;
my $doc = XML::LibXML->load_xml(location => 'trkpt.xml');
for my $trkpt ($doc->findnodes('/*/trkpt')) {
unless ($trkpt->exists('time')) {
my ($ele) = $trkpt->findnodes('ele');
my $time = $doc->createElement('time');
$time->appendTextNode('0.0');
$trkpt->insertAfter($time, $ele);
}
}
print $doc->toString(1);
Run Code Online (Sandbox Code Playgroud)
这是一个等价的usiong XML::Twig
use strict;
use warnings;
use XML::Twig;
my $twig = XML::Twig->new(
twig_roots => { trkpt => \&trkpt },
twig_print_outside_roots => 1,
pretty_print => 'indented'
);
$twig->parsefile('trkpt.xml');
sub trkpt {
my ($twig, $trkpt) = @_;
unless ($trkpt->has_child('time')) {
my $time = XML::Twig::Elt->new(time => '0.0');
my $ele = $trkpt->first_child('ele');
$time->paste('after', $ele);
}
$twig->flush;
}
Run Code Online (Sandbox Code Playgroud)
XML::LibXML会在这里做得很好.遍历所有<trkpt>节点:
for my $node ( $xml->findnodes( '//trkpt') ) { ... }
Run Code Online (Sandbox Code Playgroud)使用exists(或findnodes旧版本XML::LibXML)检测<time>节点是否存在:
if $node->exists( './time' ) { ... }
Run Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
365 次 |
| 最近记录: |