【问题标题】:XML::LibXML::XPathContext fails parsing Google Maps kml file - doesn't find "when" nodesXML::LibXML::XPathContext 无法解析 Google Maps kml 文件 - 找不到“何时”节点
【发布时间】:2019-06-03 13:14:31
【问题描述】:

我无法让 Perl 使用 XML::LibXML 读取 Google LocationHistory.kml 文件。 findnodes() 找不到 when 标签,但确实找到 gx:coord 标签。

如果我修改 XML 文件以将 gx: 放在 when 前面,它可以工作。但这不是谷歌通过他们的外卖服务生产的。

我想在不修改文件的情况下阅读他们的文件。

输入数据文件 - 来自 Google 的外卖服务

#++++++++++++++++++++++++++++++++++++++++
<?xml version='1.0' encoding='UTF-8'?>
<kml xmlns='http://www.opengis.net/kml/2.2' xmlns:gx='http://www.google.com/kml/ext/2.2'>
<Document>
    <Placemark>
        <open>1</open>
        <gx:Track>
            <altitudeMode>clampToGround</altitudeMode>
            <when>2018-05-17T15:59:24Z</when>
            <gx:coord>-98.0896248 29.997944600000004 258</gx:coord>
            <when>2018-05-17T15:59:24Z</when>
            <gx:coord>-98.0896248 29.997944600000004 258</gx:coord>
            <when>2018-05-17T15:59:23Z</when>
            <gx:coord>-98.0896647 29.9979384 258</gx:coord>
            <when>2018-05-17T15:45:14Z</when>
            <gx:coord>-98.0896772 29.9979363 258</gx:coord>
            <when>2018-05-17T15:40:08Z</when>
            <gx:coord>-98.0892224 29.9977119 262</gx:coord>
        </gx:Track>
    </Placemark>
</Document>
</kml>

我的代码

#++++++++++++++++++++++++++++++++++++++++
sub Test {
my ($infile) = @_;
my ($dom, $xpc, @gnodes, @wnodes);


$dom = XML::LibXML->load_xml(location => $infile);

$xpc = XML::LibXML::XPathContext->new($dom);
$xpc->registerNs('xmlns',    'http://www.opengis.net/kml/2.2');
$xpc->registerNs('xmlns:gx', 'http://www.google.com/kml/ext/2.2');

# should find 5
(@wnodes) = $xpc->findnodes('//when');
print 'XPath: //when      Matched:  ', scalar(@wnodes), "\n";;

# should find 5
(@gnodes) = $xpc->findnodes('//gx:coord');
say 'XPath: //gx:coord  Matched:  ', scalar(@gnodes);

};


THE OUTPUT - five <gx:coord> found, but zero <when> nodes found
searching for <gx:when> also produces zero results
#++++++++++++++++++++++++++++++++++++++++

Apple-iMac21:NewProgramLocal user$

XPath: //when      Matched:  0
XPath: //gx:coord  Matched:  5


Apple-iMac21:NewProgramLocal user$ 

【问题讨论】:

  • 当没有指定命名空间时,一个元素将在默认命名空间中。您是否尝试过寻找“xmlns:when”?
  • (@wnodes) = $xpc->findnodes('//xmlns:when'); -- 产生正确的结果。谢谢!!

标签: xml perl google-maps xpath kml


【解决方案1】:

XPath 使用的前缀不必与 XML 中使用的前缀匹配。事实上,当在 XML 中使用默认名称空间时(就像这里的情况),即使在 XML 中没有使用任何前缀,XPath 也需要前缀。只需选择对您有意义的前缀即可在 XPath 中使用。

还要注意registerNs 只带前缀,所以不要包括xmlns:

如此变化:

$xpc->registerNs('xmlns',    'http://www.opengis.net/kml/2.2');
$xpc->registerNs('xmlns:gx', 'http://www.google.com/kml/ext/2.2');
(@wnodes) = $xpc->findnodes('//when');

到:

$xpc->registerNs('main', 'http://www.opengis.net/kml/2.2');
$xpc->registerNs('gx',   'http://www.google.com/kml/ext/2.2');
(@wnodes) = $xpc->findnodes('//main:when');

达到预期:

XPath: //when      Matched:  5
XPath: //gx:coord  Matched:  5

【讨论】:

  • 漂亮、干净且有意义的前缀是kmlkmlext。我会选择kkx
  • @ikegami 因为您已经修改了我答案的几乎每个单词,您也可以更改前缀...请将您的文本作为您自己的答案发布,然后我将删除我的,看来更合乎逻辑。
  • 这个建议解决了我的问题 - 使用带有 //when 标签的适当前缀。由于 google 生成的实际文件使用 xmlns 和 gx 作为前缀,我会坚持使用这些 - 它有效!
【解决方案2】:

bytepusher 上面的答案和第二个答案一样有效。在“when”标签前添加“xmlns:”会产生正确的结果,并与使用其 Takeout 功能从 Google 下载的文件保持一致(用于“位置历史记录”)。

我假设 xmlns 作为默认值,不需要在 xpath 搜索中指定,但这是一个错误的假设。

感谢您的帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-01
    相关资源
    最近更新 更多