Perl XML :: Easy: чтение данных пути SVG - PullRequest
0 голосов
/ 31 января 2019

Я работаю над тем, что нужно будет получить для данных о путях отдельных путей в файле SVG, чтобы я мог генерировать похожие пути.

После ужаса глядя на множествоВ библиотеках c / c ++ для обработки файлов SVG я решил использовать perl (так как он больше подходит для работы по сортировке колбас данных о путях SVG) с анализатором XML.По какой-то причине я выбрал XML::Easy (у меня была веская причина. Это было вчера, и я не могу вспомнить, что это было. Вероятно, факт, что это должно быть Easy) в качестве парсера.

Однако я не нашел никаких учебных пособий или документации, кроме perldoc и metacpan.

Мне удалось прочитать мой файл в ссылку XML::Easy::Element, используя xml10_read_document, но я понятия не имею, как получить нафактические данные о пути.

Как получить колбасу из ссылки XML::Easy::Element?

Редактировать: сосиска, на которую я ссылаюсь, является атрибутом d в пути.Например:

<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 голосов
/ 31 января 2019

Вот как я это сделаю с 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};
0 голосов
/ 31 января 2019

После небольшого погружения в 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.

0 голосов
/ 31 января 2019

Поскольку вы не помните причину, по которой вы решили использовать 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...