deprecated/buildtools/buildsystemtools/lib/XML/XQL/Plus.pm
author lorewang
Thu, 11 Nov 2010 11:26:32 +0800
changeset 677 44e49837144a
parent 655 3f65fd25dfd4
permissions -rw-r--r--
update release info
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
655
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
     1
############################################################################
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
     2
# Copyright (c) 1998 Enno Derksen
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
     3
# All rights reserved.
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
     4
# This program is free software; you can redistribute it and/or modify it
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
     5
# under the same terms as Perl itself. 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
     6
############################################################################
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
     7
#
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
     8
# Extra functionality that is not part of the XQL spec
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
     9
#
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    10
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    11
package XML::XQL;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    12
use strict;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    13
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    14
BEGIN 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    15
{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    16
    die "don't use/require XML::XQL::Plus, either use/require XML::XQL or XML::XQL::Strict" unless $XML::XQL::Included;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    17
};
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    18
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    19
defineComparisonOperators
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    20
(
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    21
 "=~"		=> \&XML::XQL::match_oper,
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    22
 "!~"		=> \&XML::XQL::no_match_oper,
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    23
 "match"	=> \&XML::XQL::match_oper,
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    24
 "no_match"	=> \&XML::XQL::no_match_oper,
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    25
 "isa"		=> \&XML::XQL::isa_oper,
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    26
 "can"		=> \&XML::XQL::can_oper,
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    27
);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    28
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    29
sub match_oper
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    30
{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    31
    my ($node, $expr) = @_;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    32
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    33
    return [] if isEmptyList ($node);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    34
#?? can this happen?
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    35
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    36
    my $str = $node->xql_toString;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    37
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    38
    $expr = prepareRvalue ($expr->solve ([$node]));
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    39
    return [] if isEmptyList ($expr);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    40
#?? can this happen?
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    41
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    42
    $expr = $expr->xql_toString;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    43
    croak "bad search pattern '$expr' for =~" unless $expr =~ m!^\s*[m/]!o;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    44
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    45
    my $res = eval "\$str =~ $expr";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    46
    croak "bad search pattern '$expr' for =~ operator: $@"  if ($@);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    47
    $res;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    48
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    49
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    50
sub no_match_oper
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    51
{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    52
    my ($node, $expr) = @_;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    53
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    54
    return [] if isEmptyList ($node);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    55
#?? can this happen?
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    56
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    57
    my $str = $node->xql_toString;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    58
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    59
    $expr = prepareRvalue ($expr->solve ([$node]));
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    60
    return [] if isEmptyList ($expr);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    61
#?? can this happen?
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    62
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    63
    $expr = $expr->xql_toString;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    64
    croak "bad search pattern '$expr' for !~" unless $expr =~ m!^\s*[m/]!o;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    65
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    66
    my $res = eval "\$str !~ $expr";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    67
    croak "bad search pattern '$expr' for !~ operator: $@"  if ($@);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    68
    $res;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    69
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    70
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    71
sub isa_oper
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    72
{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    73
    my ($node, $expr) = @_;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    74
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    75
    return [] if isEmptyList ($node);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    76
#?? can this happen?
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    77
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    78
    $expr = prepareRvalue ($expr->solve ([$node]));
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    79
    return [] if isEmptyList ($expr);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    80
#?? can this happen?
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    81
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    82
    $expr = $expr->xql_toString;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    83
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    84
    # Expand "number" to "XML::XQL::Number" etc.
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    85
    $expr = expandType ($expr);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    86
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    87
#?? I don't think empty lists are possible here. If so, add "[]" as expr
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    88
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    89
    ref($node) and $node->isa ($expr);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    90
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    91
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    92
#
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    93
# Not sure how useful this is, unless it supports XQL functions/methods...
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    94
#
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    95
sub can_oper
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    96
{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    97
    my ($node, $expr) = @_;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    98
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
    99
    return [] if isEmptyList ($node);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   100
#?? can this happen?
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   101
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   102
    $expr = prepareRvalue ($expr->solve ([$node]));
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   103
    return [] if isEmptyList ($expr);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   104
#?? can this happen?
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   105
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   106
    $expr = $expr->xql_toString;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   107
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   108
    ref ($node) and $node->can ($expr);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   109
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   110
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   111
sub once
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   112
{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   113
    my ($context, $list, $expr) = @_;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   114
    $expr->solve ($context, $list);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   115
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   116
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   117
sub xql_eval
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   118
{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   119
    my ($context, $list, $query, $type) = @_;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   120
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   121
#   return [] if @$list == 0;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   122
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   123
    $query = toList ($query->solve ($context, $list));
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   124
    return [] unless @$query;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   125
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   126
    if (defined $type)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   127
    {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   128
	$type = prepareRvalue ($type->solve ($context, $list));
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   129
	$type = isEmptyList ($type) ? "Text" : $type->xql_toString;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   130
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   131
	# Expand "number" to "XML::XQL::Number" etc.
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   132
	$type = expandType ($type);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   133
    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   134
    else
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   135
    {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   136
	$type = "XML::XQL::Text";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   137
    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   138
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   139
    my @result = ();
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   140
    for my $val (@$query)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   141
    {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   142
	$val = $val->xql_toString;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   143
	$val = eval $val;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   144
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   145
#print "eval result=$val\n";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   146
#?? check result?
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   147
	push @result, eval "new $type (\$val)" if defined $val;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   148
    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   149
    \@result;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   150
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   151
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   152
sub subst
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   153
{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   154
    my ($context, $list, $query, $expr, $repl, $mod, $mode) = @_;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   155
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   156
#?? not sure?
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   157
    return [] if @$list == 0;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   158
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   159
    $expr = prepareRvalue ($expr->solve ($context, $list));
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   160
    return [] if isEmptyList ($expr);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   161
    $expr = $expr->xql_toString;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   162
    
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   163
    $repl = prepareRvalue ($repl->solve ($context, $list));
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   164
    return [] if isEmptyList ($repl);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   165
    $repl = $repl->xql_toString;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   166
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   167
    if (defined $mod)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   168
    {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   169
	$mod = prepareRvalue ($mod->solve ($context, $list));
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   170
	$mod = isEmptyList ($mod) ? "" : $mod->xql_toString;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   171
    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   172
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   173
    if (defined $mode)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   174
    {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   175
	$mode = prepareRvalue ($mode->solve ($context, $list));
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   176
	$mode = isEmptyList ($mode) ? 0 : $mode->xql_toString;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   177
    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   178
    else
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   179
    {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   180
	$mode = 0;	# default mode: use textBlocks for Elements
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   181
    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   182
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   183
    my @result = ();
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   184
    my $nodes = toList ($query->solve ($context, $list));
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   185
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   186
    for my $node (@$nodes)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   187
    {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   188
	if ($mode == 0 && $node->xql_nodeType == 1)	# 1: Element node
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   189
	{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   190
	    # For Element nodes, replace text in consecutive text blocks
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   191
	    # Note that xql_rawtextBlocks, returns the blocks in reverse order,
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   192
	    # so that the indices of nodes within previous blocks don't need
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   193
	    # to be adjusted when a replacement occurs.
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   194
	    my $block_matched = 0;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   195
	    BLOCK: for my $block ($node->xql_rawTextBlocks)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   196
	    {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   197
		my $str = $block->[2];
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   198
		my $result = eval "\$str =~ s/\$expr/\$repl/$mod";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   199
		croak "bad subst expression s/$expr/$repl/$mod: $@" if ($@);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   200
		next BLOCK unless $result;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   201
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   202
		$block_matched++;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   203
		$node->xql_replaceBlockWithText ($block->[0], $block->[1], $str);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   204
	    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   205
	    # Return the input parameter only if a substitution occurred
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   206
	    push @result, $node if $block_matched;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   207
	}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   208
	else
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   209
	{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   210
	    my $str = $node->xql_toString;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   211
	    next unless defined $str;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   212
	    
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   213
	    my $result = eval "\$str =~ s/\$expr/\$repl/$mod";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   214
	    croak "bad subst expression s/$expr/$repl/$mod: $@" if ($@);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   215
	    next unless $result;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   216
#print "result=$result for str[$str] =~ s/$expr/$repl/$mod\n";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   217
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   218
	    # Return the input parameter only if a substitution occurred
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   219
	    $node->xql_setValue ($str);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   220
	    push @result, $node;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   221
	}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   222
	# xql_setValue will actually change the value of the node for an Attr,
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   223
	# Text, CDataSection, EntityRef or Element
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   224
    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   225
    \@result;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   226
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   227
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   228
#?? redo match - what should it return?
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   229
sub match
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   230
{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   231
    my ($context, $list, $query, $repl, $mod) = @_;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   232
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   233
    return [] if @$list == 0;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   234
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   235
    $query = prepareRvalue ($query->solve ($context, $list));
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   236
    return [] if isEmptyList ($query);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   237
    $query = $query->xql_toString;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   238
    
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   239
    if (defined $mod)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   240
    {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   241
	$mod = prepareRvalue ($mod->solve ($context, $list));
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   242
	$mod = isEmptyList ($mod) ? "" : $mod->xql_toString;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   243
    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   244
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   245
    my $str = $list->[0]->xql_toString;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   246
    return [] unless defined $str;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   247
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   248
    my (@matches) = ();
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   249
    eval "\@matches = (\$str =~ /\$query/$mod)";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   250
    croak "bad match expression m/$query/$mod" if ($@);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   251
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   252
#?? or should I map undef to XML::XQL::Text("") ?
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   253
    @matches = map { defined($_) ? new XML::XQL::Text ($_) : [] } @matches;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   254
    \@matches;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   255
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   256
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   257
sub xql_map
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   258
{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   259
    my ($context, $list, $query, $code) = @_;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   260
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   261
#?? not sure?
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   262
    return [] if @$list == 0;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   263
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   264
    $code = prepareRvalue ($code->solve ($context, $list));
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   265
    return [] if isEmptyList ($code);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   266
    $code = $code->xql_toString;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   267
    
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   268
    my @result = ();
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   269
    my $nodes = toList ($query->solve ($context, $list));
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   270
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   271
    for my $node (@$nodes)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   272
    {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   273
	my $str = $node->xql_toString;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   274
	next unless defined $str;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   275
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   276
	my (@mapresult) = ($str);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   277
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   278
#?? NOTE: the $code should
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   279
	eval "\@mapresult = map { $code } (\$str)";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   280
	croak "bad map expression '$code' ($@)" if ($@);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   281
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   282
	# Return the input parameter only if a change occurred
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   283
	next unless $mapresult[0] eq $str;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   284
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   285
	# xql_setValue will actually change the value of the node for an Attr,
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   286
	# Text, CDataSection, EntityRef or Element
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   287
	$node->xql_setValue ($str);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   288
	push @result, $node;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   289
    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   290
    \@result;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   291
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   292
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   293
sub xql_new
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   294
{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   295
    my ($type, @arg) = @_;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   296
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   297
    # Expand "number" to "XML::XQL::Number" etc.
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   298
    $type = expandType ($type);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   299
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   300
    my $obj = eval "new $type (\@arg)";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   301
    $@ ? [] : $obj;	# return empty list on exception
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   302
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   303
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   304
my $DOM_PARSER;	# used by xql_document (below)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   305
sub setDocParser
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   306
{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   307
    $DOM_PARSER = shift;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   308
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   309
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   310
sub xql_document
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   311
{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   312
    my ($docname) = @_;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   313
    my $parser = $DOM_PARSER ||= new XML::DOM::Parser;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   314
    my $doc;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   315
    eval
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   316
    {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   317
	$doc = $parser->parsefile ($docname);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   318
    };
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   319
    if ($@)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   320
    {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   321
	warn "xql_document: could not read XML file [$docname]: $@";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   322
    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   323
    return defined $doc ? $doc : [];
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   324
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   325
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   326
#----------- XQL+ methods --------------------------------------------
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   327
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   328
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   329
sub DOM_nodeType
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   330
{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   331
    my ($context, $list) = @_;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   332
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   333
    return [] if @$list == 0;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   334
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   335
    new XML::XQL::Number ($list->[0]->xql_DOM_nodeType, $list->[0]);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   336
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   337
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   338
#----------- Perl Builtin Functions ----------------------------------
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   339
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   340
# Note that certain functions (like mkdir) are not considered "constant"
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   341
# because we don't want their invocation values cached. (We want the
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   342
# function to be called every time the Invocation is solved/evaluated.)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   343
my %PerlFunc =
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   344
(
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   345
 # Format: 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   346
 #  "funcName", => [ARGCOUNT, RETURN_TYPE [, CONSTANT = 0, [QUERY_ARG = 0]]]
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   347
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   348
 #-------- Arithmetic Functions
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   349
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   350
 "abs" => [1, "Number", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   351
 "atan2" => [2, "Number", 1, -1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   352
 "cos" => [1, "Number", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   353
 "exp" => [1, "Number", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   354
 "int" => [1, "Number", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   355
 "log" => [1, "Number", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   356
 "rand" => [[0, 1], "Number", 0, -1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   357
 "sin" => [1, "Number", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   358
 "sqrt" => [1, "Number", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   359
 "srand" => [[0, 1], "Number", 0, -1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   360
 "time" => [0, "Number", 0, -1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   361
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   362
 #-------- Conversion Functions
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   363
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   364
 "chr" => [1, "Text", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   365
# "gmtime" => [1, "List of Number", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   366
 "hex" => [1, "Number", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   367
# "localtime" => [1, "List of Number", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   368
 "oct" => [1, "Number", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   369
 "ord" => [1, "Text", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   370
 "vec" => [3, "Number", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   371
 "pack" => [[1, -1], "Text", 1, -1], #?? how should this work??
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   372
# "unpack" => [2, "List of ?", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   373
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   374
 #-------- String Functions
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   375
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   376
 "chomp" => [1, "Text", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   377
 "chop" => [1, "Text", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   378
 "crypt" => [2, "Text", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   379
 "lindex" => [[2, 3], "Number", 1],	# "index" is already taken by XQL
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   380
 "length" => [1, "Number", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   381
 "lc" => [1, "Text", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   382
 "lcfirst" => [1, "Text", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   383
 "quotemeta" => [1, "Text", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   384
 "rindex" => [[2, 3], "Number", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   385
 "substr" => [[2, 3], "Text", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   386
 "uc" => [1, "Text", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   387
 "ucfirst" => [1, "Text", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   388
 "reverse" => [1, "Text", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   389
 "sprintf" => [[1, -1], "Text", 1, -1],
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   390
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   391
 #-------- Array Functions
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   392
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   393
 "join" => [[1, -1], "Text", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   394
# "split" => [[2, 3], "List of Text", 1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   395
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   396
 #-------- File Functions
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   397
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   398
 "chmod" => [2, "Boolean", 0, 1],
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   399
 "chown" => [3, "Boolean", 0, 2],
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   400
 "link" => [2, "Number", 0, -1],		#?? no return value
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   401
# "lstat" => [1, "List of Number"], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   402
 "mkdir" => [2, "Boolean"],		#?? or is 1 arg also allowed?
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   403
 "readlink" => [1, "Text"], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   404
 "rename" => [2, "Boolean", 0, -1],
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   405
 "rmdir" => [1, "Boolean"],
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   406
# "stat" => [1, "List of Number"], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   407
 "symlink" => [2, "Boolean", 0, -1],
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   408
 "unlink" => [1, "Boolean"],
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   409
 "utime" => [3, "Boolean", 0, 2],
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   410
 "truncate" => [2, "Number"],		#?? no return value
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   411
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   412
 #-------- System Interaction
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   413
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   414
 "exit" => [[0, 1], "Number"], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   415
# "glob" => [1, "List of Text"], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   416
 "system" => [[1, -1], "Number", 0, -1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   417
# "times" => [0, "List of Number"],
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   418
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   419
 #-------- Miscellaneous
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   420
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   421
 "defined" => [1, "Boolean"],	# is this useful??
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   422
 "dump" => [[0, 1], "Number", 0, -1], 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   423
 "ref" => [1, "Text"],
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   424
);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   425
#?? die, warn, croak (etc.), 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   426
#?? file test (-X), tr// (same as y//)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   427
#?? array functions, sort
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   428
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   429
# Generate wrapper for Perl builtin function on the fly
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   430
sub generatePerlWrapper
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   431
{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   432
    my ($name) = @_;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   433
    my $args = $PerlFunc{$name};
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   434
    return undef unless defined $args;	# not found
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   435
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   436
    my ($argCount, $returnType, $const, $queryArg) = @$args;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   437
    my $funcName = $name;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   438
    if ($name eq "lindex")	# "index" is already taken
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   439
    {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   440
	$funcName = "index";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   441
    }    
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   442
    generateFunction ($name, $funcName, $returnType, $argCount, 0, $const, 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   443
		      $queryArg);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   444
    $Func{$name};
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   445
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   446
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   447
#?? Inline functions, do they make sense? E.g. 'elem!sub("code", "arg1")'
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   448
#?? Normally, user should use defineFunction, but if most of them have
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   449
#?? a lot of common code, I could provide the pre- and post-code.
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   450
#?? After processing the user-supplied code block, how should I convert the
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   451
#?? user's result back to an Invocation result. E.g. do I get a single value
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   452
#?? or a list back?
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   453
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   454
defineFunction ("eval",  \&XML::XQL::xql_eval,		[1, 2]);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   455
defineFunction ("subst", \&XML::XQL::subst,		[3, 5], 1);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   456
defineFunction ("s",	 \&XML::XQL::subst,		[3, 5], 1);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   457
defineFunction ("match", \&XML::XQL::match,		[1, 2]);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   458
defineFunction ("m",     \&XML::XQL::match,		[1, 2]);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   459
defineFunction ("map",   \&XML::XQL::xql_map,		2,      1);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   460
defineFunction ("once",  \&XML::XQL::once,		1,      1);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   461
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   462
defineMethod ("DOM_nodeType", \&XML::XQL::DOM_nodeType, 0, 0);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   463
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   464
generateFunction ("new", "XML::XQL::xql_new", "*", [1, -1], 1, 0, 1);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   465
generateFunction ("document", "XML::XQL::xql_document", "*", 1, 1, 0, 0);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   466
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   467
# doc() is an alias for document() 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   468
defineFunction ("doc", \&XML::XQL::xql_wrap_document, 1, 1);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   469
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   470
#------------------------------------------------------------------------------
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   471
# The following functions were found in the XPath spec.
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   472
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   473
# Found in XPath but not (yet) implemented in XML::XQL:
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   474
# - type casting (string, number, boolean) - Not sure if needed...
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   475
#   Note that string() converts booleans to 'true' and 'false', but our
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   476
#   internal type casting converts it to perl values '0' and '1'...
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   477
# - math (+,-,*,mod,div) - Use eval() for now
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   478
# - last(), position() - Similar to end() and index() except they're 1-based
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   479
# - local-name(node-set?), namespace-uri(node-set?)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   480
# - name(node-set?) - Can we pass a node-set in XQL?
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   481
# - lang(string)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   482
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   483
sub xpath_concat	{ join ("", @_) }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   484
sub xpath_starts_with	{ $_[0] =~ /^\Q$_[1]\E/ }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   485
# ends-with is not part of XPath
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   486
sub xpath_ends_with	{ $_[0] =~ /\Q$_[1]\E$/ }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   487
sub xpath_contains	{ $_[0] =~ /\Q$_[1]\E/ }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   488
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   489
# The following methods don't know about NaN, +/-Infinity or -0.
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   490
sub xpath_floor		{ use POSIX; POSIX::floor ($_[0]) }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   491
sub xpath_ceiling	{ use POSIX; POSIX::ceil ($_[0]) }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   492
sub xpath_round  	{ use POSIX; POSIX::floor ($_[0] + 0.5) }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   493
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   494
# Note that the start-index is 1-based in XPath
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   495
sub xpath_substring	
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   496
{ 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   497
    defined $_[2] ? substr ($_[0], $_[1] - 1, $_[2]) 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   498
		  : substr ($_[0], $_[1] - 1) 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   499
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   500
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   501
sub xpath_substring_before	
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   502
{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   503
    my $i = index ($_[0], $_[1]); 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   504
    $i == -1 ? undef : substr ($_[0], 0, $i) 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   505
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   506
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   507
sub xpath_substring_after	
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   508
{ 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   509
    my $i = index ($_[0], $_[1]);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   510
    $i == -1 ? undef : substr ($_[0], $i + length($_[1])) 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   511
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   512
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   513
# Note that d,c,s are tr/// modifiers. Also can't use open delimiters i.e. {[(<
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   514
my @TR_DELIMITERS = split //, "/!%^&*)-_=+|~]}'\";:,.>/?abefghijklmnopqrtuvwxyz";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   515
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   516
sub xpath_translate
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   517
{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   518
    my ($str, $from, $to) = @_;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   519
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   520
    my $delim;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   521
    for my $d (@TR_DELIMITERS)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   522
    {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   523
	if (index ($from, $d) == -1 && index ($to, $d) == -1)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   524
	{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   525
	    $delim = $d;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   526
	    last;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   527
	}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   528
    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   529
    die "(xpath_)translate: can't find suitable 'tr' delimiter" 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   530
	unless defined $delim;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   531
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   532
    # XPath defines that if length($from) > length($to), characters in $from
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   533
    # for which there is no match in $to, should be deleted.
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   534
    # (So we must use the 's' modifier.)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   535
    eval "\$str =~ tr$delim$from$delim$to${delim}d";
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   536
    $str;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   537
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   538
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   539
sub xpath_string_length
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   540
{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   541
    my ($context, $list, $text) = @_;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   542
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   543
    if (defined $text)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   544
    {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   545
	$text = XML::XQL::prepareRvalue ($text->solve ($context, $list));
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   546
	return [] unless defined $text;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   547
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   548
	return new XML::XQL::Number (length $text->xql_toString, 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   549
				     $text->xql_sourceNode);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   550
    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   551
    else
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   552
    {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   553
	return [] if @$list == 0;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   554
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   555
	my @result;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   556
	for my $node (@$list)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   557
	{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   558
	    push @result, new XML::XQL::Number (length $node->xql_toString, 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   559
						$node);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   560
	}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   561
	return \@result;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   562
    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   563
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   564
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   565
sub _normalize
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   566
{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   567
    $_[0] =~ s/\s+/ /g;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   568
    $_[0] =~ s/^\s+//;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   569
    $_[0] =~ s/\s+$//;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   570
    $_[0];
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   571
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   572
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   573
sub xpath_normalize_space
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   574
{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   575
    my ($context, $list, $text) = @_;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   576
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   577
    return [] if @$list == 0;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   578
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   579
    if (defined $text)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   580
    {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   581
	$text = XML::XQL::prepareRvalue ($text->solve ($context, $list));
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   582
	return [] unless defined $text;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   583
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   584
	return new XML::XQL::Text (_normalize ($text->xql_toString), 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   585
				   $text->xql_sourceNode);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   586
    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   587
    else
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   588
    {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   589
	my @result;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   590
	for my $node (@$list)
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   591
	{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   592
	    push @result, new XML::XQL::Text (_normalize ($node->xql_toString), 
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   593
					      $node);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   594
	}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   595
	return \@result;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   596
    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   597
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   598
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   599
sub xpath_sum
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   600
{
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   601
    my ($context, $list, $expr) = @_;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   602
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   603
    return [] if @$list == 0;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   604
#?? or return Number(0) ?
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   605
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   606
    my $sum = 0;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   607
    $expr = XML::XQL::toList ($expr->solve ($context, $list));
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   608
    for my $r (@{ $expr })
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   609
    {
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   610
	$sum += $r->xql_toString;
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   611
    }
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   612
    return new XML::XQL::Number ($sum, undef);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   613
}
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   614
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   615
generateFunction ("round", "XML::XQL::xpath_round", "Number", 1, 1);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   616
generateFunction ("floor", "XML::XQL::xpath_floor", "Number", 1, 1);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   617
generateFunction ("ceiling", "XML::XQL::xpath_ceiling", "Number", 1, 1);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   618
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   619
generateFunction ("concat", "XML::XQL::xpath_concat", "Text", [2, -1], 1);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   620
generateFunction ("starts-with", "XML::XQL::xpath_starts_with", "Boolean", 2, 1);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   621
generateFunction ("ends-with", "XML::XQL::xpath_ends_with", "Boolean", 2, 1);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   622
generateFunction ("contains", "XML::XQL::xpath_contains", "Boolean", 2, 1);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   623
generateFunction ("substring-before", "XML::XQL::xpath_substring_before", "Text", 2, 1);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   624
generateFunction ("substring-after", "XML::XQL::xpath_substring_after", "Text", 2, 1);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   625
# Same as Perl substr() except index is 1-based
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   626
generateFunction ("substring", "XML::XQL::xpath_substring", "Text", [2, 3], 1);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   627
generateFunction ("translate", "XML::XQL::xpath_translate", "Text", 3, 1);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   628
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   629
defineMethod ("string-length", \&XML::XQL::xpath_string_length, [0, 1], 1);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   630
defineMethod ("normalize-space", \&XML::XQL::xpath_normalize_space, [0, 1], 1);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   631
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   632
defineFunction ("sum", \&XML::XQL::xpath_sum, 1, 1);
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   633
3f65fd25dfd4 sync up SVN codes
kelvzhu
parents:
diff changeset
   634
1;	# module return code