From eea4328b66e5d9e45f6ecf0f3a4cb66d5d1a382b Mon Sep 17 00:00:00 2001 From: mirod Date: Tue, 20 Sep 2011 03:32:02 +0200 Subject: [PATCH] more cleanup --- HTML-TreeBuilder-XPath-0.10.tar.gz | Bin 10034 -> 0 bytes HTML-TreeBuilder-XPath-0.11.tar.gz | Bin 10125 -> 0 bytes HTML-TreeBuilder-XPath-0.12.tar.gz | Bin 10277 -> 0 bytes HTML-TreeBuilder-XPath-0.13.tar.gz | Bin 10367 -> 0 bytes HTML-TreeBuilder-XPath-0.14.tar.gz | Bin 10689 -> 0 bytes HTML-TreeBuilder-XPath-root.patch | 47 --- Makefile.PL~ | 12 - XPath_with_as_XML_clean.pm | 546 ------------------------------- cover_report.txt | 0 index.html | 70 ---- index.html~ | 70 ---- lib/HTML/TreeBuilder/XPath.pm.orig | 636 ------------------------------------- test_as_XML | 41 --- test_guess_charset | 21 -- ~/.perldb.hist | 16 - 15 files changed, 1459 deletions(-) delete mode 100644 HTML-TreeBuilder-XPath-0.10.tar.gz delete mode 100644 HTML-TreeBuilder-XPath-0.11.tar.gz delete mode 100644 HTML-TreeBuilder-XPath-0.12.tar.gz delete mode 100644 HTML-TreeBuilder-XPath-0.13.tar.gz delete mode 100644 HTML-TreeBuilder-XPath-0.14.tar.gz delete mode 100644 HTML-TreeBuilder-XPath-root.patch delete mode 100644 Makefile.PL~ delete mode 100644 XPath_with_as_XML_clean.pm delete mode 100644 cover_report.txt delete mode 100644 index.html delete mode 100644 index.html~ delete mode 100644 lib/HTML/TreeBuilder/XPath.pm.orig delete mode 100644 test_as_XML delete mode 100644 test_guess_charset delete mode 100644 ~/.perldb.hist diff --git a/HTML-TreeBuilder-XPath-0.10.tar.gz b/HTML-TreeBuilder-XPath-0.10.tar.gz deleted file mode 100644 index c6ca6f17924018635d16af2abc4bda4efaf636ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 10034 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 IEC9#=0N?GwcmMzZ diff --git a/HTML-TreeBuilder-XPath-0.11.tar.gz b/HTML-TreeBuilder-XPath-0.11.tar.gz deleted file mode 100644 index cda6bfede5dd511643fa62fdf9103b152e485c8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 10125 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 diff --git a/HTML-TreeBuilder-XPath-0.13.tar.gz b/HTML-TreeBuilder-XPath-0.13.tar.gz deleted file mode 100644 index ac05ca08571f96ae16c5945ebdd02e144f3f305e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 10367 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 diff --git a/HTML-TreeBuilder-XPath-root.patch b/HTML-TreeBuilder-XPath-root.patch deleted file mode 100644 index c3e73c0..0000000 --- a/HTML-TreeBuilder-XPath-root.patch +++ /dev/null @@ -1,47 +0,0 @@ -diff --git a/lib/HTML/TreeBuilder/XPath.pm b/lib/HTML/TreeBuilder/XPath.pm -index 9f15450..3d0feaf 100644 ---- a/lib/HTML/TreeBuilder/XPath.pm -+++ b/lib/HTML/TreeBuilder/XPath.pm -@@ -336,6 +336,10 @@ sub getParentNode { return (); } - sub getChildNodes { my @content= ( $_[0]->{_root}); return wantarray ? @content : \@content; } - sub getAttributes { return [] } - sub isDocumentNode { return 1 } -+sub getRootNode { return $_[0] } -+sub getName { return } -+sub getNextSibling { return } -+sub getPreviousSibling { return } - - # added to provide element-like methods to root, for use by cmp - sub lineage { return ($_[0]); } -diff --git a/t/HTML-TreeBuilder-XPath.t b/t/HTML-TreeBuilder-XPath.t -index 33e818c..d1e91f1 100644 ---- a/t/HTML-TreeBuilder-XPath.t -+++ b/t/HTML-TreeBuilder-XPath.t -@@ -3,7 +3,7 @@ - - ######################### - --use Test::More tests => 19; -+use Test::More tests => 25; - BEGIN { use_ok('HTML::TreeBuilder::XPath') }; - - ######################### -@@ -55,6 +55,18 @@ is( $html->findvalue('id("foo")'), 'spans', 'id function'); - is( $html->findvalue('id("foo")/@id'), 'foo', 'id function (attribute)'); - } - -+{ -+# test for root -+my ($fake_root)=$html->findnodes('/'); -+ok( !$fake_root->getParentNode => "fake root does not have a parent"); -+is( $fake_root->getRootNode, $fake_root, "fake root is its own root"); -+ok( !@{$fake_root->getAttributes} => "fake root has no attributes"); -+ok( !defined($fake_root->getName) => "fake root does not have a name"); -+ok( !defined($fake_root->getNextSibling) => "fake root does not have a next sibling"); -+ok( !defined($fake_root->getPreviousSibling) => "fake root does not have a prev sibling"); -+ -+} -+ - __END__ - /html/body/h1 1 Example header - //@id[.="toto"] 2 toto diff --git a/Makefile.PL~ b/Makefile.PL~ deleted file mode 100644 index c4b0af1..0000000 --- a/Makefile.PL~ +++ /dev/null @@ -1,12 +0,0 @@ -use 5.006; -use ExtUtils::MakeMaker; -# See lib/ExtUtils/MakeMaker.pm for details of how to influence -# the contents of the Makefile that is written. -WriteMakefile( - NAME => 'HTML::TreeBuilder::XPath', - VERSION_FROM => 'lib/HTML/TreeBuilder/XPath.pm', # finds $VERSION - PREREQ_PM => { XML::XPathEngine => 0.03, HTML::TreeBuilder => 0, }, # e.g., Module::Name => 1.1 - ($] >= 5.005 ? ## Add these new keywords supported since 5.005 - (ABSTRACT_FROM => 'lib/HTML/TreeBuilder/XPath.pm', # retrieve abstract from module - AUTHOR => 'Michel Rodriguez ') : ()), -); diff --git a/XPath_with_as_XML_clean.pm b/XPath_with_as_XML_clean.pm deleted file mode 100644 index 27b387d..0000000 --- a/XPath_with_as_XML_clean.pm +++ /dev/null @@ -1,546 +0,0 @@ -package HTML::TreeBuilder::XPath; - - -use strict; -use warnings; - -use vars qw($VERSION); - -$VERSION = '0.10'; - -my %CHAR2DEFAULT_ENT= ( '&' => '&', '<' => '<', '>' => '>', '"' => '"e;'); -my %NUM2DEFAULT_ENT= ( '38' => 'amp', '60' => 'lt', '62' => 'gt', '"' => '"e;'); - -package HTML::TreeBuilder::XPath; - -use base( 'HTML::TreeBuilder'); - - -package HTML::TreeBuilder::XPath::Node; - -sub isElementNode { 0 } -sub isAttributeNode { 0 } -sub isNamespaceNode { 0 } -sub isTextNode { 0 } -sub isProcessingInstructionNode { 0 } -sub isPINode { 0 } -sub isCommentNode { 0 } - -sub getChildNodes { return wantarray ? () : []; } -sub getFirstChild { return undef; } -sub getLastChild { return undef; } - -sub getElementById - { my ($self, $id) = @_; - return scalar $self->look_down( id => $id); - } - -sub to_number { return XML::XPathEngine::Number->new( shift->getValue); } - -sub cmp - { my( $a, $b)=@_; - - # comparison with the root (in $b, or processed in HTML::TreeBuilder::XPath::Root) - if( $b->isa( 'HTML::TreeBuilder::XPath::Root') ) { return -1; } - - # easy cases - return 0 if( $a == $b); - return 1 if( $a->is_inside($b)); # a starts after b - return -1 if( $b->is_inside($a)); # a starts before b - - # lineage does not include the element itself - my @a_pile= ($a, $a->lineage); - my @b_pile= ($b, $b->lineage); - - # the 2 elements are not in the same twig - unless( $a_pile[-1] == $b_pile[-1]) - { warn "2 nodes not in the same pile: ", ref( $a), " - ", ref( $b), "\n"; - print "a: ", $a->string_value, "\nb: ", $b->string_value, "\n"; - return undef; - } - - # find the first non common ancestors (they are siblings) - my $a_anc= pop @a_pile; - my $b_anc= pop @b_pile; - - while( $a_anc == $b_anc) - { $a_anc= pop @a_pile; - $b_anc= pop @b_pile; - } - - if( defined( $a_anc->{_rank}) && defined( $b_anc->{_rank})) - { return $a_anc->{_rank} <=> $b_anc->{_rank}; } - else - { - # from there move left and right and figure out the order - my( $a_prev, $a_next, $b_prev, $b_next)= ($a_anc, $a_anc, $b_anc, $b_anc); - while() - { $a_prev= $a_prev->getPreviousSibling || return -1; - return 1 if( $a_prev == $b_anc); - $a_next= $a_next->getNextSibling || return 1; - return -1 if( $a_next == $b_anc); - $b_prev= $b_prev->getPreviousSibling || return 1; - return -1 if( $b_prev == $a_next); - $b_next= $b_next->getNextSibling || return -1; - return 1 if( $b_next == $a_prev); - } - } - } - - -# need to modify directly the HTML::Element package, because HTML::TreeBuilder won't let me -# change the class of the nodes it generates -package HTML::Element; -use Scalar::Util qw(weaken); -use vars qw(@ISA); - -push @ISA, 'HTML::TreeBuilder::XPath::Node'; - -use XML::XPathEngine; - -{ my $xp; - sub xp - { $xp ||=XML::XPathEngine->new(); - return $xp; - } -} - -sub findnodes { my( $elt, $path)= @_; return xp->findnodes( $path, $elt); } -sub findnodes_as_string { my( $elt, $path)= @_; return xp->findnodes_as_string( $path, $elt); } -sub findnodes_as_strings { my( $elt, $path)= @_; return xp->findnodes_as_strings( $path, $elt); } -sub findvalue { my( $elt, $path)= @_; return xp->findvalue( $path, $elt); } -sub exists { my( $elt, $path)= @_; return xp->exists( $path, $elt); } -sub find_xpath { my( $elt, $path)= @_; return xp->find( $path, $elt); } -sub matches { my( $elt, $path)= @_; return xp->matches( $elt, $path, $elt); } -sub set_namespace { my $elt= shift; xp->new->set_namespace( @_); } - -sub getRootNode - { my $elt= shift; - # The parent of root is a HTML::TreeBuilder::XPath::Root - # that helps getting the tree to mimic a DOM tree - return $elt->root->getParentNode; # I like this one! - } - -sub getParentNode - { my $elt= shift; - return $elt->{_parent} || bless { _root => $elt }, 'HTML::TreeBuilder::XPath::Root'; - } -sub getName { return shift->tag; } -sub getNextSibling { my( $elt)= @_; - my $parent= $elt->{_parent} || return undef; - return $parent->_child_as_object( scalar $elt->right, ($elt->{_rank} || 0) + 1); - } -sub getPreviousSibling { my( $elt)= @_; - my $parent= $elt->{_parent} || return undef; - return undef unless $elt->{_rank}; - return $parent->_child_as_object( scalar $elt->left, $elt->{_rank} - 1); - } -sub isElementNode { return ref $_[0] && ($_[0]->{_tag}!~ m{^~}) ? 1 : 0; } -sub isCommentNode { return ref $_[0] && ($_[0]->{_tag} eq '~comment') ? 1 : 0; } -sub isProcessingInstructionNode { return ref $_[0] && ($_[0]->{_tag} eq '~pi') ? 1 : 0; } -sub isTextNode { return ref $_[0] ? 0 : 1; } - -sub getValue - { my $elt= shift; - if( $elt->isCommentNode) { return $elt->{_text}; } - return $elt->as_text; - } - -sub getChildNodes - { my $parent= shift; - my $rank=0; - my @children= map { $parent->_child_as_object( $_, $rank++) } $parent->content_list; - return wantarray ? @children : \@children; - } - -sub getFirstChild - { my $parent= shift; - my @content= $parent->content_list; - if( @content) - { return $parent->_child_as_object( $content[0], 0); } - else - { return undef; } - } -sub getLastChild - { my $parent= shift; - my @content= $parent->content_list; - if( @content) - { return $parent->_child_as_object( $content[-1], $#content); } - else - { return undef; } - } - -sub getAttributes - { my $elt= shift; - my %atts= $elt->all_external_attr; - my $rank=0; - my @atts= map { bless( { _name => $_, _value => $atts{$_}, - _elt => $elt, _rank => $rank++, - }, - 'HTML::TreeBuilder::XPath::Attribute' - ) - } sort keys %atts; - return wantarray ? @atts : \@atts; - } - -sub to_number { return XML::XPathEngine::Number->new( $_[0]->as_text); } -sub string_value - { my $elt= shift; - if( $elt->isCommentNode) { return $elt->{_text}; } - return $elt->as_text; - }; - -# called on a parent, with a child as second argument and its rank as third -# returns the child if it is already an element, or -# a new HTML::TreeBuilder::XPath::Text element if it is a plain string -sub _child_as_object - { my( $elt, $elt_or_text, $rank)= @_; - return undef unless( defined $elt_or_text); - if( ! ref $elt_or_text) - { # $elt_or_text is a string, turn it into a TextNode object - $elt_or_text= bless { _content => $elt_or_text, _parent => $elt, }, - 'HTML::TreeBuilder::XPath::TextNode' - ; - } - if( ref $rank) { warn "rank is a ", ref( $rank), " elt_or_text is a ", ref( $elt_or_text); } - $elt_or_text->{_rank}= $rank; # used for sorting; - return $elt_or_text; - } - -sub toString { return shift->as_XML_clean( @_); } - -# produces better looking XML -{ my( $indent, %return_before_endtag); - BEGIN - { $indent= ' '; - %return_before_endtag= map { $_ => 1 } qw(html head body script div table tr form ol ul); - } - - sub as_XML_clean - { my( $node, $indent_level)= @_; - - my $xml= ''; - my $wrapping_nl= "\n"; - - if( !defined( $indent_level)) { $indent_level = 0; $wrapping_nl= ''; } - - my $name = $node->{'_tag'}; - if( $HTML::Tagset::isKnown{lc $name} && !$HTML::Tagset::isPhraseMarkup{lc $name} && $indent_level > 0) - { $xml.= $wrapping_nl . ($indent x $indent_level); } - - if( $name eq '~literal') { $xml= _xml_escape_text( $node->{text}); } - elsif( $name eq '~declaration') { $xml= '{text}) . '>'; } - elsif( $name eq '~pi') { $xml= '{text}) . '?>'; } - elsif( $name eq '~comment') { $xml= '<--' . _xml_escape_comment( $node->{text}) . '-->'; } - elsif( $HTML::Tagset::isCDATA_Parent{lc $name}) - { $xml.= $node->_start_tag; - my $content= $node->{_content} || ''; - if( ref $content eq 'ARRAY' || $content->isa( 'ARRAY')) - { $xml .= _xml_escape_cdata( join( '', @$content)); } - if( $return_before_endtag{lc $name}) { $xml.= "\n" . ($indent x $indent_level); } - } - else - { # start tag - $xml.= $node->_start_tag; - my $child_indent_level= $HTML::Tagset{lc $name} ? $indent_level : $indent_level+1; - foreach my $child ($node->content_list) - { if( ref $child) { $xml .= $child->as_XML_clean( $child_indent_level); } - else { $xml .= _xml_escape_text( $child); } - } - if( $return_before_endtag{lc $name}) { $xml.= "\n" . ($indent x $indent_level); } - } - $xml .="" unless $HTML::Tagset::emptyElement{lc $name}; - if( $indent_level == 0) { $xml .= $wrapping_nl; } - return $xml; - } -} - - -sub _start_tag - { my( $node)= @_; - my $name = $node->{'_tag'}; - my $start_tag.= "<$name"; - foreach my $att (sort keys %$node) - { next if( (!length $att) || ($att=~ m{^_}) || ($att eq '/') ); - $start_tag .= qq{ $att="} . _xml_escape_attribute_value $node->{$att} . qq{"}; - } - $start_tag.= $HTML::Tagset::emptyElement{lc $name} ? " />" : ">"; - return $start_tag; - } - -sub _indent_level - { my( $node)= @_; - my $level= scalar grep { !$HTML::Tagset::isPhraseMarkup{lc $_->{_tag}} } $node->lineage; - return $level; - } - - -sub _xml_escape_attribute_value - { my( $text)= @_; - $text=~ s{([&<>"])}{$CHAR2DEFAULT_ENT{$1}}g; # escape also quote, as it is the attribute separator - return $text; - } - -sub _xml_escape_text - { my( $text)= @_; - $text=~ s{([&<>])}{$CHAR2DEFAULT_ENT{$1}}g; - return $text; - } - -sub _xml_escape_comment - { my( $text)= @_; - $text=~ s{([&<>])}{$CHAR2DEFAULT_ENT{$1}}g; - $text=~ s{--}{--}g; # can't have double --'s in XML comments - return $text; - } - -sub _xml_escape_cdata - { my( $text)= @_; - $text=~ s{^\s*\Q\E\s*$}{}s; - $text=~ s{]]>}{]]>}g; # can't have]]> in CDATA - $text= ""; - return $text; - } - - -package HTML::TreeBuilder::XPath::TextNode; - -use base 'HTML::TreeBuilder::XPath::Node'; - -sub getParentNode { return shift->{_parent}; } -sub getValue { return shift->{_content}; } -sub isTextNode { return 1; } -sub getAttributes { return wantarray ? () : []; } - -# similar to HTML::Element as_XML -sub as_XML - { my( $node, $entities)= @_; - my $content= $node->{_content}; - if( $node->{_parent} && $node->{_parent}->{_tag} eq 'script') - { $content=~ s{(&\w+;)}{HTML::Entities::decode($1)}eg; } - else - { HTML::Element::_xml_escape($content); } - return $content; - } - -sub as_XML_clean - { my( $node, $entities)= @_; - my $content= $node->{_content}; - if( $node->{_parent} && $node->{_parent}->{_tag} eq 'script') - { $content=~ s{(&\w+;)}{HTML::Entities::decode($1)}eg; } - else - { $content= HTML::Element::_xml_escape_text($content); } - return $content; - } - -sub getPreviousSibling - { my $self= shift; - my $rank= $self->{_rank}; - #unless( defined $self->{_rank}) - # { warn "no rank for text node $self->{_content}, parent is $self->{_parent}->{_tag}\n"; } - my $parent= $self->{_parent}; - return $rank ? $parent->_child_as_object( $parent->{_content}->[$rank-1], $rank-1) : undef; - } - -sub getNextSibling - { my $self= shift; - my $rank= $self->{_rank}; - #unless( defined $self->{_rank}) - # { warn "no rank for text node $self->{_content}, parent is $self->{_parent}->{_tag}\n"; } - my $parent= $self->{_parent}; - my $next_sibling= $parent->{_content}->[$rank+1]; - return defined( $next_sibling) ? $parent->_child_as_object( $next_sibling, $rank+1) : undef; - } - -sub getRootNode - { return shift->{_parent}->getRootNode; } - -sub string_value { return shift->{_content}; } - -# added to provide element-like methods to text nodes, for use by cmp -sub lineage - { my( $node)= @_; - my $parent= $node->{_parent}; - return( $parent, $parent->lineage); - } - -sub is_inside - { my( $text, $node)= @_; - return $text->{_parent}->is_inside( $node); - } - -1; - - -package HTML::TreeBuilder::XPath::Attribute; -use base 'HTML::TreeBuilder::XPath::Node'; - -sub getParentNode { return $_[0]->{_elt}; } -sub getValue { return $_[0]->{_value}; } -sub getName { return $_[0]->{_name} ; } -sub getLocalName { (my $name= $_[0]->{_name}) =~ s{^.*:}{}; $name; } -sub string_value { return $_[0]->{_value}; } -sub to_number { return XML::XPathEngine::Number->new( $_[0]->{_value}); } -sub isAttributeNode { 1 } -sub toString { return qq{$_[0]->{_name}="$_[0]->{_value}"}; } - -# awfully inefficient, but hopefully this is called only for weird (read test-case) queries -sub getPreviousSibling - { my $self= shift; - my $rank= $self->{_rank}; - return undef unless $rank; - my %atts= $self->{_elt}->all_external_attr; - my $previous_att_name= (sort keys %atts)[$rank-1]; - return bless( { _name => $previous_att_name, - _value => $atts{$previous_att_name}, - _elt => $self->{_elt}, _rank => $rank-1, - }, 'HTML::TreeBuilder::XPath::Attribute' - ); - } - -sub getNextSibling - { my $self= shift; - my $rank= $self->{_rank}; - my %atts= $self->{_elt}->all_external_attr; - my $next_att_name= (sort keys %atts)[$rank+1] || return undef; - return bless( { _name => $next_att_name, _value => $atts{$next_att_name}, - _elt => $self->{_elt}, _rank => $rank+1, - }, 'HTML::TreeBuilder::XPath::Attribute' - ); - - } - - - -# added to provide element-like methods to attributes, for use by cmp -sub lineage - { my( $att)= @_; - my $elt= $att->{_elt}; - return( $elt, $elt->lineage); - } - -sub is_inside - { my( $att, $node)= @_; - return ($att->{_elt} == $node) || $att->{_elt}->is_inside( $node); - } - -1; - - -package HTML::TreeBuilder::XPath::Root; - -use base 'HTML::TreeBuilder::XPath::Node'; - -sub getParentNode { return (); } -sub getChildNodes { my @content= ( $_[0]->{_root}); return wantarray ? @content : \@content; } -sub getAttributes { return [] } -sub isDocumentNode { return 1 } - -# added to provide element-like methods to root, for use by cmp -sub lineage { return ($_[0]); } -sub is_inside { return 0; } -sub cmp { return $_[1]->isa( ' HTML::TreeBuilder::XPath::Root') ? 0 : 1; } - -1; - -__END__ -=head1 NAME - -HTML::TreeBuilder::XPath - add XPath support to HTML::TreeBuilder - -=head1 SYNOPSIS - - use HTML::TreeBuilder::XPath; - my $tree= HTML::TreeBuilder::XPath->new; - $tree->parse_file( "mypage.html"); - my $nb=$tree->findvalue( '/html/body//p[@class="section_title"]/span[@class="nb"]'); - my $id=$tree->findvalue( '/html/body//p[@class="section_title"]/@id'); - - my $p= $html->findnodes( '//p[@id="toto"]')->[0]; - my $link_texts= $p->findvalue( './a'); # the texts of all a elements in $p - - -=head1 DESCRIPTION - -This module adds typical XPath methods to HTML::TreeBuilder, to make it -easy to query a document. - -=head1 METHODS - -Extra methods added both to the tree object and to each element: - -=head2 findnodes ($path) - -Returns a list of nodes found by C<$path>. -In scalar context returns an C object. - -=head2 findnodes_as_string ($path) - -Returns the text values of the nodes, as one string. - -=head2 findnodes_as_strings ($path) - -Returns a list of the values of the result nodes. - -=head2 findvalue ($path) - -Returns either a C, a C -or a C object. If the path returns a NodeSet, -$nodeset->xpath_to_literal is called automatically for you (and thus a -C is returned). Note that -for each of the objects stringification is overloaded, so you can just -print the value found, or manipulate it in the ways you would a normal -perl value (e.g. using regular expressions). - -=head2 exists ($path) - -Returns true if the given path exists. - -=head2 matches($path) - -Returns true if the element matches the path. - -=head2 find ($path) - -The find function takes an XPath expression (a string) and returns either a -Tree::XPathEngine::NodeSet object containing the nodes it found (or empty if -no nodes matched the path), or one of XML::XPathEngine::Literal (a string), -XML::XPathEngine::Number, or XML::XPathEngine::Boolean. It should always -return something - and you can use ->isa() to find out what it returned. If -you need to check how many nodes it found you should check $nodeset->size. -See L. - -=head2 as_XML_clean ($optional_indent_level) - -HTML::TreeBuilder's C output is not really nice to look at, so -I added a new method, that can be used as a simple replacement for it. -It escapes only the '<', '>' and '&' (plus '"' in attribute values), and -wraps CDATA elements in CDATA sections. - -The C<$optional_indent_level> defaults to the level in the original HTML -document (ie you probably don't have to use it) - -This method is currently in alpha state. Ping me if you want other options added -to it (wrapping?). - -=head1 SEE ALSO - -L - -L - -=head1 AUTHOR - -Michel Rodriguez, Emirod@cpan.orgE - -=head1 COPYRIGHT AND LICENSE - -Copyright (C) 2006 by Michel Rodriguez - -This library is free software; you can redistribute it and/or modify -it under the same terms as Perl itself, either Perl version 5.8.4 or, -at your option, any later version of Perl 5 you may have available. - - -=cut diff --git a/cover_report.txt b/cover_report.txt deleted file mode 100644 index e69de29..0000000 diff --git a/index.html b/index.html deleted file mode 100644 index 73e84fd..0000000 --- a/index.html +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - HTML::TreeBuilder::XPath - - - - -
-

XML, the Perl Way

-
-
- - - -
-

HTML::TreeBuilder::XPath

-

HTML::TreeBuilder::XPath uses XML::XPathEngine to add - XPath to - HTML::TreeBuilder. If you - use HTML::TreeBuilder::XPath instead of HTML::TreeBuilder then you get to use - methods like findnodes, as in my @nodes= $root->findnodes( '<xpath_expression>') - or findvalue with the full power of XPath.. -

-
-
- - - diff --git a/index.html~ b/index.html~ deleted file mode 100644 index 73e84fd..0000000 --- a/index.html~ +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - HTML::TreeBuilder::XPath - - - - -
-

XML, the Perl Way

-
-
- - - -
-

HTML::TreeBuilder::XPath

-

HTML::TreeBuilder::XPath uses XML::XPathEngine to add - XPath to - HTML::TreeBuilder. If you - use HTML::TreeBuilder::XPath instead of HTML::TreeBuilder then you get to use - methods like findnodes, as in my @nodes= $root->findnodes( '<xpath_expression>') - or findvalue with the full power of XPath.. -

-
-
- - - diff --git a/lib/HTML/TreeBuilder/XPath.pm.orig b/lib/HTML/TreeBuilder/XPath.pm.orig deleted file mode 100644 index 6adbdd1..0000000 --- a/lib/HTML/TreeBuilder/XPath.pm.orig +++ /dev/null @@ -1,636 +0,0 @@ -package HTML::TreeBuilder::XPath; - -use List::Util qw( first); - -use strict; -use warnings; - -use vars qw($VERSION); - -$VERSION = '0.10'; - -my %CHAR2DEFAULT_ENT= ( '&' => '&', '<' => '<', '>' => '>', '"' => '"'); -my %NUM2DEFAULT_ENT= ( '38' => 'amp', '60' => 'lt', '62' => 'gt', '"' => '"'); - -package HTML::TreeBuilder::XPath; - -use base( 'HTML::TreeBuilder'); - -package HTML::TreeBuilder::XPath::Node; - -sub isElementNode { 0 } -sub isAttributeNode { 0 } -sub isNamespaceNode { 0 } -sub isTextNode { 0 } -sub isProcessingInstructionNode { 0 } -sub isPINode { 0 } -sub isCommentNode { 0 } - -sub getChildNodes { return wantarray ? () : []; } -sub getFirstChild { return undef; } -sub getLastChild { return undef; } - -# need to do a complete look_down each time, as the id could have been changed -# without any object being involved, hence without a potential cache being -# up to date -sub getElementById - { my ($self, $id) = @_; - return scalar $self->look_down( id => $id); - } - -sub to_number { return XML::XPathEngine::Number->new( shift->getValue); } - -sub cmp - { my( $a, $b)=@_; - - # comparison with the root (in $b, or processed in HTML::TreeBuilder::XPath::Root) - if( $b->isa( 'HTML::TreeBuilder::XPath::Root') ) { return -1; } - - # easy cases - return 0 if( $a == $b); - return 1 if( $a->is_inside($b)); # a starts after b - return -1 if( $b->is_inside($a)); # a starts before b - - # lineage does not include the element itself - my @a_pile= ($a, $a->lineage); - my @b_pile= ($b, $b->lineage); - - # the 2 elements are not in the same twig - unless( $a_pile[-1] == $b_pile[-1]) - { warn "2 nodes not in the same pile: ", ref( $a), " - ", ref( $b), "\n"; - print "a: ", $a->string_value, "\nb: ", $b->string_value, "\n"; - return undef; - } - - # find the first non common ancestors (they are siblings) - my $a_anc= pop @a_pile; - my $b_anc= pop @b_pile; - - while( $a_anc == $b_anc) - { $a_anc= pop @a_pile; - $b_anc= pop @b_pile; - } - - if( defined( $a_anc->{_rank}) && defined( $b_anc->{_rank})) - { return $a_anc->{_rank} <=> $b_anc->{_rank}; } - else - { - # from there move left and right and figure out the order - my( $a_prev, $a_next, $b_prev, $b_next)= ($a_anc, $a_anc, $b_anc, $b_anc); - while() - { $a_prev= $a_prev->getPreviousSibling || return -1; - return 1 if( $a_prev == $b_anc); - $a_next= $a_next->getNextSibling || return 1; - return -1 if( $a_next == $b_anc); - $b_prev= $b_prev->getPreviousSibling || return 1; - return -1 if( $b_prev == $a_next); - $b_next= $b_next->getNextSibling || return -1; - return 1 if( $b_next == $a_prev); - } - } - } - - -# need to modify directly the HTML::Element package, because HTML::TreeBuilder won't let me -# change the class of the nodes it generates -package HTML::Element; -use Scalar::Util qw(weaken); -use vars qw(@ISA); - -push @ISA, 'HTML::TreeBuilder::XPath::Node'; - -use XML::XPathEngine; - -{ my $xp; - sub xp - { $xp ||=XML::XPathEngine->new(); - return $xp; - } -} - - -sub findnodes { my( $elt, $path)= @_; return xp->findnodes( $path, $elt); } -sub findnodes_as_string { my( $elt, $path)= @_; return xp->findnodes_as_string( $path, $elt); } -sub findnodes_as_strings { my( $elt, $path)= @_; return xp->findnodes_as_strings( $path, $elt); } -sub findvalue { my( $elt, $path)= @_; return xp->findvalue( $path, $elt); } -sub findvalues { my( $elt, $path)= @_; return xp->findvalues( $path, $elt); } -sub exists { my( $elt, $path)= @_; return xp->exists( $path, $elt); } -sub find_xpath { my( $elt, $path)= @_; return xp->find( $path, $elt); } -sub matches { my( $elt, $path)= @_; return xp->matches( $elt, $path, $elt); } -sub set_namespace { my $elt= shift; xp->new->set_namespace( @_); } - -sub getRootNode - { my $elt= shift; - # The parent of root is a HTML::TreeBuilder::XPath::Root - # that helps getting the tree to mimic a DOM tree - return $elt->root->getParentNode; # I like this one! - } - -sub getParentNode - { my $elt= shift; - return $elt->{_parent} || bless { _root => $elt }, 'HTML::TreeBuilder::XPath::Root'; - } -sub getName { return shift->tag; } -sub getNextSibling { my( $elt)= @_; - my $parent= $elt->{_parent} || return undef; - return $parent->_child_as_object( scalar $elt->right, ($elt->{_rank} || 0) + 1); - } -sub getPreviousSibling { my( $elt)= @_; - my $parent= $elt->{_parent} || return undef; - return undef unless $elt->{_rank}; - return $parent->_child_as_object( scalar $elt->left, $elt->{_rank} - 1); - } -sub isElementNode { return ref $_[0] && ($_[0]->{_tag}!~ m{^~}) ? 1 : 0; } -sub isCommentNode { return ref $_[0] && ($_[0]->{_tag} eq '~comment') ? 1 : 0; } -sub isProcessingInstructionNode { return ref $_[0] && ($_[0]->{_tag} eq '~pi') ? 1 : 0; } -sub isTextNode { return ref $_[0] ? 0 : 1; } - -sub getValue - { my $elt= shift; - if( $elt->isCommentNode) { return $elt->{_text}; } - return $elt->as_text; - } - -sub getChildNodes - { my $parent= shift; - my $rank=0; - my @children= map { $parent->_child_as_object( $_, $rank++) } $parent->content_list; - return wantarray ? @children : \@children; - } - -sub getFirstChild - { my $parent= shift; - my @content= $parent->content_list; - if( @content) - { return $parent->_child_as_object( $content[0], 0); } - else - { return undef; } - } -sub getLastChild - { my $parent= shift; - my @content= $parent->content_list; - if( @content) - { return $parent->_child_as_object( $content[-1], $#content); } - else - { return undef; } - } - -sub getAttributes - { my $elt= shift; - my %atts= $elt->all_external_attr; - my $rank=0; - my @atts= map { bless( { _name => $_, _value => $atts{$_}, - _elt => $elt, _rank => $rank++, - }, - 'HTML::TreeBuilder::XPath::Attribute' - ) - } sort keys %atts; - return wantarray ? @atts : \@atts; - } - -sub to_number { return XML::XPathEngine::Number->new( $_[0]->as_text); } -sub string_value - { my $elt= shift; - if( $elt->isCommentNode) { return $elt->{_text}; } - return $elt->as_text; - }; - -# called on a parent, with a child as second argument and its rank as third -# returns the child if it is already an element, or -# a new HTML::TreeBuilder::XPath::Text element if it is a plain string -sub _child_as_object - { my( $elt, $elt_or_text, $rank)= @_; - return undef unless( defined $elt_or_text); - if( ! ref $elt_or_text) - { # $elt_or_text is a string, turn it into a TextNode object - $elt_or_text= bless { _content => $elt_or_text, _parent => $elt, }, - 'HTML::TreeBuilder::XPath::TextNode' - ; - } - if( ref $rank) { warn "rank is a ", ref( $rank), " elt_or_text is a ", ref( $elt_or_text); } - $elt_or_text->{_rank}= $rank; # used for sorting; - return $elt_or_text; - } - -sub toString { return shift->as_XML( @_); } - -# produces better looking XML -{ - no warnings 'redefine'; - sub as_XML_compact - { my( $node, $opt)= @_; - my $name = $node->{'_tag'}; - if( $name eq '~literal') { return _xml_escape_text( $node->{text}); } - - if( $name eq '~declaration') { return '{text}) . ">"; } - if( $name eq '~pi') { return '{text}) . '?>'; } - if( $name eq '~comment') { return ''; } - - my $lc_name= lc $name; - - my $xml= $node->_start_tag; - - if( $HTML::Tagset::isCDATA_Parent{$lc_name}) - { my $content= $node->{_content} || ''; - if( ref $content eq 'ARRAY' || $content->isa( 'ARRAY')) - { $xml .= _xml_escape_cdata( join( '', @$content), $opt); } - else - { $xml .= $content; } - } - else - { # start tag - foreach my $child ($node->content_list) - { if( ref $child) { $xml .= $child->as_XML_compact(); } - else { $xml .= _xml_escape_text( $child); } - } - } - $xml.= "" unless $HTML::Tagset::emptyElement{$lc_name}; - return $xml; - } -} - - - -{ my %phrase_name; # all phrase tags, + literals (those are not indented) - my %extra_newline; # tags that get an extra newline before the end tag - my $default_indent; # 2 spaces, change with the 'indent' option - BEGIN - { %phrase_name= %HTML::Tagset::isPhraseMarkup; - $phrase_name{'~literal'}= 1; - $default_indent= ' '; - %extra_newline= map { $_ => 1 } qw(html head body script div table tbody thead tfoot tr form dl ol ul); - } - - sub as_XML_indented - { my( $node, $opt)= @_; - - - my $name = $node->{'_tag'}; - my $lc_name= lc $name; - - if( $name eq '~literal') { return _xml_escape_text( $node->{text}); } - if( $name eq '~declaration') { return '{text}) . ">\n"; } - - - if( $name eq '~pi') { return '{text}) . '?>'; } - if( $name eq '~comment') { return ''; } - - my $xml; - my $pre_tag_indent=''; - if(!$phrase_name{$lc_name}) { $pre_tag_indent= "\n" . ($opt->{indent} || $default_indent) x ($opt->{indent_level}||0); } - if( $opt->{indent_level}) { $xml .= $pre_tag_indent; } - - $xml.= $node->_start_tag(); - - my $content=''; - - if( $HTML::Tagset::isCDATA_Parent{$lc_name}) - { my $content= $node->{_content} || ''; - if( ref $content && (ref $content eq 'ARRAY' || $content->isa( 'ARRAY') )) - { $content= _xml_escape_cdata( join( '', @$content), $opt); } - } - else - { - my %child_opt= %$opt; - $child_opt{indent_level}++; - foreach my $child ($node->content_list) - { if( ref $child) { $content .= $child->as_XML_indented( \%child_opt ); } - else { $content .= _xml_escape_text( $child); } - } - } - $xml .= $content; - - if( $extra_newline{$lc_name} && $content ne '' ) { $xml.= $pre_tag_indent; } - $xml.= "" unless $HTML::Tagset::emptyElement{$lc_name}; - $xml .="\n" if( !$opt->{indent_level}); - - return $xml; - } -} - -sub _start_tag - { my( $node)= @_; - my $name = $node->{'_tag'}; - my $start_tag.= "<$name"; - foreach my $att_name (sort keys %$node) - { next if( (!length $att_name) || ($att_name=~ m{^_}) || ($att_name eq '/') ); - my $well_formed_att_name= well_formed_name( $att_name); - $start_tag .= qq{ $well_formed_att_name="} . _xml_escape_attribute_value( $node->{$att_name}) . qq{"}; - } - $start_tag.= $HTML::Tagset::emptyElement{lc $name} ? " />" : ">"; - return $start_tag; - } - -sub well_formed_name - { my( $name)= @_; - $name=~ s{[^\w:_-]+}{_}g; - if( $name=~ m{^\d}) { $name= "a$name"; } - return $name; - } - -sub _indent_level - { my( $node)= @_; - my $level= scalar grep { !$HTML::Tagset::isPhraseMarkup{lc $_->{_tag}} } $node->lineage; - return $level; - } - -{ my( $indent, %extra_newline, $nl); - BEGIN - { $indent= ' '; - $nl= "\n"; - %extra_newline= map { $_ => 1 } qw(html head body script div table tr form ol ul); - } - - sub indents - { my( $opt, $name)= @_; - my $indents= { pre_start_tag => '', post_start_tag => '', pre_end_tag => '', post_end_tag => ''}; - if( $opt->{indented}) - { my $indent_level= $opt->{indent_level}; - my $wrapping_nl= $nl; - if( !defined( $indent_level)) { $indent_level = 0; $wrapping_nl= ''; } - if( $HTML::Tagset::isKnown{lc $name} && !$HTML::Tagset::isPhraseMarkup{lc $name} && $indent_level > 0) - { $indents->{pre_start_tag}= $wrapping_nl . ($indent x $indent_level); } - if( $extra_newline{lc $name}) - { $indents->{post_start_tag}= $nl; - $indents->{pre_end_tag}= $nl . ($indent x $indent_level); - } - if( $indent_level == 0) - { $indents->{post_end_tag} = $wrapping_nl; } - } - return $indents; - } -} - - -sub _xml_escape_attribute_value - { my( $text)= @_; - $text=~ s{([&<>"])}{$CHAR2DEFAULT_ENT{$1}}g; # escape also quote, as it is the attribute separator - return $text; - } - -sub _xml_escape_text - { my( $text)= @_; - $text=~ s{([&<>])}{$CHAR2DEFAULT_ENT{$1}}g; - return $text; - } - -sub _xml_escape_comment - { my( $text)= @_; - $text=~ s{([&<>])}{$CHAR2DEFAULT_ENT{$1}}g; - $text=~ s{--}{--}g; # can't have double --'s in XML comments - return $text; - } - -sub _xml_escape_cdata - { my( $text, $opt)= @_; - if( $opt->{force_escape_cdata} || $text=~ m{[<&]}) - { $text=~ s{^\s*\Q\E\s*$}{}s; - $text=~ s{]]>}{]]>}g; # can't have]]> in CDATA - $text= ""; - } - return $text; - } - - -package HTML::TreeBuilder::XPath::TextNode; - -use base 'HTML::TreeBuilder::XPath::Node'; - -sub getParentNode { return shift->{_parent}; } -sub getValue { return shift->{_content}; } -sub isTextNode { return 1; } -sub getAttributes { return wantarray ? () : []; } - -# similar to HTML::Element as_XML -sub as_XML - { my( $node, $entities)= @_; - my $content= $node->{_content}; - if( $node->{_parent} && $node->{_parent}->{_tag} eq 'script') - { $content=~ s{(&\w+;)}{HTML::Entities::decode($1)}eg; } - else - { $content= HTML::Element::_xml_escape_text($content); } - return $content; - } -*as_XML_compact = *as_XML; -*as_XML_indented = *as_XML; - - -sub getPreviousSibling - { my $self= shift; - my $rank= $self->{_rank}; - #unless( defined $self->{_rank}) - # { warn "no rank for text node $self->{_content}, parent is $self->{_parent}->{_tag}\n"; } - my $parent= $self->{_parent}; - return $rank ? $parent->_child_as_object( $parent->{_content}->[$rank-1], $rank-1) : undef; - } - -sub getNextSibling - { my $self= shift; - my $rank= $self->{_rank}; - #unless( defined $self->{_rank}) - # { warn "no rank for text node $self->{_content}, parent is $self->{_parent}->{_tag}\n"; } - my $parent= $self->{_parent}; - my $next_sibling= $parent->{_content}->[$rank+1]; - return defined( $next_sibling) ? $parent->_child_as_object( $next_sibling, $rank+1) : undef; - } - -sub getRootNode - { return shift->{_parent}->getRootNode; } - -sub string_value { return shift->{_content}; } - -# added to provide element-like methods to text nodes, for use by cmp -sub lineage - { my( $node)= @_; - my $parent= $node->{_parent}; - return( $parent, $parent->lineage); - } - -sub is_inside - { my( $text, $node)= @_; - return $text->{_parent}->is_inside( $node); - } - -1; - - -package HTML::TreeBuilder::XPath::Attribute; -use base 'HTML::TreeBuilder::XPath::Node'; - -sub getParentNode { return $_[0]->{_elt}; } -sub getValue { return $_[0]->{_value}; } -sub getName { return $_[0]->{_name} ; } -sub getLocalName { (my $name= $_[0]->{_name}) =~ s{^.*:}{}; $name; } -sub string_value { return $_[0]->{_value}; } -sub to_number { return XML::XPathEngine::Number->new( $_[0]->{_value}); } -sub isAttributeNode { 1 } -sub toString { return qq{ $_[0]->{_name}="$_[0]->{_value}"}; } - -# awfully inefficient, but hopefully this is called only for weird (read test-case) queries -sub getPreviousSibling - { my $self= shift; - my $rank= $self->{_rank}; - return undef unless $rank; - my %atts= $self->{_elt}->all_external_attr; - my $previous_att_name= (sort keys %atts)[$rank-1]; - return bless( { _name => $previous_att_name, - _value => $atts{$previous_att_name}, - _elt => $self->{_elt}, _rank => $rank-1, - }, 'HTML::TreeBuilder::XPath::Attribute' - ); - } - -sub getNextSibling - { my $self= shift; - my $rank= $self->{_rank}; - my %atts= $self->{_elt}->all_external_attr; - my $next_att_name= (sort keys %atts)[$rank+1] || return undef; - return bless( { _name => $next_att_name, _value => $atts{$next_att_name}, - _elt => $self->{_elt}, _rank => $rank+1, - }, 'HTML::TreeBuilder::XPath::Attribute' - ); - - } - - - -# added to provide element-like methods to attributes, for use by cmp -sub lineage - { my( $att)= @_; - my $elt= $att->{_elt}; - return( $elt, $elt->lineage); - } - -sub is_inside - { my( $att, $node)= @_; - return ($att->{_elt} == $node) || $att->{_elt}->is_inside( $node); - } - -1; - - -package HTML::TreeBuilder::XPath::Root; - -use base 'HTML::TreeBuilder::XPath::Node'; - -sub getParentNode { return (); } -sub getChildNodes { my @content= ( $_[0]->{_root}); return wantarray ? @content : \@content; } -sub getAttributes { return [] } -sub isDocumentNode { return 1 } - -# added to provide element-like methods to root, for use by cmp -sub lineage { return ($_[0]); } -sub is_inside { return 0; } -sub cmp { return $_[1]->isa( ' HTML::TreeBuilder::XPath::Root') ? 0 : 1; } - -1; - -__END__ -=head1 NAME - -HTML::TreeBuilder::XPath - add XPath support to HTML::TreeBuilder - -=head1 SYNOPSIS - - use HTML::TreeBuilder::XPath; - my $tree= HTML::TreeBuilder::XPath->new; - $tree->parse_file( "mypage.html"); - my $nb=$tree->findvalue( '/html/body//p[@class="section_title"]/span[@class="nb"]'); - my $id=$tree->findvalue( '/html/body//p[@class="section_title"]/@id'); - - my $p= $html->findnodes( '//p[@id="toto"]')->[0]; - my $link_texts= $p->findvalue( './a'); # the texts of all a elements in $p - - -=head1 DESCRIPTION - -This module adds typical XPath methods to HTML::TreeBuilder, to make it -easy to query a document. - -=head1 METHODS - -Extra methods added both to the tree object and to each element: - -=head2 findnodes ($path) - -Returns a list of nodes found by C<$path>. -In scalar context returns an C object. - -=head2 findnodes_as_string ($path) - -Returns the text values of the nodes, as one string. - -=head2 findnodes_as_strings ($path) - -Returns a list of the values of the result nodes. - -=head2 findvalue ($path) - -Returns either a C, a C -or a C object. If the path returns a NodeSet, -$nodeset->xpath_to_literal is called automatically for you (and thus a -C is returned). Note that -for each of the objects stringification is overloaded, so you can just -print the value found, or manipulate it in the ways you would a normal -perl value (e.g. using regular expressions). - -=head2 findvalues ($path) - -Returns the values of the matching nodes as a list. This is mostly the same -as findnodes_as_strings, except that the elements of the list are objects -(with overloaded stringification) instead of plain strings. - -=head2 exists ($path) - -Returns true if the given path exists. - -=head2 matches($path) - -Returns true if the element matches the path. - -=head2 find ($path) - -The find function takes an XPath expression (a string) and returns either a -Tree::XPathEngine::NodeSet object containing the nodes it found (or empty if -no nodes matched the path), or one of XML::XPathEngine::Literal (a string), -XML::XPathEngine::Number, or XML::XPathEngine::Boolean. It should always -return something - and you can use ->isa() to find out what it returned. If -you need to check how many nodes it found you should check $nodeset->size. -See L. - -=head2 as_XML_compact - -HTML::TreeBuilder's C output is not really nice to look at, so -I added a new method, that can be used as a simple replacement for it. -It escapes only the '<', '>' and '&' (plus '"' in attribute values), and -wraps CDATA elements in CDATA sections. - -Note that the XML is actually not garanteed to be valid at this point. Nothing -is done about the encoding of the string. Patches or just ideas of how it could -work are welcome. - -=head2 as_XML_indented - -Same as as_XML, except that the output is indented. - -=head1 SEE ALSO - -L - -L - -=head1 AUTHOR - -Michel Rodriguez, Emirod@cpan.orgE - -=head1 COPYRIGHT AND LICENSE - -Copyright (C) 2006 by Michel Rodriguez - -This library is free software; you can redistribute it and/or modify -it under the same terms as Perl itself, either Perl version 5.8.4 or, -at your option, any later version of Perl 5 you may have available. - - -=cut diff --git a/test_as_XML b/test_as_XML deleted file mode 100644 index 5e858dc..0000000 --- a/test_as_XML +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/perl - -use strict; -use warnings; - -use HTML::TreeBuilder::XPath; - -my $doc=q{ - - - - - - - -

& & < > & été été été ""

-

& & < > & été été été

-
-

foo bar baz

- -}; - -{ -my $h= HTML::TreeBuilder::XPath->new; -$h->parse( $doc); -#print $h->as_HTML; -} - - -{ -my $h= HTML::TreeBuilder::XPath->new; -$h->parse( $doc); -#print $h->as_XML; -} -{ -my $h= HTML::TreeBuilder::XPath->new; -$h->parse( $doc); -print $h->as_XML_clean; -} - - diff --git a/test_guess_charset b/test_guess_charset deleted file mode 100644 index 75b2d0c..0000000 --- a/test_guess_charset +++ /dev/null @@ -1,21 +0,0 @@ - -sub charset - { my( $root)= @_; - #my $root= $node->root; - my $charset; - # get the XML declaration first (need pis to be stored) - if( my $xml_decl= first { $_->{_tag} eq '~pi' } $root->content_list) - { if( $xml_decl->{text}=~ m{encoding\s*=\s*(["'])(.*?)\1}) - { $charset->{declaration}= $2; } - } - - if( my $head= first { lc( $_->{_tag}) eq 'head' } $root->content_list) - { if( my $meta= first { lc( $_->{_tag}) eq 'meta' && lc( $_->{http-equiv}) eq "content-type") } - $root->content_list - ) - { if( $meta->{content} && lc( $meta->{content})=~ m{charset\s*=\s*([\w-]*)) - { charset->{meta}= $1; } - } - - return $charset; - } diff --git a/~/.perldb.hist b/~/.perldb.hist deleted file mode 100644 index ac251f9..0000000 --- a/~/.perldb.hist +++ /dev/null @@ -1,16 +0,0 @@ -b 36 -x $t->as_XML -b 39 -x $t -x $t->findvalue( '/html/body/comment()' -$t->findvalue( '/html/body/comment()') -x $t->findvalue( '/html/body/comment()') -x $t->findvalue( '//comment()') -x $t->findnodes( '//comment()') -x map { $_->getValue } $t->findnodes( '//comment()') -x $t->findvalue( '//comment()') -$c= ($t->findnodes( '//comment()'))[0] -x $c->as_text -x $c -x $c->string_value -x $c->{text} -- 2.11.4.GIT