Почему я получаю ошибку в цикле FOREACH, используя Template? - PullRequest
0 голосов
/ 01 ноября 2011

Мне нужна помощь с этой проблемой, я борюсь за последние 15 дней, пожалуйста, помогите мне. У меня есть XML-файл, и я храню в переменной, используя XML :: simple. Я обработал через шаблонный инструментарий. Я получаю ошибку, как это

$var1={
 university=>{
      'name'=>'svu',
       'location'=>'ravru',
        'branch'=>{
                 'electronics'=>{
                            'student'=>[
                                     {
                                    'name'=>'mikky',
                                     'number'=>'12',
                                       'semester'=>{
                                              'Number'=>'1',
                                              'subjects'=>'7',
                                               'rank'=>'1'
                                              }
                                           },
                                   {
                                    'name'=>'vijju',
                                     'number'=>'15',
                                       'semester'=>[
                                            {
                                           'number'=>'1',
                                            'subjects'=>'7',
                                             'rank'=>'10'
                                              },
                                             {
                                            'number'=>'1',
                                            'subjects'=>'7',
                                             'rank'=>'1'
                                              }
                                             ]
                                           },
                                          {
                                    'name'=>'shyam',
                                     'number'=>'16',
                                       'semester'=>[
                                            {
                                           'number'=>'1',
                                            'subjects'=>'7',
                                             'rank'=>'2'
                                              },
                                             {
                                            'number'=>'2',
                                            'subjects'=>'4',
                                             'rank'=>'2'
                                              }
                                             ]
                                           }
                                         }
                                      ]
                                     }
                                   };
           university=>{
                 'name'=>'sku',
                'location'=>'ANTP',
                  'branch'=>{
                        'electronics'=>{
                                  'student'=>[
                                            {
                                          'name'=>'xxx',
                                           'number'=>'12',
                                          'semester'=>{
                                                  'Number'=>'3',
                                                    'subjects'=>'6',
                                                  'rank'=>'20'
                                              }
                                           },
                                   {
                                    'name'=>'xxx',
                                     'number'=>'6',
                                       'semester'=>[
                                            {
                                           'number'=>'1',
                                            'subjects'=>'9',
                                             'rank'=>'12'
                                              },
                                             {
                                            'number'=>'2',
                                            'subjects'=>'4',
                                             'rank'=>'2'
                                              }
                                             ]
                                           }
                                         }
                                      ]
                                     }
                                   };
      'studentaddres'=>{
                 'address'=>[
                            {
                           'name'=>'mikky',
                           'number'=>'12',
                           'adress'=>' badvel,kadapa,a.p,india',
                            },

                           {
                           'name'=>'vijju',
                           'number'=>'15',
                           'adress'=>' raipur,ananthapur,a.p,india',
                            },

                           {
                           'name'=>'shyam',
                           'number'=>'16',
                           'adress'=>' raighad,rajsthan,india',
                            },
                          ]
                       }

(Новый комментарий: у меня есть такие данные: если мы посмотрим глубже, у меня есть одно и то же имя и номер в элементе студента, а также в элементе адреса, у меня есть еще один адрес в элементе адреса. Теперь мне нужно искать имя и номер студента в элементе address и получите адрес этого студента. Иногда у меня одни и те же имена с разными номерами, поэтому мне нужно искать и номер, и имя для адреса студента.)

и я обработал вот так

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

my $xml = new XML::Simple;
my $data = $xml->XMLin("data.xml");
print Dumper($data);
my $template = Template->new();
my $filename = 'output.tex';
$template->process(\*DATA, $data, $filename)
    || die "Template process failed: ", $template->error(), "\n";

system( "pdflatex $filename" );
__DATA__
\documentclass[a4paper,leqno,twoside]{article}
\begin{document}

[% FOREACH st IN university %]
[% st.name %] 
[%st.location%]
studentdata:
[% FOREACH student IN st.branch.electronics.student %]
Component type: [%+ student.name +%][%+ student.number +%]
[% FOREACH semester IN student.semester %]
[%+ semester.number +%]
[%+ semester.subjects +%]
[%+  semester.rank +%]
[% END %]
[% END %]
[% END %]

\end{document}

Но я получаю другой результат, а не то, что я хочу. После выполнения этого сценария я получаю результаты, когда у меня есть три или более студентов по электронике и два или более семестров для каждого студента, тогда только я получаю. в противном случае он печатает любую вещь, просто печатая данные ученика: три раза. например, если у меня есть один студент с одним семестром в университете в такой ситуации, он ничего не печатает, как это

       studentdata:
           studentdata:
            studentdata:

почему цикл for выполняется так, я не могу понять, что неправильно выиграть цикл for, но мне нужно напечатать так

name:
      svu
location: 
      ravru
student data:
   student name=xxx  number=12
  semester number=1 subjects=7 rank=2
   student name=xxx  number=15
  semester number=1 subjects=7 rank=10
 semester number=2 subjects=4 rank=1
 student name=xxx  number=16
 semester number=1 subjects=7 rank=2
 semester number=2 subjects=4 rank=2

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

 my $studentaddres;

  my $xml = new XML::Simple;
 my $data = $xml->XMLin("data.xml", ForceArray=>1);
  print Dumper($data);

 my $template = Template->new();
   my $filename = 'output.tex';
   $template->process(\*DATA, $data, $filename)
 || die "Template process failed: ", $template->error(), "\n";

 $studentaddres->{by_student_number} 
 = { map { $_->{number} => $_ } @{ $studentaddres->{address} }};

 system( "pdflatex $filename" );
  __DATA__
\documentclass[a4paper,leqno,twoside]{article}
   \begin{document}

 [% FOREACH st IN university %]
  [% st.name %] 
   [%st.location%]
  studentdata:
  [% FOREACH student IN st.branch.electronics.student %]
    Component type: [%+ student.name +%][%+ student.number +%]

  [% address = studentaddres.by_student_number.item( student.number );
  IF address %]
 [% address.adress %]
 [% END %]
 [% FOREACH semester IN student.semester %]
  [%+ semester.number +%]
   [%+ semester.subjects +%]
   [%+  semester.rank +%]
    [% END %]
   [% END %]
   [% END %]

  \end{document}

1 Ответ

3 голосов
/ 01 ноября 2011

Прежде всего, ваши данные не действительны perl. Во-вторых, итерация по хешу дает вам (Java-подобные) «входные» объекты. Так что 'st' => {key => 'name', value => 'svu'}. Таким образом, st.name ничто.

Это больше похоже на то, что вы хотите (или что работает, в любом случае):

name:
      [% university.name %] 
location:
      [% university.location %]
studentdata:
   [%- FOREACH student IN university.branch.electronics.student %]
      student name=[% student.name %] number=[% student.number %]
       [%- FOREACH semester IN student.semester %]
     semester number=[% semester.number %] subjects=[% semester.subjects 
           %] rank=[% semester.rank %]
       [%- END -%]
   [%- END -%]

И мне пришлось изменить «семестр» на ученике № 12, чтобы он был массивом, и снять число с заглавной буквы. Вот что у вас было:

   'semester'=>{
          'Number'=>'1',
          'subjects'=>'7',
           'rank'=>'1'
          }

Вот что я изменил:

   'semester'=>[{
          'number'=>'1',
          'subjects'=>'7',
           'rank'=>'1'
          }]

Без семестра в виде массива вы просто повторяли этот тип вещи снова:

( { key => 'number',   value => '1' }
, { key => 'subjects', value => '7' }
, { key => 'rank',     value => '1' } 
)

И не обязательно (или даже вероятно ) в этом порядке.

Используя правильно закрытый $var1 в качестве данных, код, который я поместил выше, дает мне:

   \documentclass[a4paper,leqno,twoside]{article}
   \begin{document}

name:
      svu 
location:
      ravru
studentdata:
      student name=xxx number=12
     semester number=1 subjects=7 rank=1
      student name=xxx number=15
     semester number=1 subjects=7 rank=10
     semester number=1 subjects=7 rank=1
      student name=xxx number=16
     semester number=1 subjects=7 rank=2
     semester number=2 subjects=4 rank=2
  \end{document}

Для отладки вашего скрипта вы можете внести следующие изменения:

my $template = Template->new( { EVAL_PERL => 1 } );

И затем, где вы хотите увидеть структуру, к которой обращаетесь, сделайте это:

 [% RAWPERL %]
 use Data::Dumper ();
 print Data::Dumper->Dump( [ $stash->get( 'semester' ) ], [ 'semester' ] ), "\n";
 [% END %]

Вы быстро увидите, когда в хеше в семестре отсутствуют поля чисел, предметов или рангов.


(Отвечая на комментарий) Ну, если у вас есть несколько учеников с адресами, как у некоторых, вы можете сделать следующее:

[% IF student.address;
    addr = student.address; %][%-
    -%]Address: [% addr.lines.1 %]
                [% addr.lines.2 %]
                [% addr.city %], [% addr.state %] [% addr.zip %]
[% END %]

Или, если у вас есть хэш адресов, вы можете сделать следующее.

[% IF address_for_student.exists( student.number );
     address = address_for_student.item( student.number );
     %]
...
[% END %]

(отвечая на новую адресную часть вопроса)

Вы можете массировать ваши данные перед презентацией. Это то, что я предлагаю до передачи данных на уровень представления. (Здесь $studentaddres - это просто ссылка на структуру в тайнике.)

$studentaddres->{by_student_number} 
    = { map { $_->{number} => $_ } @{ $studentaddres->{address} }}
    ;

Затем в слое презентации вы можете просто сделать это:

[% address = studentaddres.by_student_number.item( student.number );
   IF address %]
   ...
[% END %]

В общем, у вас должны быть ссылки, которые вам нужны до на уровень представления, что делает уровень представления просто вопросом отображения данных.

XML хранит вашу модель. Хорошо. XML прекрасно работает с деревьями, но не слишком хорошо строит сложные графики. Поэтому, если у вас сложные отношения (а XML :: Simple не собирается знать что-нибудь о них), вы должны использовать этот тип алгоритмической модели: retrieve & rarr; ссылка & rarr; дисплей . Вы должны сделать это с помощью YAML, JSON или даже строк, извлеченных из базы данных, поэтому этап связывания для меня является второй натурой.

Уровень представления - это неправильный уровень для поиска . Он должен просто обрабатывать списки из 0, 1 или многих или простых случаев, например, существует связь или нет.

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