[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/se3-unattended/var/se3/unattended/install/linuxaux/opt/perl/lib/site_perl/5.10.0/XML/XPath/ -> Function.pm (source)

   1  # $Id: Function.pm,v 1.26 2002/12/26 17:24:50 matt Exp $
   2  
   3  package XML::XPath::Function;
   4  use XML::XPath::Number;
   5  use XML::XPath::Literal;
   6  use XML::XPath::Boolean;
   7  use XML::XPath::NodeSet;
   8  use XML::XPath::Node::Attribute;
   9  use strict;
  10  
  11  sub new {
  12      my $class = shift;
  13      my ($pp, $name, $params) = @_;
  14      bless { 
  15          pp => $pp, 
  16          name => $name, 
  17          params => $params 
  18          }, $class;
  19  }
  20  
  21  sub as_string {
  22      my $self = shift;
  23      my $string = $self->{name} . "(";
  24      my $second;
  25      foreach (@{$self->{params}}) {
  26          $string .= "," if $second++;
  27          $string .= $_->as_string;
  28      }
  29      $string .= ")";
  30      return $string;
  31  }
  32  
  33  sub as_xml {
  34      my $self = shift;
  35      my $string = "<Function name=\"$self->{name}\"";
  36      my $params = "";
  37      foreach (@{$self->{params}}) {
  38          $params .= "<Param>" . $_->as_string . "</Param>\n";
  39      }
  40      if ($params) {
  41          $string .= ">\n$params</Function>\n";
  42      }
  43      else {
  44          $string .= " />\n";
  45      }
  46      
  47      return $string;
  48  }
  49  
  50  sub evaluate {
  51      my $self = shift;
  52      my $node = shift;
  53      if ($node->isa('XML::XPath::NodeSet')) {
  54          $node = $node->get_node(1);
  55      }
  56      my @params;
  57      foreach my $param (@{$self->{params}}) {
  58          my $results = $param->evaluate($node);
  59          push @params, $results;
  60      }
  61      $self->_execute($self->{name}, $node, @params);
  62  }
  63  
  64  sub _execute {
  65      my $self = shift;
  66      my ($name, $node, @params) = @_;
  67      $name =~ s/-/_/g;
  68      no strict 'refs';
  69      $self->$name($node, @params);
  70  }
  71  
  72  # All functions should return one of:
  73  # XML::XPath::Number
  74  # XML::XPath::Literal (string)
  75  # XML::XPath::NodeSet
  76  # XML::XPath::Boolean
  77  
  78  ### NODESET FUNCTIONS ###
  79  
  80  sub last {
  81      my $self = shift;
  82      my ($node, @params) = @_;
  83      die "last: function doesn't take parameters\n" if (@params);
  84      return XML::XPath::Number->new($self->{pp}->get_context_size);
  85  }
  86  
  87  sub position {
  88      my $self = shift;
  89      my ($node, @params) = @_;
  90      if (@params) {
  91          die "position: function doesn't take parameters [ ", @params, " ]\n";
  92      }
  93      # return pos relative to axis direction
  94      return XML::XPath::Number->new($self->{pp}->get_context_pos);
  95  }
  96  
  97  sub count {
  98      my $self = shift;
  99      my ($node, @params) = @_;
 100      die "count: Parameter must be a NodeSet\n" unless $params[0]->isa('XML::XPath::NodeSet');
 101      return XML::XPath::Number->new($params[0]->size);
 102  }
 103  
 104  sub id {
 105      my $self = shift;
 106      my ($node, @params) = @_;
 107      die "id: Function takes 1 parameter\n" unless @params == 1;
 108      my $results = XML::XPath::NodeSet->new();
 109      if ($params[0]->isa('XML::XPath::NodeSet')) {
 110          # result is the union of applying id() to the
 111          # string value of each node in the nodeset.
 112          foreach my $node ($params[0]->get_nodelist) {
 113              my $string = $node->string_value;
 114              $results->append($self->id($node, XML::XPath::Literal->new($string)));
 115          }
 116      }
 117      else { # The actual id() function...
 118          my $string = $self->string($node, $params[0]);
 119          $_ = $string->value; # get perl scalar
 120          my @ids = split; # splits $_
 121          foreach my $id (@ids) {
 122              if (my $found = $node->getElementById($id)) {
 123                  $results->push($found);
 124              }
 125          }
 126      }
 127      return $results;
 128  }
 129  
 130  sub local_name {
 131      my $self = shift;
 132      my ($node, @params) = @_;
 133      if (@params > 1) {
 134          die "name() function takes one or no parameters\n";
 135      }
 136      elsif (@params) {
 137          my $nodeset = shift(@params);
 138          $node = $nodeset->get_node(1);
 139      }
 140      
 141      return XML::XPath::Literal->new($node->getLocalName);
 142  }
 143  
 144  sub namespace_uri {
 145      my $self = shift;
 146      my ($node, @params) = @_;
 147      die "namespace-uri: Function not supported\n";
 148  }
 149  
 150  sub name {
 151      my $self = shift;
 152      my ($node, @params) = @_;
 153      if (@params > 1) {
 154          die "name() function takes one or no parameters\n";
 155      }
 156      elsif (@params) {
 157          my $nodeset = shift(@params);
 158          $node = $nodeset->get_node(1);
 159      }
 160      
 161      return XML::XPath::Literal->new($node->getName);
 162  }
 163  
 164  ### STRING FUNCTIONS ###
 165  
 166  sub string {
 167      my $self = shift;
 168      my ($node, @params) = @_;
 169      die "string: Too many parameters\n" if @params > 1;
 170      if (@params) {
 171          return XML::XPath::Literal->new($params[0]->string_value);
 172      }
 173      
 174      # TODO - this MUST be wrong! - not sure now. -matt
 175      return XML::XPath::Literal->new($node->string_value);
 176      # default to nodeset with just $node in.
 177  }
 178  
 179  sub concat {
 180      my $self = shift;
 181      my ($node, @params) = @_;
 182      die "concat: Too few parameters\n" if @params < 2;
 183      my $string = join('', map {$_->string_value} @params);
 184      return XML::XPath::Literal->new($string);
 185  }
 186  
 187  sub starts_with {
 188      my $self = shift;
 189      my ($node, @params) = @_;
 190      die "starts-with: incorrect number of params\n" unless @params == 2;
 191      my ($string1, $string2) = ($params[0]->string_value, $params[1]->string_value);
 192      if (substr($string1, 0, length($string2)) eq $string2) {
 193          return XML::XPath::Boolean->True;
 194      }
 195      return XML::XPath::Boolean->False;
 196  }
 197  
 198  sub contains {
 199      my $self = shift;
 200      my ($node, @params) = @_;
 201      die "starts-with: incorrect number of params\n" unless @params == 2;
 202      my $value = $params[1]->string_value;
 203      if ($params[0]->string_value =~ /(.*?)\Q$value\E(.*)/) {
 204          # $1 and $2 stored for substring funcs below
 205          # TODO: Fix this nasty implementation!
 206          return XML::XPath::Boolean->True;
 207      }
 208      return XML::XPath::Boolean->False;
 209  }
 210  
 211  sub substring_before {
 212      my $self = shift;
 213      my ($node, @params) = @_;
 214      die "starts-with: incorrect number of params\n" unless @params == 2;
 215      if ($self->contains($node, @params)->value) {
 216          return XML::XPath::Literal->new($1); # hope that works!
 217      }
 218      else {
 219          return XML::XPath::Literal->new('');
 220      }
 221  }
 222  
 223  sub substring_after {
 224      my $self = shift;
 225      my ($node, @params) = @_;
 226      die "starts-with: incorrect number of params\n" unless @params == 2;
 227      if ($self->contains($node, @params)->value) {
 228          return XML::XPath::Literal->new($2);
 229      }
 230      else {
 231          return XML::XPath::Literal->new('');
 232      }
 233  }
 234  
 235  sub substring {
 236      my $self = shift;
 237      my ($node, @params) = @_;
 238      die "substring: Wrong number of parameters\n" if (@params < 2 || @params > 3);
 239      my ($str, $offset, $len);
 240      $str = $params[0]->string_value;
 241      $offset = $params[1]->value;
 242      $offset--; # uses 1 based offsets
 243      if (@params == 3) {
 244          $len = $params[2]->value;
 245      }
 246      return XML::XPath::Literal->new(substr($str, $offset, $len));
 247  }
 248  
 249  sub string_length {
 250      my $self = shift;
 251      my ($node, @params) = @_;
 252      die "string-length: Wrong number of params\n" if @params > 1;
 253      if (@params) {
 254          return XML::XPath::Number->new(length($params[0]->string_value));
 255      }
 256      else {
 257          return XML::XPath::Number->new(
 258                  length($node->string_value)
 259                  );
 260      }
 261  }
 262  
 263  sub normalize_space {
 264      my $self = shift;
 265      my ($node, @params) = @_;
 266      die "normalize-space: Wrong number of params\n" if @params > 1;
 267      my $str;
 268      if (@params) {
 269          $str = $params[0]->string_value;
 270      }
 271      else {
 272          $str = $node->string_value;
 273      }
 274      $str =~ s/^\s*//;
 275      $str =~ s/\s*$//;
 276      $str =~ s/\s+/ /g;
 277      return XML::XPath::Literal->new($str);
 278  }
 279  
 280  sub translate {
 281      my $self = shift;
 282      my ($node, @params) = @_;
 283      die "translate: Wrong number of params\n" if @params != 3;
 284      local $_ = $params[0]->string_value;
 285      my $find = $params[1]->string_value;
 286      my $repl = $params[2]->string_value;
 287      eval "tr/\\Q$find\\E/\\Q$repl\\E/d, 1" or die $@;
 288      return XML::XPath::Literal->new($_);
 289  }
 290  
 291  ### BOOLEAN FUNCTIONS ###
 292  
 293  sub boolean {
 294      my $self = shift;
 295      my ($node, @params) = @_;
 296      die "boolean: Incorrect number of parameters\n" if @params != 1;
 297      return $params[0]->to_boolean;
 298  }
 299  
 300  sub not {
 301      my $self = shift;
 302      my ($node, @params) = @_;
 303      $params[0] = $params[0]->to_boolean unless $params[0]->isa('XML::XPath::Boolean');
 304      $params[0]->value ? XML::XPath::Boolean->False : XML::XPath::Boolean->True;
 305  }
 306  
 307  sub true {
 308      my $self = shift;
 309      my ($node, @params) = @_;
 310      die "true: function takes no parameters\n" if @params > 0;
 311      XML::XPath::Boolean->True;
 312  }
 313  
 314  sub false {
 315      my $self = shift;
 316      my ($node, @params) = @_;
 317      die "true: function takes no parameters\n" if @params > 0;
 318      XML::XPath::Boolean->False;
 319  }
 320  
 321  sub lang {
 322      my $self = shift;
 323      my ($node, @params) = @_;
 324      die "lang: function takes 1 parameter\n" if @params != 1;
 325      my $lang = $node->findvalue('(ancestor-or-self::*[@xml:lang]/@xml:lang)[last()]');
 326      my $lclang = lc($params[0]->string_value);
 327      # warn("Looking for lang($lclang) in $lang\n");
 328      if (substr(lc($lang), 0, length($lclang)) eq $lclang) {
 329          return XML::XPath::Boolean->True;
 330      }
 331      else {
 332          return XML::XPath::Boolean->False;
 333      }
 334  }
 335  
 336  ### NUMBER FUNCTIONS ###
 337  
 338  sub number {
 339      my $self = shift;
 340      my ($node, @params) = @_;
 341      die "number: Too many parameters\n" if @params > 1;
 342      if (@params) {
 343          if ($params[0]->isa('XML::XPath::Node')) {
 344              return XML::XPath::Number->new(
 345                      $params[0]->string_value
 346                      );
 347          }
 348          return $params[0]->to_number;
 349      }
 350      
 351      return XML::XPath::Number->new( $node->string_value );
 352  }
 353  
 354  sub sum {
 355      my $self = shift;
 356      my ($node, @params) = @_;
 357      die "sum: Parameter must be a NodeSet\n" unless $params[0]->isa('XML::XPath::NodeSet');
 358      my $sum = 0;
 359      foreach my $node ($params[0]->get_nodelist) {
 360          $sum += $self->number($node)->value;
 361      }
 362      return XML::XPath::Number->new($sum);
 363  }
 364  
 365  sub floor {
 366      my $self = shift;
 367      my ($node, @params) = @_;
 368      require POSIX;
 369      my $num = $self->number($node, @params);
 370      return XML::XPath::Number->new(
 371              POSIX::floor($num->value));
 372  }
 373  
 374  sub ceiling {
 375      my $self = shift;
 376      my ($node, @params) = @_;
 377      require POSIX;
 378      my $num = $self->number($node, @params);
 379      return XML::XPath::Number->new(
 380              POSIX::ceil($num->value));
 381  }
 382  
 383  sub round {
 384      my $self = shift;
 385      my ($node, @params) = @_;
 386      my $num = $self->number($node, @params);
 387      require POSIX;
 388      return XML::XPath::Number->new(
 389              POSIX::floor($num->value + 0.5)); # Yes, I know the spec says don't do this...
 390  }
 391  
 392  1;


Generated: Tue Mar 17 22:47:18 2015 Cross-referenced by PHPXref 0.7.1