# Quest, a computer role playing game system # Copyright (C) 2002 Willem Robert van Hage, details in the COPYING file. package tree; use strict; use Data::Dumper; $Data::Dumper::Indent = 1; sub find_all { my ($href,$key) = @_; my @rv; return if ref($href) ne "HASH"; foreach (keys %{$href}) { push @rv, $href->{$_} if $_ eq $key; my @children = find_all($href->{$_},$key); push @rv, @children; } return @rv } sub xpath_token { $_ = shift; return ($1,$2) if /^(\/\/)(.*)/; # // return ($1,$2) if /^(\/)(.*)/; # / return ($1,$2) if /^(\*)(.*)/; # * return ($1,$2) if /^(\w+)(.*)/; # word return } sub query { my ($context,$xpath) = @_; return $context unless $xpath; my ($h,$t) = xpath_token($xpath); if ($h eq "/") { return query($context,$t) } elsif ($h eq "//") { my ($th,$tt) = xpath_token($t); my @match = find_all($context,$th); foreach (@match) { my $rv = query($_,$tt); return $rv if $rv } } elsif ($h eq "*") { return unless ref($context) eq "HASH"; foreach (keys %{$context}) { my $rv = query($context->{$_},$t); return $rv if $rv } } elsif ($h =~ /\w+/) { return unless ref($context) eq "HASH" and $context->{$h}; return query($context->{$h},$t) } return } 1;