--- loncom/xml/lonxml.pm	2000/06/23 20:40:06	1.2
+++ loncom/xml/lonxml.pm	2000/08/02 16:47:53	1.14
@@ -1,149 +1,193 @@
 # The LearningOnline Network with CAPA
-# Style Parser Module 
+# XML Parser Module 
 #
-# last modified 06/23/00 by Alexander Sakharuk
+# last modified 06/26/00 by Alexander Sakharuk
 
-package Apache::lonstyleparser; 
+package Apache::lonxml; 
 
 use strict;
 use HTML::TokeParser;
+use Safe;
+use Opcode;
 
-#============================================================= style subroutine 
-
-sub styleparser {
-
-  my ($target,$content_style_string) = @_;
-
-#------------------------------------------- target redefinition (if necessary) 
-    
-  my @target_string = '';
-  my $element;
-   
-  ($element,@target_string) = split ('&&',$target);
-
-  map {$content_style_string =~ s/\<(.*)$_\>/\<$1$element\>/g; } @target_string;
-   
-  $target = $element;
-   
-#-------------------------------------------- create a table for defined target
-#----------------------------------------- from the information from Style File
-
-  my @value_style = ();
-  my $current_key = '';
-  my $current_value = '';
-  my $stoken;
-  my $flag;                  
-  my $iele;
-
-  my $pstyle = HTML::TokeParser->new(\$content_style_string);
-
-  while ($stoken = $pstyle->get_token) {
-#----------------------------------------------------- start for tag definition
-   if ($stoken->[0] eq 'S' and $stoken->[1] eq 'definetag') {
-#-------------------------------------------------------------- new key in hash
-    $current_key = $stoken->[2]{name};
-    $flag = 0;
-#-------------------------------------------------------------- metadata output
-    if ($target eq 'meta') {
-     while ($stoken = $pstyle->get_token and $stoken->[1] ne 'definetag') { 
-       if ($stoken->[0] eq 'S' and $stoken->[1] eq 'meta') {
-        while ($stoken = $pstyle->get_token and $stoken->[1] ne 'meta') {
-	    $current_value .= $stoken->[1];
-        }
+sub register {
+  my $space;
+  my @taglist;
+  my $temptag;
+  ($space,@taglist) = @_;
+  foreach $temptag (@taglist) {
+    $Apache::lonxml::alltags{$temptag}=$space;
+  }
+}
+                                     
+use Apache::style;
+use Apache::lontexconvert;
+use Apache::run;
+use Apache::londefdef;
+use Apache::scripttag;
+#==================================================   Main subroutine: xmlparse  
+
+sub xmlparse {
+
+ my ($target,$content_file_string,%style_for_target) = @_;
+ my $pars = HTML::TokeParser->new(\$content_file_string);
+ my $currentstring = '';
+ my $finaloutput = ''; 
+ my $newarg = '';
+ my $safeeval = new Safe;
+ $safeeval->permit("entereval");
+ $safeeval->permit(":base_math");
+#-------------------- Redefinition of the target in the case of compound target
+
+ ($target, my @tenta) = split('&&',$target);
+
+#------------------------- Stack definition (in stack we have all current tags)
+
+ my @stack = (); 
+ my @parstack = ();
+
+#------------------------------------- Parse input string (content_file_string)
+ 
+ my $token;
+ 
+ while ($token = $pars->get_token) {
+   if ($token->[0] eq 'T') {
+     $finaloutput .= &Apache::run::evaluate($token->[1],$safeeval,'');
+   } elsif ($token->[0] eq 'S') {
+     # add tag to stack 	    
+     push (@stack,$token->[1]);
+     # add parameters list to another stack
+     push (@parstack,&parstring($token));
+     
+     if (exists $style_for_target{$token->[1]}) {
+       #basically recurse, but we never got more than one level down so just 
+       #create the new context here
+       my @innerstack = (); 
+       my @innerparstack = ();
+       # use style file definition
+       $newarg = $style_for_target{$token->[1]};       
+       my $pat = HTML::TokeParser->new(\$newarg);
+       my $tokenpat = '';
+       my $partstring = '';
+
+       while  ($tokenpat = $pat->get_token) {
+	 if ($tokenpat->[0] eq 'T') {
+	   $partstring = $tokenpat->[1];
+	 } elsif ($tokenpat->[0] eq 'S') {
+	   push (@innerstack,$tokenpat->[1]);
+	   push (@innerparstack,&parstring($tokenpat));
+	   $partstring = &callsub("start_$tokenpat->[1]", 
+				  $target, $tokenpat, \@innerparstack,
+				  $pat, $safeeval, \%style_for_target);
+	 } elsif ($tokenpat->[0] eq 'E') {
+	   #clear out any tags that didn't end
+	   while ($tokenpat->[1] ne $innerstack[$#innerstack] 
+		  && ($#innerstack > 0)) {pop @innerstack;pop @innerparstack;}
+	   $partstring = &callsub("end_$tokenpat->[1]",
+				  $target, $tokenpat, \@innerparstack,
+				  $pat, $safeeval, \%style_for_target);
+	 }
+	 #pass both the variable to the style tag, and the tag we 
+	 #are processing inside the <definedtag>
+	 if ($partstring ne "" ) {
+	   $finaloutput .= &Apache::run::evaluate($partstring,$safeeval,
+		$parstack[$#parstack].$innerparstack[$#innerparstack]);
+	 }
+	 if ($tokenpat->[0] eq 'E') { pop @innerstack;pop @innerparstack; }
        }
-     }
-    } else {
-#--------------------------------------------------------------- outtext output
-     while ($stoken = $pstyle->get_token and $stoken->[1] ne 'outtext') {
-	   if ($stoken->[1] eq 'definetag') {
-	     $flag = 1;
-             last;
-	   }
-      }
-     if ($flag == 0) { 
-       while ($stoken = $pstyle->get_token and $stoken->[0] ne 'S') {
-	    $current_value .= $stoken->[1];
+     } else {
+       my $result = &callsub("start_$token->[1]", $target, $token,\@parstack,
+			     $pars, $safeeval, \%style_for_target);
+       if ($result ne "" ) {
+	 $finaloutput .= &Apache::run::evaluate($result,$safeeval,
+						$parstack[$#parstack]);
        }
-      while ($stoken->[1] ne 'definetag') {
-       if ($stoken->[0] eq 'S' and $stoken->[1] eq $target) {
-	while ($stoken = $pstyle->get_token) {
-	 if ($stoken->[1] ne $target) {
-	   if ($stoken->[0] eq 'S') {
-	       my $flagelem = 0;
-               for (my $i=$#value_style-1;$i>0;$i=$i-2) {
-		   if ($stoken->[1] eq $value_style[$i]) {
-		       $flagelem = 1;
-                       $iele = $i+1;
-                       last;
-		   }
-	       }
-	       if ($flagelem == 0) {
-	         $current_value .= $stoken->[4];
-     	       } else {
-		   $current_value .= $value_style[$iele];
-	       }
-	   } 
-           if ($stoken->[0] eq 'E') {
-	       my $flagelem = 0;
-               for (my $i=$#value_style-1;$i>0;$i=$i-2) {
-		   if ('/'.$stoken->[1] eq $value_style[$i]) {
-		       $flagelem = 1;
-                       $iele = $i+1;
-                       last;
-		   }
-	       }
-	       if ($flagelem == 0) {
-                 $current_value .= $stoken->[2];
-     	       } else {
-		   $current_value .= $value_style[$iele];
-	       }
-	   } 
-           if ($stoken->[0] eq 'T') {
-             $current_value .= $stoken->[1]; 
-	   }                 
-	 }  else {      
-		last;
+     }              
+   } elsif ($token->[0] eq 'E')  {
+     #clear out any tags that didn't end
+     while ($token->[1] ne $stack[$#stack] 
+	    && ($#stack > 0)) {pop @stack;pop @parstack;}
+
+     if (exists $style_for_target{'/'."$token->[1]"}) {
+       my @innerstack = (); 
+       my @innerparstack = ();
+       $newarg = $style_for_target{'/'."$token->[1]"};
+       my $pat = HTML::TokeParser->new(\$newarg);
+       my $tokenpat;
+       my $partstring = '';
+       
+       while  ($tokenpat = $pat->get_token) {
+	 if ($tokenpat->[0] eq 'T') {
+	   $partstring = $tokenpat->[1];
+	 } elsif ($tokenpat->[0] eq 'S') {
+	   push (@innerstack,$tokenpat->[1]);
+	   push (@innerparstack,&parstring($tokenpat));
+	   $partstring = &callsub("start_$tokenpat->[1]", 
+				  $target, $tokenpat, \@innerparstack,
+				  $pat, $safeeval, \%style_for_target);
+	 } elsif ($tokenpat->[0] eq 'E') {
+	   #clear out any tags that didn't end
+	   while ($tokenpat->[1] ne $innerstack[$#innerstack] 
+		  && ($#innerstack > 0)) {pop @innerstack;pop @innerparstack;}
+	   $partstring = &callsub("end_$tokenpat->[1]",
+				  $target, $tokenpat, \@innerparstack,
+				  $pat, $safeeval, \%style_for_target);
 	 }
-        }
-       } elsif ($stoken->[0] eq 'S' and $stoken->[1] ne $target) {
-	  my $tempotempo = $stoken->[1];
-	   while ($stoken = $pstyle->get_token and $stoken->[1] ne $tempotempo) {
-	   }
+	 #pass both the variable to the style tag, and the tag we 
+	 #are processing inside the <definedtag>
+	 if ( $partstring ne "" ) {
+	   $finaloutput .= &Apache::run::evaluate($partstring,$safeeval,
+		$parstack[$#parstack].$innerparstack[$#innerparstack]);
+	 }
+	 if ($tokenpat->[0] eq 'E') { pop @innerstack;pop @innerparstack; }
+       }
+     } else {
+       my $result = &callsub("end_$token->[1]", $target, $token, \@parstack,
+			     $pars,$safeeval, \%style_for_target);
+       if ($result ne "") {
+	 $finaloutput .= &Apache::run::evaluate($result,$safeeval,
+						$parstack[$#parstack]);
        }
+     }
+     pop @stack; 
+     pop @parstack;
+   }
+ }
+ return $finaloutput;
+}
 
-       while ($stoken = $pstyle->get_token) {
-        if ($stoken->[0] eq 'T') {
-          $current_value .= $stoken->[1];
-	} 
-        if ($stoken->[0] eq 'E') {
-	  last;
-	} 
-        if ($stoken->[0] eq 'S') {
-	  last;
-	}
-       }	     
-    
+sub callsub {
+  my ($sub,$target,$token,$parstack,$parser,$safeeval,$style)=@_;
+  my $currentstring='';
+  {
+    no strict 'refs';
+    if (my $space=$Apache::lonxml::alltags{$token->[1]}) {
+      #print "Calling sub $sub in $space \n";
+      $sub="$space\:\:$sub";
+      $currentstring = &$sub($target,$token,\@$parstack,$parser,$safeeval,$style);
+    } else {
+      #print "NOT Calling sub $sub\n";
+      if (defined($token->[4])) {
+	$currentstring = $token->[4];
+      } else {
+	$currentstring = $token->[2];
       }
-     }
     }
-    
-   }    
-   $current_value =~ s/(\s)+/$1/g;
-     if ($current_value ne ' ' and $current_value ne '' ) {  
-       push (@value_style,lc $current_key,$current_value);
-     }
-     $current_key = '';
-     $current_value = '';         
-
-  }  
-  my %style_for_target = @value_style;   
-#--------------------------------------------------------------- check printing
-#  while (($current_key,$current_value) = each %style_for_target) {
-#       print "$current_key => $current_value\n";
-#  }
-#---------------------------------------------------------------- return result
-  return %style_for_target; 
+    use strict 'refs';
+  }
+  return $currentstring;
 }
 
+sub parstring {
+  my ($token) = @_;
+  my $temp='';
+  map {$temp .= "my \$$_=\"$token->[2]->{$_}\";"} @{$token->[3]};
+  return $temp;
+}
 1;
 __END__
+
+
+
+
+