В Perl, как я могу изменить элемент в файле XML без изменения формата файла XML? - PullRequest
5 голосов
/ 25 августа 2009

У меня есть файл XML в формате:

<outer1>
    <inner1>
        <name>Stonecold</name>
        <profession>warrior</profession>
        <org>wwf</org>
    </inner1>
    <inner1>
        <name>Shanebond</name>
        <profession>Bowler</profession>
        <org>newzealand</org>
    </inner1>
    <inner1>
        <name>brain schemidit</name>
        <profession>Chairman</profession>
        <org>Google</org>
    </inner1>
</outer1>

Я хочу изменить значение Shanebond на Shane Bond.

Я использовал XML::Simple, норезультат был хеш.

Я хочу тот же формат, что и входной файл.Например: выходной файл должен быть следующим:

<outer1>
    <inner1>
        <name>Stonecold</name>
        <profession>warrior</profession>
        <org>wwf</org>
    </inner1>
    <inner1>
        <name>Shane Bond</name>
        <profession>Bowler</profession>
        <org>newzealand</org>
    </inner1>
    <inner1>
        <name>brain schemidit</name>
        <profession>Chairman</profession>
        <org>Google</org>
    </inner1>
</outer1>

Посоветуйте, пожалуйста, как это сделать.

Заранее спасибо.

Я хочу сохранить выходной файлв том же каталоге и, если возможно, с тем же именем.это возможно?

Ответы [ 4 ]

8 голосов
/ 25 августа 2009

Когда дело доходит до чтения или манипулирования файлом XML, тогда XML :: Twig часто является первым инструментом, который я использую.

Сначала я подумал, что это может быть излишним для вашего требования, но потом я заметил, что он идет с опцией parsefile_inplace ():

use strict;
use warnings;
use XML::Twig;

XML::Twig->new(
    pretty_print  => 'indented',
    twig_handlers => { 
        name => sub { 
            $_->set_text( 'Shane Bond' )->flush  if $_->text eq 'Shanebond' 
        },
    },
)->parsefile_inplace( 'data.xml', 'bak_*' );

NB. Если вы не хотите сохранять файл резервной копии, удалите второй аргумент ('bak _ *').

5 голосов
/ 26 августа 2009

Зачем вообще обрабатывать его как XML? Почему бы просто не сделать регулярное выражение-заменить?

perl -pi -e 's/Shanebond/Shane Bond/' filename.xml

Это сделает замену на месте, сохранив то же имя файла и все.

4 голосов
/ 25 августа 2009

XML::Simple имеет опции, которые позволяют вам указать, как ввод будет преобразован в структуру данных Perl и как эта структура будет выводиться:

#!/usr/bin/perl

use strict;
use warnings;

use XML::Simple;

my $xml_file = 'b.xml';

my $xml = XMLin(
    $xml_file,
    KeepRoot => 1,
    ForceArray => 1,
);

$xml->{outer1}->[0]->{inner1}->[1]->{name} = 'Shane Bond';

XMLout(
    $xml,
    KeepRoot => 1,
    NoAttr => 1,
    OutputFile => $xml_file,
);

XML::Simple становится немного странно, если вы делаете что-то интересное, потому что его цель не в том, чтобы быть библиотекой XML общего назначения, а в предоставлении простого способа работы с файлами конфигурации, написанными на XML.

CPAN имеет множество XML-связанных модулей . Если только это не была единственная проблема, с которой вам приходилось сталкиваться, стоило бы рассмотреть некоторые из более способных и более подходящих модулей.

3 голосов
/ 25 августа 2009

Вы пробовали XMLout с OutputFile

Из документации по XML :: Simple:

По умолчанию XMLout () возвращает XML в виде строки. Если вы хотите записать XML в файл, просто укажите имя файла, используя опцию «OutputFile».
Эта опция также принимает объект дескриптора ввода-вывода, что особенно полезно в Perl 5.8.0 и новее для вывода с использованием кодировки, отличной от UTF-8, например:

open my $fh, '>:encoding(iso-8859-1)', $path or die "open($path): $!";
XMLout($ref, OutputFile => $fh);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...