как сравнить текст между тегами xml с помощью perl

У меня есть данные xml, подобные этому

 <ce:affiliation id="aff1">
 <ce:label>a</ce:label>
 <ce:textfn>Department of Urology, Radboud University Nijmegen Medical Center, Nijmegen, The Netherlands</ce:textfn>
  <sa:affiliation>
 <sa:organization>Department of Urology</sa:organization>
 <sa:organization>Radboud University Nijmegen Medical Center</sa:organization>
 <sa:city>Nijmegen</sa:city>
 </sa:affiliation>

и тд..

теперь я хочу прочитать текст внутри "sa:affiliation" во время чтения текста, сначала прочитайте текст в теге внутри sa:affiliation и сделайте текст типа "Кафедра урологии, Медицинский центр Университета Радбауд в Неймегене , Nijmegen" в этом "," формате разделения и сравнить этот текст с текстом внутри "ce:textn" .... "/ce:textn"

например, мне нужно сравнить каждый тег ce:affillition с тегом sa:affilliation для нескольких файлов, и если какое-либо несоответствие нужно сообщить пользователю.


person Kathir .K    schedule 04.12.2013    source источник


Ответы (4)


Ваш вопрос немного расплывчатый. Непонятно, куда идет каждый фрагмент XML. Один файл? несколько файлов? Один фрагмент на файл? Несколько? Если данные находятся в нескольких файлах, как связать элемент ce:affilliation с соответствующим элементом sa:affilliation, особенно если вы проверяете, совпадают ли два текста? Почему в sa:affilliation нет страны? Где объявляются пространства имен?

Предполагая, что 2 части данных находятся в 2 файлах, а префиксы пространства имен не меняются:

#!/usr/bin/perl

use strict;

use warnings;

use XML::Twig;
use Test::More;

my $DEFAULT_COUNTRY= "The Netherlands";

# usage is <tool> <ce file> <sa file>
my( $ce_file, $sa_file)= @ARGV;

my $ce= XML::Twig->new->parsefile( $ce_file)->root;
my $ce_text = $ce->field( 'ce:textfn');

my $sa= XML::Twig->new->parsefile( $sa_file)->root;

# add the country if not present
if( ! $sa->first_child( 'sa:country')) 
  { $sa->insert_new_elt( last_child => 'sa:country' => $DEFAULT_COUNTRY); }

my $sa_text= join( ', ', $sa->children_text);

is( $ce_text, $sa_text, "checking " . $ce->id);

done_testing();
person mirod    schedule 04.12.2013
comment
Это несколько файлов и несколько фрагментов. просто я хочу сравнить текст в ce: affilliaiton и sa: affilliation, который содержится между тегами. В данном утверждении страна отсутствует в sa:affillion, поэтому укажите для этого некоторую ошибку. - person Kathir .K; 04.12.2013
comment
сначала я хочу прочитать текст внутри sa:affilliation после прочтения каждого тега внутри sa:affilliation это мой текст после прочтения Департамента урологии Медицинского центра Университета Радбауд в Неймегене, Неймеген nw сравнить этот текст с текстом ce:affilliaiton . - person Kathir .K; 04.12.2013
comment
насколько я понимаю, у вас должно быть все в порядке. Удалите часть кода, которая устанавливает страну по умолчанию. Поскольку вы на самом деле не ответили на большинство моих вопросов, я думаю, вам больше не нужна помощь ;--) - person mirod; 04.12.2013
comment
Наконец, я нашел этот код, но есть ли способ получить этот текст ce: affillition и sa: affillition без использования условия if else, потому что он не выполнил какое-то условие. Это можно сделать без использования use XML:: Twig; используйте Тест::Больше; - person Kathir .K; 25.12.2013

Вы можете использовать XML::XPath для поиска узлов, которые вы хочу. Затем просто проверьте, являются ли два узла string_value neq.

person Jonathan Ruffin    schedule 04.12.2013
comment
Я новичок в перле. пожалуйста, можете ли вы дать полный сценарий для этого ?? - person Kathir .K; 04.12.2013
comment
Возможно, вам следует обновить свой пост тем, что вы пробовали до сих пор. Если вы знаете, как использовать CPAN, ссылка, которую я вам дал, должна помочь вам начать работу без необходимости писать собственный синтаксический анализатор XML. :) - person Jonathan Ruffin; 04.12.2013

наконец, я нашел этот код, но есть ли способ получить этот текст ce: affillition и sa: affillition без использования условия if else, потому что он не выполнил какое-то условие.

#!/usr/bin/perl  
@files = <*.xml>;
open my $out, '>', 'output.xml' or die $!;
foreach $file (@files) {
open   (FILE, "$file");
$a =1;
while(my $line= <FILE> ){
do{
if ($line =~ /<ce:affiliation id=\"aff$a\">(.+?)<ce:textfn>(.+?)<\/ce:textfn><sa:affiliation>(.+?)<\/sa:affiliation><\/ce:affiliation>/){
$count = $3;
$textfn = $2;
print ("$count\n");
print ("$textfn\n");
if ($count =~ /<\/sa:(.+?)>/){
$count =~ s/<\/sa:organization>/, /g;
$count =~ s/<\/sa:city>/, /g;
$count =~ s/<\/sa:country>/, /g;
$count =~ s/<\/sa:state>/, /g;
$count =~ s/<sa:organization>//g;
$count =~ s/<sa:city>//g;
$count =~ s/<sa:country>//g;
$count =~ s/<sa:state>//g;
chop($count);
chop($count);
if($count ne $textfn){
print $out("$file affilliation $a is mismatch\n");}}}
else{
if($line =~ /<ce:affiliation id=\"aff$a\">(.+?)<ce:textfn>(.+?)<\/ce:textfn><\/ce:affiliation>/){
print $out("$file sa:affilliation missing for $a\n");}}
$a=$a+1;}
while($line =~ /aff$a/);}}

Для этого условия xml я получаю неправильный результат

 <ce:affiliation id="aff1"><ce:label>a</ce:label><ce:textfn>Department of Urology, Radboud University Nijmegen Medical Center, Nijmegen, The Netherlands</ce:textfn><sa:affiliation><sa:organization>Department of Urology</sa:organization><sa:organization>Radboud University Nijmegen Medical Center</sa:organization><sa:city>Nijmegen</sa:city><sa:country>The Netherlands</sa:country></sa:affiliation></ce:affiliation><ce:affiliation id="aff2"><ce:textfn>Norris Comprehensive Cancer Center, University of Southern California Institute of Urology, Los Angeles, California</ce:textfn></ce:affiliation><ce:affiliation id="aff3"><ce:label>c</ce:label><ce:textfn>Department of Urology, Stanford University, Stanford, California</ce:textfn><sa:affiliation><sa:organization>Department of Urology</sa:organization><sa:organization>Stanford University</sa:organization><sa:city>Stanford</sa:city><sa:state>California</sa:state></sa:affiliation></ce:affiliation><ce:correspondence id="cor1"></article>
person Kathir .K    schedule 22.12.2013
comment
Это должно быть ответом на ваш собственный вопрос или это пример того, что вы пробовали до сих пор? Если последнее, вам следует отредактировать исходный вопрос и добавить его туда. Кроме того, пожалуйста сделайте отступ в коде, это сделает его намного более легким для чтения. - person Ilmari Karonen; 22.12.2013
comment
@IlmariKaronen Наконец-то я нашел этот код, но есть ли способ получить этот текст ce: affillition и sa: affillition без использования условия if else, потому что он не выполнил какое-то условие. - person Kathir .K; 25.12.2013

Наконец я получил требуемый результат.

#!/usr/bin/perl  
@files= <*.xml>;
open my $out, '>', 'output.xml' or die $!;
foreach $file (@files){
open   (FILE, "$file");
my $a =1;
while(my $line= <FILE> ){
do{
if($line =~ /<ce:affiliation id=\"aff$a\">(.+?)<\/ce:affiliation>/){
$count=$1;
if($count =~ /<ce:label>/){
$count=~ s/<ce:label>(.+?)<\/ce:label>//;}
if($count =~ /<sa:affiliation>/){
if($count =~ /<ce:textfn>(.+?)<\/ce:textfn><sa:affiliation>(.+?)<\/sa:affiliation>/){
$textfn=$1;
$sff=$2;
$sff =~ s/<\/sa:organization>/, /g;
$sff =~ s/<\/sa:city>/, /g;
$sff =~ s/<\/sa:country>/, /g;
$sff =~ s/<\/sa:state>/, /g;
$sff =~ s/<sa:organization>//g;
$sff =~ s/<sa:city>//g;
$sff =~ s/<sa:country>//g;
$sff =~ s/<sa:state>//g;
chop($sff);
chop($sff);}
if($textfn ne $sff){
print $out("$file ce:aff and sa:aff  mismatch in aff$a\n");}
if($textfn =~ /<ce:sup>/){
print $out("$file check label aff$a\n");}}
else{
if($line =~ /\"art520.dtd\"/){
print $out("$file strct affilition missing for aff$a\n");
}}}
$a=$a+1;
}while($line =~ /aff$a/);}}
person Kathir .K    schedule 27.12.2013