Annotation of loncom/xml/lonxml.pm, revision 1.20

1.2       sakharuk    1: # The LearningOnline Network with CAPA
1.3       sakharuk    2: # XML Parser Module 
1.2       sakharuk    3: #
1.3       sakharuk    4: # last modified 06/26/00 by Alexander Sakharuk
1.2       sakharuk    5: 
1.4       albertel    6: package Apache::lonxml; 
1.1       sakharuk    7: 
                      8: use strict;
                      9: use HTML::TokeParser;
1.3       sakharuk   10: use Safe;
1.13      albertel   11: use Opcode;
1.7       albertel   12: 
                     13: sub register {
                     14:   my $space;
                     15:   my @taglist;
                     16:   my $temptag;
                     17:   ($space,@taglist) = @_;
                     18:   foreach $temptag (@taglist) {
                     19:     $Apache::lonxml::alltags{$temptag}=$space;
                     20:   }
                     21: }
1.11      sakharuk   22:                                      
1.4       albertel   23: use Apache::style;
1.3       sakharuk   24: use Apache::lontexconvert;
1.7       albertel   25: use Apache::run;
1.4       albertel   26: use Apache::londefdef;
1.7       albertel   27: use Apache::scripttag;
1.3       sakharuk   28: #==================================================   Main subroutine: xmlparse  
                     29: 
                     30: sub xmlparse {
                     31: 
1.18      albertel   32:  my ($target,$content_file_string,$safeinit,%style_for_target) = @_;
1.16      albertel   33:  my @pars = ();
                     34:  push (@pars,HTML::TokeParser->new(\$content_file_string));
1.3       sakharuk   35:  my $currentstring = '';
                     36:  my $finaloutput = ''; 
                     37:  my $newarg = '';
1.16      albertel   38:  my $result;
1.3       sakharuk   39:  my $safeeval = new Safe;
1.6       albertel   40:  $safeeval->permit("entereval");
1.13      albertel   41:  $safeeval->permit(":base_math");
1.19      albertel   42:  $safeeval->deny(":base_io");
                     43: #need to inspect this class of ops
                     44: # $safeeval->deny(":base_orig");
1.18      albertel   45:  if ( $safeinit ne '') {&Apache::run::run($safeinit,$safeeval);}
1.3       sakharuk   46: #-------------------- Redefinition of the target in the case of compound target
                     47: 
                     48:  ($target, my @tenta) = split('&&',$target);
                     49: 
                     50:  my @stack = (); 
                     51:  my @parstack = ();
1.17      albertel   52:  &initdepth;
1.3       sakharuk   53:  my $token;
1.16      albertel   54:  while ( $#pars > -1 ) {
                     55:    while ($token = $pars[$#pars]->get_token) {
                     56:      if ($token->[0] eq 'T') {
                     57:        $result=$token->[1];
                     58: #       $finaloutput .= &Apache::run::evaluate($token->[1],$safeeval,'');
                     59:      } elsif ($token->[0] eq 'S') {
                     60:        # add tag to stack 	    
                     61:        push (@stack,$token->[1]);
                     62:        # add parameters list to another stack
                     63:        push (@parstack,&parstring($token));
1.19      albertel   64:        &increasedepth($token);       
1.16      albertel   65:        if (exists $style_for_target{$token->[1]}) {
                     66: 	 $finaloutput .= &recurse($style_for_target{$token->[1]},
                     67: 				  $target,$safeeval,\%style_for_target,
                     68: 				  @parstack);
                     69:        } else {
1.17      albertel   70: 	 $result = &callsub("start_$token->[1]", $target, $token,\@parstack,
1.16      albertel   71: 			       \@pars, $safeeval, \%style_for_target);
                     72:        }              
                     73:      } elsif ($token->[0] eq 'E')  {
                     74:        #clear out any tags that didn't end
                     75:        while ($token->[1] ne $stack[$#stack] 
1.19      albertel   76: 	      && ($#stack > -1)) {pop @stack;pop @parstack;&decreasedepth($token);}
1.16      albertel   77:        
                     78:        if (exists $style_for_target{'/'."$token->[1]"}) {
                     79: 	 $finaloutput .= &recurse($style_for_target{'/'."$token->[1]"},
                     80: 				  $target,$safeeval,\%style_for_target,
                     81: 				  @parstack);
                     82:        } else {
1.17      albertel   83: 	 $result = &callsub("end_$token->[1]", $target, $token, \@parstack,
1.16      albertel   84: 			       \@pars,$safeeval, \%style_for_target);
1.13      albertel   85:        }
1.16      albertel   86:      }
                     87:      if ($result ne "" ) {
                     88:        if ( $#parstack > -1 ) { 
1.13      albertel   89: 	 $finaloutput .= &Apache::run::evaluate($result,$safeeval,
                     90: 						$parstack[$#parstack]);
1.16      albertel   91:        } else {
                     92: 	 $finaloutput .= &Apache::run::evaluate($result,$safeeval,'');
1.13      albertel   93:        }
1.16      albertel   94:        $result = '';
1.2       sakharuk   95:      }
1.19      albertel   96:      if ($token->[0] eq 'E') { pop @stack;pop @parstack;&decreasedepth($token);}
1.5       albertel   97:    }
1.16      albertel   98:    pop @pars;
1.3       sakharuk   99:  }
                    100:  return $finaloutput;
1.15      albertel  101: }
                    102: 
                    103: sub recurse {
                    104:   
                    105:   my @innerstack = (); 
                    106:   my @innerparstack = ();
                    107:   my ($newarg,$target,$safeeval,$style_for_target,@parstack) = @_;
1.16      albertel  108:   my @pat = ();
                    109:   push (@pat,HTML::TokeParser->new(\$newarg));
1.15      albertel  110:   my $tokenpat;
                    111:   my $partstring = '';
                    112:   my $output='';
1.16      albertel  113:   my $decls='';
                    114:   while ( $#pat > -1 ) {
                    115:     while  ($tokenpat = $pat[$#pat]->get_token) {
                    116:       if ($tokenpat->[0] eq 'T') {
                    117: 	$partstring = $tokenpat->[1];
                    118:       } elsif ($tokenpat->[0] eq 'S') {
                    119: 	push (@innerstack,$tokenpat->[1]);
                    120: 	push (@innerparstack,&parstring($tokenpat));
1.19      albertel  121: 	&increasedepth($tokenpat);
1.16      albertel  122: 	$partstring = &callsub("start_$tokenpat->[1]", 
                    123: 			       $target, $tokenpat, \@innerparstack,
                    124: 			       \@pat, $safeeval, $style_for_target);
                    125:       } elsif ($tokenpat->[0] eq 'E') {
                    126: 	#clear out any tags that didn't end
                    127: 	while ($tokenpat->[1] ne $innerstack[$#innerstack] 
1.17      albertel  128: 	       && ($#innerstack > -1)) {pop @innerstack;pop @innerparstack;
1.19      albertel  129: 					&decreasedepth($tokenpat);}
1.16      albertel  130: 	$partstring = &callsub("end_$tokenpat->[1]",
                    131: 			       $target, $tokenpat, \@innerparstack,
                    132: 			       \@pat, $safeeval, $style_for_target);
                    133:       }
                    134:       #pass both the variable to the style tag, and the tag we 
                    135:       #are processing inside the <definedtag>
                    136:       if ( $partstring ne "" ) {
                    137: 	if ( $#parstack > -1 ) { 
                    138: 	  if ( $#innerparstack > -1 ) { 
                    139: 	    $decls= $parstack[$#parstack].$innerparstack[$#innerparstack];
                    140: 	  } else {
                    141: 	    $decls= $parstack[$#parstack];
                    142: 	  }
                    143: 	} else {
                    144: 	  if ( $#innerparstack > -1 ) { 
                    145: 	    $decls=$innerparstack[$#innerparstack];
                    146: 	  } else {
                    147: 	    $decls='';
                    148: 	  }
                    149: 	}
                    150: 	$output .= &Apache::run::evaluate($partstring,$safeeval,$decls);
                    151: 	$partstring = '';
                    152:       }
1.17      albertel  153:       if ($tokenpat->[0] eq 'E') { pop @innerstack;pop @innerparstack;
1.19      albertel  154: 				 &decreasedepth($tokenpat);}
1.15      albertel  155:     }
1.16      albertel  156:     pop @pat;
1.15      albertel  157:   }
                    158:   return $output;
1.7       albertel  159: }
                    160: 
                    161: sub callsub {
1.14      albertel  162:   my ($sub,$target,$token,$parstack,$parser,$safeeval,$style)=@_;
1.7       albertel  163:   my $currentstring='';
                    164:   {
                    165:     no strict 'refs';
                    166:     if (my $space=$Apache::lonxml::alltags{$token->[1]}) {
1.20    ! albertel  167:       #print "Calling sub $sub in $space<br>\n";
1.7       albertel  168:       $sub="$space\:\:$sub";
1.17      albertel  169:       $Apache::lonxml::curdepth=join('_',@Apache::lonxml::depthcounter);
1.16      albertel  170:       $currentstring = &$sub($target,$token,$parstack,$parser,
                    171: 			     $safeeval,$style);
1.7       albertel  172:     } else {
1.20    ! albertel  173:       #print "NOT Calling sub $sub<br>\n";
1.7       albertel  174:       if (defined($token->[4])) {
                    175: 	$currentstring = $token->[4];
                    176:       } else {
                    177: 	$currentstring = $token->[2];
                    178:       }
                    179:     }
                    180:     use strict 'refs';
                    181:   }
                    182:   return $currentstring;
1.17      albertel  183: }
                    184: 
                    185: sub initdepth {
                    186:   @Apache::lonxml::depthcounter=();
                    187:   $Apache::lonxml::depth=-1;
                    188:   $Apache::lonxml::olddepth=-1;
                    189: }
                    190: 
                    191: sub increasedepth {
1.19      albertel  192:   my ($token) = @_;
1.17      albertel  193:   if ($Apache::lonxml::depth<$Apache::lonxml::olddepth-1) {
                    194:     $#Apache::lonxml::depthcounter--;
                    195:     $Apache::lonxml::olddepth=$Apache::lonxml::depth;
                    196:   }
                    197:   $Apache::lonxml::depth++;
1.19      albertel  198: #  print "<br>s $Apache::lonxml::depth : $Apache::lonxml::olddepth : $token->[1]<br>\n";
1.17      albertel  199:   $Apache::lonxml::depthcounter[$Apache::lonxml::depth]++;
                    200:   if ($Apache::lonxml::depthcounter[$Apache::lonxml::depth]==1) {
                    201:     $Apache::lonxml::olddepth=$Apache::lonxml::depth;
                    202:   }
                    203: }
                    204: 
                    205: sub decreasedepth {
1.19      albertel  206:   my ($token) = @_;
1.17      albertel  207:   $Apache::lonxml::depth--;
1.19      albertel  208: #  print "<br>e $Apache::lonxml::depth : $Apache::lonxml::olddepth : $token->[1]<br>\n";
1.1       sakharuk  209: }
1.19      albertel  210: 
                    211: sub get_all_text {
                    212: 
                    213:  my($tag,$pars)= @_;
                    214:  my $depth=0;
                    215:  my $token;
                    216:  my $result='';
                    217:  while (($depth >=0) && ($token = $pars->get_token)) {
                    218:    if ($token->[0] eq 'T') {
                    219:      $result.=$token->[1];
                    220:    } elsif ($token->[0] eq 'S') {
                    221:      if ($token->[1] eq $tag) { $depth++; }
                    222:      $result.=$token->[4];
                    223:    } elsif ($token->[0] eq 'E')  {
                    224:      if ($token->[1] eq $tag) { $depth--; }
                    225:      #skip sending back the last end tag
                    226:      if ($depth > -1) { $result.=$token->[2]; }
                    227:    }
                    228:  }
                    229:  return $result
                    230: }
                    231: 
1.1       sakharuk  232: 
1.8       albertel  233: sub parstring {
                    234:   my ($token) = @_;
                    235:   my $temp='';
1.20    ! albertel  236:   map {
        !           237:     if ($_=~/\w+/) {
        !           238:       $temp .= "my \$$_=\"$token->[2]->{$_}\";"
        !           239:     }
        !           240:   } @{$token->[3]};
1.8       albertel  241:   return $temp;
                    242: }
1.1       sakharuk  243: 1;
                    244: __END__
1.11      sakharuk  245: 
                    246: 
                    247: 
                    248: 
                    249: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>