2014-02-10 56 views
3

在下面的代碼中,我試圖解析SVG文件並刪除其中的所有文本節點。 但是,它不起作用(代碼永遠不會進入fornop for findnodes)。我究竟做錯了什麼?我嘗試使用XPath和LibXML版本的代碼,但沒有一個能夠工作。他們解析並轉儲文件,但findnodes不匹配。Perl XML/SVG解析器無法找到節點

#!/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 

@

+0

您是否有輸入文件的示例? – mirod

+0

,因爲你的代碼適用於我(當然,除了XML :: XPath中的未知'unbindNode'方法外),所以也許SVG不是你想象的那樣。 – mirod

+0

你會介意給我們一個合適的輸入文件嗎?您在問題中包含的片段格式不正確,因此無法使用XML工具進行分析。謝謝。 – mirod

回答

4

/svg/text查找直接text元件svg根元素下。這不是你在這裏。它看起來像你想要的text元素在文檔中的任何地方,這將是//text。這應該適用於XML :: XPath。

如果您想使用XML :: LibXML,您應該使用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; 
} 
+0

謝謝,先生!對於解決方案和改進提示! – WorkWise

+0

沒問題。命名空間在處理XML時通常很痛苦。它們在構建通用工具時非常有用,但對於大多數實際的XML消除方法,它們會阻礙並混淆事物。特別是默認的命名空間。 – mirod

+0

是的!這讓我開始了他們,我一定會經常需要他們。 – WorkWise