【问题标题】:Why do I get an error in FOREACH loop using Template?为什么我在使用模板的 FOREACH 循环中出现错误?
【发布时间】:2011-12-19 14:31:29
【问题描述】:

我需要帮助解决这个问题,我在过去 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',
                            },
                          ]
                       }

(新评论:我有这样的数据,如果我们深入研究,我在学生元素和地址元素中都有相同的姓名和号码,我在地址元素中还有一个地址。现在我需要搜索地址元素中的学生姓名和编号并获取该学生的地址。有时我的姓名相同但编号不同,因此我需要同时搜索编号和姓名来查找学生地址。)

我是这样处理的

#!/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:
            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}

【问题讨论】:

    标签: perl templates template-toolkit


    【解决方案1】:

    首先,您的数据不是有效的 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 → link → display .您必须使用 YAML 或 JSON 甚至从数据库中提取的行来执行此操作,因此链接阶段对我来说是第二天性。

    表示层是错误的搜索层。它应该只处理 0、1 或许多或简单情况的列表,例如关系存在或不存在。

    【讨论】:

    • 我有 15 所大学,所以我编写了 for 循环来获取所有大学的,并且我得到了所有值,但我的问题在于第二个 for 循环。我无法获得我想要的学生元素。如果一个学生和一个学期的电子学,for循环执行三次。如果我有两个或更多的学生和两个或更多的电子学学期,它会准确打印。我不知道为什么会出现这个问题。
    • @pavini,正如我所说。 1)您的数据不好,2)您正在遍历哈希。你转了三圈,因为有三把钥匙。查看我对学生 #12 所做的更改。
    • 非常感谢您的帮助。它的工作,我很高兴。
    • ,您好,很抱歉再次询问我的问题是在我的学生元素中,我有编号和姓名,而且我有相同的数据学生姓名和编号以及地址。如果找到匹配项,我需要搜索该数据中的每个学生姓名和编号,然后获取地址并连同学生姓名和编号一起打印。你能建议我该怎么做吗?
    • 非常感谢您的回复,我按照您的说法尝试了但它不起作用,如果您不介意我清楚地编辑了我的问题并将我的问题添加为新评论。你能看看评论并建议我吗,因为我是使用模板工具包的初学者。
    猜你喜欢
    • 1970-01-01
    • 2016-05-31
    • 2021-04-30
    • 2021-05-22
    • 1970-01-01
    • 1970-01-01
    • 2016-04-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多