Изменить текстовое содержимое XML с помощью XML :: LibXML с шаблоном регулярных выражений - PullRequest
0 голосов
/ 24 июня 2018

Мне нужно очистить твиттерный корпус в XML, я проанализировал его с помощью `XML :: LibXML .

original.xml

<?xml version="1.0" encoding="UTF-8"?>
<tweets>
  <tweet>
    <tweetid>768213876278165504</tweetid>
    <user>OnceBukowski</user>
    <content>@caca, #holadictadura, RT no me daaaaaa la gana</content>
  </tweet>
<tweet>

main.pl

my $filename = 'original.xml';

my $dom = XML::LibXML->load_xml( location => $filename );

foreach my $tweet ( $dom->findnodes( '//tweet' ) ) {

    my ( $content ) = $tweet->findvalue( './content' );

    #say $content;

    #~ $content =~ s///g;
    $content =~ s/@//g;
    $content =~ s/#/tío/g;
    $content =~ s/ k /que/g;
    $content =~ s/ ke /que/g;
    $content =~ s/pls/por favor/g;

    #say $content; }

Я не понимаю, почему при печати:

   print $dom->toString;

Изменения, которые я сделал в $content, не были включены / вставлены в вывод.

Я читал, что вы можете заменить узел содержимого на appendText, но это не работает для меня.

Ответы [ 2 ]

0 голосов
/ 24 июня 2018

Например, вы можете получить элемент содержимого и установить для его дочерних данных text () новую строку:

#!/usr/bin/perl
use warnings;
use strict;
use utf8;
use feature qw{ say };

use XML::LibXML;

my $dom = 'XML::LibXML'->load_xml(IO => *DATA);

for my $tweet ($dom->findnodes('//tweet')) {
    my ($content) = $tweet->findnodes('./content');

    my $string = $content->findvalue('.');
    $string =~ s/@//g;
    $string =~ s/#/tío/g;
    $string =~ s/ k /que/g;
    $string =~ s/ ke /que/g;
    $string =~ s/pls/por favor/g;

    $content->findnodes('text()')->[0]->setData($string);
}

say $dom->toString;

__DATA__
<?xml version="1.0" encoding="UTF-8"?>
    <tweets>
    <tweet>
    <tweetid>768213876278165504</tweetid>
    <user>OnceBukowski</user>
    <content>@caca, #holadictadura, RT no me daaaaaa la gana</content>
    </tweet>
</tweets>
0 голосов
/ 24 июня 2018

Вы, похоже, ожидаете, что $content будет псевдонимом фактического узла (ов) DOM, но это не так, это просто обычная строка, которую вам нужно вернуть в дерево DOM.Вот один из способов сделать это, предполагая, что <content> может иметь только текст и никаких других дочерних узлов:

foreach my $tweet ($dom->findnodes('//tweet')) {
    my @content = $tweet->findnodes('./content');
    die "<tweet> didn't have exactly one <content>: $tweet"
        unless @content==1;
    my $text = $content[0]->textContent;
    $text =~ s/@//g;
    $text =~ s/#/tío/g;
    $text =~ s/ ke? /que/g;
    $text =~ s/pls/por favor/g;
    $content[0]->removeChildNodes();
    $content[0]->appendText($text);
}
print $dom->toString;
...