Возникли проблемы со скриптом Perl, который конвертирует XML в хеш - PullRequest
1 голос
/ 03 ноября 2011

У меня есть Perl-скрипт для преобразования приведенного ниже XML-файла в хеш:

<university>
   <name>svu</name>
  <location>ravru</location>
 <branch>
  <electronics>
 <student name="xxx" number="12">
 <semester number="1"subjects="7" rank="2"/>
 </student>
 <student name="xxx" number="15">
 <semester number="1" subjects="7" rank="10"/>
 <semester number="2" subjects="4" rank="1"/>
  </student>
   <student name="xxx" number="16">
   <semester number="1"subjects="7" rank="2"/>
  <semester number="2"subjects="4" rank="2"/>
   </student>
</electronics>
  </branch>
   </university>.
          . 
          .
          .
          .
          .
<data>
  <student name="msr" number="1" branch="computers" />
   <student name="ksr" number="2" branch="electronics" />
  <student name="lsr" number="3" branch="EEE" />
  <student name="csr" number="4" branch="IT" />
   <student name="msr" number="5" branch="MEC" />
  <student name="ssr" number="6" branch="computers" />
  <student name="msr" number="1" branch="CIV" />
  .............................
   ..............................
    .....................
 </data>

Как создать хеш-таблицу для элементов данных с именем и номером в качестве ключа, а ветвьзначение в этом хеше.Мне это нужно, потому что у некоторых студентов одинаковые имена, а у некоторых студентов одинаковые номера.

Используя этот хэш-ключ, я должен найти в университетском узле студента, если он найден, и распечатать название филиала каждого студента.

Я написал какой-то скрипт на XML::Simple, но не могу создать хеш.

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

 my $xml = new XML::Simple;
 my $data = $xml->XMLin("data.xml", forcearray => [ 'student' , 'semister' ],
                                    KeyAttr    => { student  => "+Name"  } );

 print Dumper($data);

с помощью дампера данных. Я печатаю информацию о дыре в XML.но мне нужно печатать только элементы Data Node, пожалуйста, помогите мне, как это сделать.

Ответы [ 2 ]

1 голос
/ 05 ноября 2011

Я бы, вероятно, написал свой собственный обработчик XML::Parser для объединения атрибутов в ключевые значения (если это что-то поддерживается XML::Simple, я не смог бы найти его в документации). Этот пример должен помочь вам начать:

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

my %hash;

sub tag_start { my ($expat, $tagname) = (shift, shift);
    # attributes are now in @_
    my %a = grep { $_=$_=>shift } @_; # attribute hash for this tag
    my $context = join('/',$expat->context()) || '';

    if ($context eq 'xml/data') {
        if ($tagname eq 'student') {
            push @{($hash{"$a{name}:$a{number}"}||=[])}, $a{branch};
        }
    } elsif ($context eq ...) {
        ...
    }
}
my $p = new XML::Parser(Handlers => { Start=>\&tag_start });
$p->parsefile('file.xml');
print Dumper \%hash;

Обратите внимание, что для того, чтобы это сработало, мне пришлось немного очистить ваш XML, заключив его в тег <xml> и добавив несколько пропущенных пробелов:

<xml>
    <university>
        <name>svu</name>
        <location>ravru</location>
        <branch>
            <electronics>
                <student name="xxx" number="12">
                    <semester number="1" subjects="7" rank="2"/>
                </student>
                <student name="xxx" number="15">
                    <semester number="1" subjects="7" rank="10"/>
                    <semester number="2" subjects="4" rank="1"/>
                </student>
                <student name="xxx" number="16">
                    <semester number="1" subjects="7" rank="2"/>
                    <semester number="2" subjects="4" rank="2"/>
                </student>
            </electronics>
        </branch>
    </university>
    <data>
        <student name="msr" number="1" branch="computers" />
        <student name="ksr" number="2" branch="electronics" />
        <student name="lsr" number="3" branch="EEE" />
        <student name="csr" number="4" branch="IT" />
        <student name="msr" number="5" branch="MEC" />
        <student name="ssr" number="6" branch="computers" />
        <student name="msr" number="1" branch="CIV" />
    </data>
</xml>

Результат:

$VAR1 = {
          'ksr:2' => [
                     'electronics'
                   ],
          'msr:1' => [
                     'computers',
                     'CIV'
                   ],
          'csr:4' => [
                     'IT'
                   ],
          'ssr:6' => [
                     'computers'
                   ],
          'msr:5' => [
                     'MEC'
                   ],
          'lsr:3' => [
                     'EEE'
                   ]
        };
1 голос
/ 03 ноября 2011

Нет необходимости использовать XML::Simple и XML::Fast вместе. Оба выполняют по существу одно и то же.

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


Я бы использовал XML::Fast для этого случая:

use strict;
use warnings;
use XML::Fast;

my $data = xml2hash 'data.xml', array => [ 'student', 'semester' ];

Даже если структура не совсем требуемая, $data может быть легко обработан и испытан по вкусу (в конце концов, это структура данных).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...