как да сравнявате текст между 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>

и т.н.

nw искам да прочета текста вътре в "sa:affiliation" докато четете текст, първо прочетете текста в тага вътре sa:affiliation и направете текст като "Катедра по урология, Медицински център на университета Radboud Nijmegen , 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, този мой текст, след като прочетох Катедра по урология, Медицински център на университета Radboud Nijmegen, Nijmegen nw сравнете този текст с ce:affilliaiton text. - person Kathir .K; 04.12.2013
comment
доколкото разбирам, тогава трябва да си добре. Премахнете частта от кода, която задава държавата по подразбиране. Тъй като всъщност не отговорихте на повечето от въпросите ми, предполагам, че нямате нужда от повече помощ ;--) - person mirod; 04.12.2013
comment
Най-накрая намерих този код, но има ли някакъв метод за извличане на този ce:affillition и sa:affillition текст, без да се използва if else условие, тъй като не успя да даде условие. Възможно е да се направи без да се използва XML::Twig; използвайте Test::More; - person Kathir .K; 25.12.2013

Можете да използвате XML::XPath, за да намерите възлите, които искам. След това просто проверете дали string_value на двата възела са neq.

person Jonathan Ruffin    schedule 04.12.2013
comment
Нов съм в perl. моля, можете ли да дадете пълен скрипт за това?? - 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