【问题标题】:How do I remove duplicate notes from an XML document in Perl?如何在 Perl 中从 XML 文档中删除重复的注释?
【发布时间】:2015-10-08 11:27:39
【问题描述】:

我有一个带有重复节点的站点地图视频文件 xml:

<?xml version="1.0"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"> 
<url>
<loc>http://www.tubtun.com/video/Samsung_42Channel_Wireless_SoundStand</loc>
<video:video>
    <video:title>Samsung 42Channel Wireless SoundStand</video:title>
    <video:description>Samsung 4.2Channel Wireless SoundStand</video:description>
    <video:thumbnail_loc>http://www.tubtun.com/media/files_thumbnail/user91/pl_5364844b0dc.jpg</video:thumbnail_loc>
    <video:player_loc>http://www.tubtun.com/modules/vPlayer/vPlayer.swf?f=http://www.tubtun.com/modules/vPlayer/vPlayercfg.php?fid=844b0dc2c7258f4de11</video:player_loc>
    <video:publication_date>2015-01-27</video:publication_date>
</video:video>
</url>
<url>
<loc>http://www.tubtun.com/video/Samsung_42Channel_Wireless_SoundStand</loc>
<video:video>
    <video:title>Samsung 42Channel Wireless SoundStand</video:title>
    <video:description>Samsung 4.2Channel Wireless SoundStand</video:description>
    <video:thumbnail_loc>http://www.tubtun.com/media/files_thumbnail/user91/pl_5364844b0dc.jpg</video:thumbnail_loc>
    <video:player_loc>http://www.tubtun.com/modules/vPlayer/vPlayer.swf?f=http://www.tubtun.com/modules/vPlayer/vPlayercfg.php?fid=844b0dc2c7258f4de11</video:player_loc>
    <video:publication_date>2015-01-27</video:publication_date>
</video:video>
</url>
.....

我已经编写了一个 perl 脚本来删除这些重复的数据:

use strict;
use warnings;
use XML::LibXML;

my $file = 'sitemap.xml';
my $doc = XML::LibXML->load_xml( location => $file );

my %seen;
foreach my $uni ( $doc->findnodes('//url') ) {  # 'university' nodes only

    my $name = $uni->find('video:title');

    print "'$name' duplicated\n",
      $uni->unbindNode() if $seen{$name}++;  # Remove if seen before
}

$doc->toFile('clarified.xml'); # Print to file

不幸的是,文件“clarified.xml”与sitemap.xml相同。

我不知道我的脚本出了什么问题。

【问题讨论】:

  • 您检查过$name 的内容吗?您的脚本是否说打印 foo duplicated 输出?
  • 那么你找到了问题所在。 $uni-&gt;find('video:title') 无法正常工作。您可能想检查如何使用 XML::LibXML 中的命名空间前缀,以及如何从元素中获取文本节点。

标签: xml perl xml-sitemap


【解决方案1】:

我不太清楚为什么您的 XML::LibXML 不起作用,尽管正如 cmets 中所述 - 如果它不能与 find 一起使用,那将是它的根源。

我将提供一个使用XML::Twig 的替代方案。

#!/usr/bin/env perl 
use strict;
use warnings;
use XML::Twig; 

my $file = 'test3.xml';

my %seen;

sub delete_url_if_seen {
   my ( $twig, $url ) = @_; 
   my $name = $url -> get_xpath('./video:video/video:title',0) -> trimmed_text;
   if ( $seen{$name}++ ) { $url -> delete; };
}

my $twig = XML::Twig -> new ( 'pretty_print' => 'indented_a', 
                   'twig_handlers' => { 'url' => \&delete_url_if_seen } );
$twig -> parsefile_inplace ( $file );

【讨论】:

    【解决方案2】:

    您应该使用XPathContext 并注册视频和默认命名空间。您还应该调用findvalue 以获取字符串形式的标题。

    my $xpc = XML::LibXML::XPathContext->new();
    $xpc->registerNs(sitemap => 'http://www.sitemaps.org/schemas/sitemap/0.9');
    $xpc->registerNs(video   => 'http://www.google.com/schemas/sitemap-video/1.1');
    for my $node ($xpc->findnodes('//sitemap:url', $doc)) {
        my $name = $xpc->findvalue('video:title', $node);
        ...
    }
    

    【讨论】:

      【解决方案3】:

      我已经成功了,这是代码&我尝试了https://stackoverflow.com/a/4817929/235961中提供的解决方案

      use strict;
      use warnings;
      use XML::LibXML;
      
      my $file = 'sitemap.xml';
      my $doc = XML::LibXML->load_xml( location => $file );
      
      my %seen;
      foreach my $uni ( $doc->findnodes("//*[name() ='url']") ) {  # 'university' nodes only
      
          my $name = $uni->find('//video:title');
          print "'$name' duplicated\n",
            $uni->unbindNode() if $seen{$name}++;  # Remove if seen before
      }
      
      $doc->toFile('clarified.xml'); # Print to file
      

      【讨论】:

      • 我很难相信您的代码与 OP 的原始代码有任何不同。您所做的只是将 XPath //url 更改为 //*[name()='url'],这在节点没有命名空间时是相同的,如此处所示。您还尝试使用 LibXML 一无所知的 video 命名空间。请显示您的示例输入数据和结果输出
      • 发现也略有不同。
      • @Borodin 我不太确定,但我认为这与 XML 命名空间有关,我在这里看到了类似的问题 stackoverflow.com/a/4817929/235961
      • @Borodin 视频提到了一个 ns,我无法在任何在线 IDE 上运行我的代码供您查看,因为没有安装 XML::LibXML
      猜你喜欢
      • 2015-02-01
      • 1970-01-01
      • 2010-09-28
      • 1970-01-01
      • 2018-06-24
      • 2021-08-13
      • 1970-01-01
      • 1970-01-01
      • 2020-08-01
      相关资源
      最近更新 更多