Perl XML :: Easy:读取SVG路径数据

时间:2019-01-31 08:31:18

标签: xml perl svg

我正在做的事情是需要获取SVG文件中各个路径的路径数据,以便生成相似的路径。

在惊恐地处理了用于处理SVG文件的大量c / c ++库之后,我决定将perl(因为它更适合对SVG路径数据的香肠进行分类的工作)与XML解析器一起使用。出于某种原因,我选择了XML::Easy(我有一个很好的理由。那是昨天,我不记得它是什么了。可能是应该是Easy的事实)作为解析器。

但是,除了perldoc和metacpan之外,我没有找到其他任何教程或文档。

我设法使用XML::Easy::Element将文件读入xml10_read_document引用中,但是我不知道如何获取实际路径数据。

如何从XML::Easy::Element参考获得路径香肠?

编辑:我指的香肠是路径中的d属性。 EG:来自

<svg>
[...]
<g id=something>
<path d="M350.41,62.567v0.135l1.118,0.04v-0.135L350.41,62.567z
    M351.898,60.655c-0.242,0-0.433,0.059-0.572,0.175c-0.089,0.104-0.179,0.207-0.269,0.311l-0.014-0.445l-0.875-0.013v0.31
        l0.458,0.067l-0.041,1.421l0.498,0.006l0.014-0.754c0.197-0.449,0.438-0.673,0.72-0.673c0.193,0,0.29,0.11,0.29,0.329
        c0,0.108-0.025,0.223-0.074,0.344l0.316,0.081c0.085-0.148,0.128-0.312,0.128-0.491c0-0.185-0.047-0.34-0.142-0.465
        C352.228,60.723,352.082,60.655,351.898,60.655z
      M350.572,62.816l-0.027,0.922l0.525-0.08l0.006-0.835L350.572,62.816z"/>
</g>
[...]
</svg>

我想提取

"M350.41,62.567v0.135l1.118,0.04v-0.135L350.41,62.567z
 M351.898,60.655c-0.242,0-0.433,0.059-0.572,0.175c-0.089,0.104-0.179,0.207-0.269,0.311l-0.014-0.445l-0.875-0.013v0.31
 l0.458,0.067l-0.041,1.421l0.498,0.006l0.014-0.754c0.197-0.449,0.438-0.673,0.72-0.673c0.193,0,0.29,0.11,0.29,0.329      c0,0.108-0.025,0.223-0.074,0.344l0.316,0.081c0.085-0.148,0.128-0.312,0.128-0.491c0-0.185-0.047-0.34-0.142-0.465
        C352.228,60.723,352.082,60.655,351.898,60.655z
      M350.572,62.816l-0.027,0.922l0.525-0.08l0.006-0.835L350.572,62.816z"

3 个答案:

答案 0 :(得分:3)

下面是我如何与做Mojo::DOM

use strict;
use warnings;
use Mojo::DOM;

my $svg = <<'SVG';
<svg>
[...]
<g id="something">
<path d="M350.41,62.567v0.135l1.118,0.04v-0.135L350.41,62.567z
    M351.898,60.655c-0.242,0-0.433,0.059-0.572,0.175c-0.089,0.104-0.179,0.207-0.269,0.311l-0.014-0.445l-0.875-0.013v0.31
        l0.458,0.067l-0.041,1.421l0.498,0.006l0.014-0.754c0.197-0.449,0.438-0.673,0.72-0.673c0.193,0,0.29,0.11,0.29,0.329
        c0,0.108-0.025,0.223-0.074,0.344l0.316,0.081c0.085-0.148,0.128-0.312,0.128-0.491c0-0.185-0.047-0.34-0.142-0.465
        C352.228,60.723,352.082,60.655,351.898,60.655z
      M350.572,62.816l-0.027,0.922l0.525-0.08l0.006-0.835L350.572,62.816z"/>
</g>
[...]
</svg>
SVG

my $dom = Mojo::DOM->new->xml(1)->parse($svg);
my $sausage = $dom->at('path')->{d};

或者如果您想从特定的<g>标记而不是第一个标记中获取它,

my $sausage = $dom->at('g#something path')->{d};

答案 1 :(得分:2)

在深入研究XML :: Easy的文档之后,我认为这会起作用:

use strict;
use warnings;
use XML::Easy::Text 'xml10_read_document';
use XML::Easy::NodeBasics qw(xml_e_content_twine xml_e_type_name xml_e_attribute);
use List::Util 'first';

my $svg = <<'SVG';
<svg>
[...]
<g id="something">
<path d="M350.41,62.567v0.135l1.118,0.04v-0.135L350.41,62.567z
    M351.898,60.655c-0.242,0-0.433,0.059-0.572,0.175c-0.089,0.104-0.179,0.207-0.269,0.311l-0.014-0.445l-0.875-0.013v0.31
        l0.458,0.067l-0.041,1.421l0.498,0.006l0.014-0.754c0.197-0.449,0.438-0.673,0.72-0.673c0.193,0,0.29,0.11,0.29,0.329
        c0,0.108-0.025,0.223-0.074,0.344l0.316,0.081c0.085-0.148,0.128-0.312,0.128-0.491c0-0.185-0.047-0.34-0.142-0.465
        C352.228,60.723,352.082,60.655,351.898,60.655z
      M350.572,62.816l-0.027,0.922l0.525-0.08l0.006-0.835L350.572,62.816z"/>
</g>
[...]
</svg>
SVG

my $root = xml10_read_document($svg);
my $contents = xml_e_content_twine($root);
my $g = first { ref $_ and xml_e_type_name($_) eq 'g' and xml_e_attribute($_, 'id') eq 'something' } @$contents;
my $g_contents = xml_e_content_twine($g);
my $path = first { ref $_ and xml_e_type_name($_) eq 'path' } @$g_contents;
my $sausage = xml_e_attribute($path, 'd');

对我来说似乎很难。我建议改用任何XPath或CSS解析器。

答案 2 :(得分:0)

由于您不记得选择使用XML::Easy的原因,因此请考虑使用XML::Simple::):

use XML::Simple qw( XMLin ) ;

my $svg = q{
    <svg width="190" height="160" xmlns="http://www.w3.org/2000/svg">
      <path d="M10 10 C 20 20, 40 20, 50 10" stroke="black" fill="transparent"/>
      <path d="M70 10 C 70 20, 120 20, 120 10" stroke="black" fill="transparent"/>
      <path d="M70 10 C 70 20, 120 20, 120 10" stroke="black" fill="transparent"/>
    </svg>
};

my $decoded = XMLin( $svg, ForceArray => 1 ) ;

foreach my $path ( @{ $decoded->{ path } } ){
    my $data = $path->{d} ;
    my $stroke = $path->{stroke} ;
    my $fill = $path->{ fill } ;
    ...
}

$decoded->{ path }在哪里:

 [
     {
         d      => "M10 10 C 20 20, 40 20, 50 10",
         fill   => "transparent",
         stroke => "black"
     },
     {
         d      => "M70 10 C 70 20, 120 20, 120 10",
         fill   => "transparent",
         stroke => "black"
     },
     {
         d      => "M70 10 C 70 20, 120 20, 120 10",
         fill   => "transparent",
         stroke => "black"
     }
 ]

注意:正如格林尼茨所指出的,不要将XML::Simple用于比平凡的SVG更复杂的事情。