Como extrair XML de um arquivo de texto

1

Eu tenho um arquivo de texto como abaixo.

1001=<?xml ns=dkfj><home><taga>dkjf</taga></home>1002=<?xml ns=dkfj><home1><taga>dkjf</taga></home1>

Eu preciso de um resultado como abaixo.

 <?xml ns=dkfj><home><taga>dkjf</taga></home>

 <?xml ns=dkfj><home1><taga>dkjf</taga></home1>

Eu tentei com sed , padrão de início e fim, mas não está funcionando, pois ambos estão na mesma linha.

Como posso fazer isso?

    
por Spike 09.11.2015 / 20:54

3 respostas

3

A pergunta original seria resolvida por cat test.xml | tr "<" "\n" | sed -n '/taga>./p' | sed 's/taga>//'
a segunda pergunta atual seria resolvida com cat test.xml | sed 's/[0-9][0-9][0-9][0-9]=/\n/g'

ele procura uma ocorrência de quatro números seguidos por um sinal =, portanto, se você tiver esses tipos de caracteres em outros lugares na string real, isso não funcionará, mas não se parece com isso agora

    
por 09.11.2015 / 21:21
2

Olhando para o seu snippet, parece que você delimitou o XML por 'number ='. Então extraia com split:

#!/usr/bin/env perl
use strict;
use warnings;

use Data::Dumper;

local $/;
my @xml_chunks = split ( /\d+\=/, <> );
print Dumper \@xml_chunks;

Claro, você provavelmente deve notar - seu XML ... não é. A declaração não é válida. Eu vou assumir que é um erro de transposição. Mas deve ser algo como:

<?xml version="1.0" encoding="utf-8"?>

Portanto, com seus dados de exemplo, isso fará uma aproximação razoável da correção do XML (supondo, é claro, que não seja válido).

#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
use Data::Dumper;

local $/;
my @xml_chunks = split( /\d+\=/, <DATA> );
print Dumper \@xml_chunks;

foreach my $chunk ( grep {/xml/} @xml_chunks ) {
    $chunk =~ s/^<[^>]+>//;
    my $twig = XML::Twig->new( pretty_print => 'indented_a' );
    $twig->parse($chunk);
    $twig->set_encoding('utf-8');
    $twig->set_xml_version('1.0');
    $twig->root->set_att( 'xmlns', 'http://www.some_ns.com' );
    $twig->print;
}
    
por 09.11.2015 / 22:18
0

Acho que o sed funcionará, mas farei uma solução de perl:

 perl -ane 'while (/(<\?xml.*?>)($|\d+=)/g) { push @w,$1; }' \
        -e 'print join("\n",@w)."\n";@w=();'

O /g regex op no perl diz "inicie o próximo regex correspondente a partir daqui na linha". Se não houver correspondência, a regex retorna 0 (falso), terminando o loop while , permitindo que o codon imprima sua saída. Enquanto isso, as correspondências são acumuladas na matriz @w , que você deve limpar para a próxima linha de entrada. No regexp, suponho que seu limite de pesquisa seja essencialmente os dígitos e o sinal de igual.

    
por 09.11.2015 / 21:07

Tags