diff options
-rw-r--r-- | Changes | 1 | ||||
-rw-r--r-- | lib/PPIx/XPath.pm | 59 |
2 files changed, 55 insertions, 5 deletions
@@ -1,3 +1,4 @@ {{$NEXT}} - fixed example code as per RT#116737, thanks Alastair Cooke + - more documentation - switched to Dist::Zilla diff --git a/lib/PPIx/XPath.pm b/lib/PPIx/XPath.pm index 4853fe6..a4e7609 100644 --- a/lib/PPIx/XPath.pm +++ b/lib/PPIx/XPath.pm @@ -57,6 +57,15 @@ initial C<PPI::>, with C<::> replaced by C<->. That is: =end :list +=method C<new> + + my $pxp = PPIx::XPath->new("some_code.pl"); + + my $pxp = PPIx::XPath->new($pdom); + +Only useful for the backward-compatible, and deprecated, interface. +Returns an instance of C<PPIx::XPath> tied to the given document. + =cut sub new { @@ -80,9 +89,22 @@ sub new { return bless {doc=>$doc},$class; } -# PPIx::XPath 1.0.0 allowed the use of partial package names as node names; -# this collides with the axis specification of proper XPath. -# Here we change the "old-style" node names into the new names +=method C<clean_xpath_expr> + + my $new_xpath_expr = $pxp->clean_xpath_expr($old_xpath_expr); + +C<PPIx::XPath> version 1.0.0 allowed the use of partial package names +(like C<Token::Number>) as element names: this collides with the axis +specification of proper XPath. For this reason, in newer version of +C<PPIx::XPath>, the element name is the class name of the PDOM node, +minus the initial C<PPI::>, with C<::> replaced by C<-> (like +C<Token-Number>). + +This method replaces all occurrences of PPI package names in the given +string with the new names. + +=cut + { my $legacy_names_rx;my %new_name_for; sub clean_xpath_expr { @@ -95,6 +117,7 @@ sub new { my @PPI_Packs; # taken from Devel::Symdump + # breadth-first search of packages under C<PPI> my @packages=('PPI'); while (my $pack=shift(@packages)) { my %pack_symbols = do { @@ -102,15 +125,20 @@ sub new { %{*{"$pack\::"}} }; while (my ($key,$val)=each(%pack_symbols)) { + # that {HASH} lookup is special for typeglobs, so we have + # to alias a local typeglob to make it work local *ENTRY=$val; + # does this symbol table entry look like a sub-package? if (defined $val && defined *ENTRY{HASH} && $key=~/::$/ && $key !~ /^::/ && $key ne 'main::' && $key ne '<none>::') { + # add it to the search list my $p = "$pack\::$key";$p =~ s{::$}{}; push @packages,$p; - $p =~ s{^PPI::}{}; + # and add it to the map of names + $p =~ s{^PPI::}{}; next unless $p=~/::/; my $newname=$p; @@ -120,12 +148,34 @@ sub new { } } } + + # @PPI_Packs now contains all the old-style names, build a regex + # to match them (the sort is important, we want to match longer + # names first!) $legacy_names_rx='\b('.join(q{|}, sort {length($b) <=> length($a)} @PPI_Packs ).')\b'; $legacy_names_rx=qr{$legacy_names_rx}; } +=method C<match> + + my @subs = $pxp->match("//Statement::Sub"); + my $vars = $pxp->match("//Token::Symbol"); + +Only useful for the backward-compatible, and deprecated, +interface. From the document this instance was built against, returns +the nodes that match the given XPath expression. + +You should not use this method, you should call L<< +C<findnodes>|Tree::XPathEngine/findnodes >> instead: + + my $xpath = Tree::XPathEngine->new(); + my @subs = $xpath->findnodes('//Statement-Sub',$pdom); + my @vars = $xpath->findnodes('//Token-Symbol',$pdom); + +=cut + sub match { my ($self,$expr) = @_; @@ -134,7 +184,6 @@ sub match { Tree::XPathEngine->new()->findnodes($expr,$self->{doc}); } - =head1 BUGS and LIMITATIONS =for :list |