【问题标题】:Perl XML/SVG Parser unable to findnodesPerl XML/SVG 解析器无法找到节点
【发布时间】:2014-02-10 12:22:18
【问题描述】:

在下面的代码中,我试图解析一个 SVG 文件并删除其中的所有文本节点。 但是,它不起作用(代码永远不会进入 findnodes 的 forloop)。我究竟做错了什么?我尝试使用 XPath 和 LibXML 版本的代码,但它们都不起作用。他们很好地解析和转储文件,但 findnodes 什么都不匹配。

#!/usr/bin/perl

use strict;
use warnings;

use XML::XPath;
use XML::XPath::XMLParser;

my $num_args=$#ARGV+1;
if($num_args != 1) { print "Usage: $0 <filename>\n"; exit(1); }


my $file=$ARGV[0];


my $doc = XML::XPath->new(filename => $file);

foreach my $dead ($doc->findnodes('/svg/text')) {
    print "Found Text Node\n";
    $dead->unbindNode;
}

开始几行 SVG 文件:

<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   version="1.1"
   width="675"
   height="832.5"
   id="svg2"
   xml:space="preserve"><metadata
     id="metadata8"><rdf:RDF><cc:Work
         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
     id="defs6" /><g
     transform="matrix(1.25,0,0,-1.25,0,832.5)"
     id="g10"><path
       d="m 54,608.663 450,0 M 54,129.052 l 450,0"
       inkscape:connector-curvature="0"
       id="path12"
       style="fill:none;stroke:#231f20;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1;stroke-dasharray:none" /><text
       transform="matrix(1,0,0,-1,229.0848,615.9133)"
       id="text14"><tspan

@

【问题讨论】:

  • 你有输入文件的例子吗?
  • 因为你的代码对我有用(当然除了 XML::XPath 中未知的 unbindNode 方法),所以也许 SVG 不是你想的那样。
  • 您介意给我们一个正确的输入文件吗?您在问题中包含的片段格式不正确,因此无法使用 XML 工具进行解析。谢谢。

标签: perl parsing svg libxml2


【解决方案1】:

/svg/text 直接在 svg 根元素下查找 text 元素。这不是你在这里所拥有的。看起来您想要的是文档中任何位置的text 元素,即//text。这应该适用于 XML::XPath。

如果你想使用 XML::LibXML,你应该使用它,因为它是一个比 XML::XPath 更好的模块(更好的维护、更高效、更强大),那么你必须注意命名空间:整体文档有一个默认命名空间(开始标记中的xmlns="http://www.w3.org/2000/svg" 位)。您需要声明它并使用 XML::LibXML::XPathContext 来评估 XPath 表达式,包括前缀。:

#!/usr/bin/perl

use strict;
use warnings;

use XML::LibXML;
use XML::LibXML::XPathContext;

# it's easier to test directly @ARGV in scalar context than to use $#ARGV
if(@ARGV != 1) { print "Usage: $0 <filename>\n"; exit(1); }

my $file=$ARGV[0];

my $doc = XML::LibXML->load_xml( location => $file);

my $xpc = XML::LibXML::XPathContext->new( $doc);     # create the XPath evaluator
$xpc->registerNs(x => 'http://www.w3.org/2000/svg'); # declare the namespace as x

# the query now uses x as the prefix for the svg namespace
foreach my $dead ($xpc->findnodes('//x:text')) {
    print "Found Text Node\n";
    $dead->unbindNode;
}

【讨论】:

  • 谢谢先生!对于解决方案,以及改进提示!
  • 没问题。处理 XML 时,命名空间通常很痛苦。它们在构建通用工具时很有用,但对于大多数 XML 修改的实际情况,它们会妨碍并混淆事物。尤其是默认命名空间。
  • 是的!这让我开始使用它们,我认为肯定会经常需要它们。
  • 言语无法形容我对 XML 命名空间的厌恶。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-15
  • 1970-01-01
  • 2019-06-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多