Changeset 21998 for lang/perl/MooseX-DOM
- Timestamp:
- 10/24/08 00:34:02 (5 years ago)
- Location:
- lang/perl/MooseX-DOM/trunk
- Files:
-
- 7 added
- 6 removed
- 4 modified
-
Changes (modified) (1 diff)
-
Makefile.PL (modified) (1 diff)
-
eg (added)
-
eg/synopsis.pl (added)
-
lib/MooseX/DOM.pm (modified) (2 diffs)
-
lib/MooseX/DOM/LibXML.pm (modified) (1 diff)
-
lib/MooseX/DOM/LibXML/ContextNode.pm (deleted)
-
lib/MooseX/DOM/LibXML/XPathContext.pm (added)
-
lib/MooseX/DOM/Meta/Class.pm (added)
-
lib/MooseX/DOM/Meta/LibXML (deleted)
-
lib/MooseX/DOM/Meta/LibXML.pm (deleted)
-
t/00_compile.t (deleted)
-
t/01_simple.t (deleted)
-
t/lib/Test/MooseX (added)
-
t/lib/Test/MooseX/DOM (added)
-
t/lib/Test/MooseX/DOM/Recipe001.pm (added)
-
t/lib/Test/MxD (deleted)
Legend:
- Unmodified
- Added
- Removed
-
lang/perl/MooseX-DOM/trunk/Changes
r17482 r21998 1 1 Changes 2 2 ======= 3 4 0.00999_01 - 23 Oct 2008 5 * Major rewrite. Beware! Backwards incompatible! 6 Everything is changed, except for the core idea. 7 This release should make it really easy to create DOM based objects. 3 8 4 9 0.00004 - 12 Aug 2008 -
lang/perl/MooseX-DOM/trunk/Makefile.PL
r17353 r21998 5 5 all_from('lib/MooseX/DOM.pm'); 6 6 7 requires 'Class::Inspector';8 7 requires 'Moose'; 9 requires 'XML::LibXML', 1.63; 10 requires 'XML::LibXML::XPathContext'; 8 requires 'XML::LibXML'; 11 9 12 10 test_requires 'Test::More'; 13 11 test_requires 'Test::UseAllModules'; 14 12 15 auto_include ;13 auto_include_deps; 16 14 WriteAll; 15 -
lang/perl/MooseX-DOM/trunk/lib/MooseX/DOM.pm
r17482 r21998 3 3 package MooseX::DOM; 4 4 use strict; 5 use Moose::Util; 6 use Carp (); 5 use warnings; 6 use 5.008; 7 use MooseX::DOM::Meta::Class; 7 8 8 9 our $AUTHORITY = 'cpan:DMAKI'; 9 our $VERSION = '0.00004'; 10 11 BEGIN { 12 my $engine = $ENV{MOOSEX_DOM_ENGINE} || 'MooseX::DOM::LibXML'; 13 Class::MOP::load_class( $engine ); 14 15 constant->import(ENGINE => $engine); 16 } 10 our $VERSION = '0.00999'; 17 11 18 12 sub import { 19 13 my $class = shift; 20 my $caller = caller(0); 21 22 return if $caller eq 'main'; 23 24 # if $caller is already meta-fied. 25 if ( $caller->can('meta') ) { 26 Carp::confess "You already have 'meta' initialized. you need to 'use MooseX::DOM' /instead/ of 'use Moose'"; 27 } 28 29 my $engine = &ENGINE; 30 $engine->init_meta( $caller ); 31 Moose::Util::apply_all_roles($caller->meta, $engine); 32 Moose->import( { into => $caller }, @_ ); 33 34 my $exporter = join('::', $engine, 'export_dsl'); 35 goto &$exporter; 14 my $caller = caller(); 15 16 my $backend = 'MooseX::DOM::LibXML'; 17 Class::MOP::load_class($backend); 18 19 Moose::Util::MetaRole::apply_metaclass_roles( 20 for_class => $caller, 21 metaclass_roles => [ 'MooseX::DOM::Meta::Class' ] 22 ); 23 $backend->setup($caller); 24 $class->export_keywords($caller); 36 25 } 37 26 38 27 sub unimport { 39 28 my $class = shift; 40 41 my $caller = caller(0); 42 Moose->unimport( { into => $caller }, @_ ); 43 44 my $engine = &ENGINE; 45 my $unexporter = join('::', $engine, 'unexport_dsl' ); 46 goto &$unexporter; 47 } 48 49 50 29 my $caller = caller(); 30 31 $class->unexport_keywords($caller); 32 } 33 34 sub export_keywords { 35 my ($class, $caller) = @_; 36 37 my $exporter = Sub::Exporter::build_exporter({ 38 into => $caller, 39 groups => { default => [ ':all' ] }, 40 exports => [ 41 dom_nodes => sub { $class->build_dom_nodes($caller) }, 42 dom_fetchnodes => sub { $class->build_dom_fetchnodes($caller) }, 43 dom_to_class => sub { $class->build_dom_to_class($caller) }, 44 dom_value => sub { $class->build_dom_value($caller) }, 45 ] 46 }); 47 $exporter->($class); 48 } 49 50 sub unexport_keywords { 51 my ($class, $caller) = @_; 52 my @keywords = qw(dom_nodes dom_fetchnodes dom_to_class dom_value); 53 54 { no strict 'refs'; 55 foreach my $name (@keywords) { 56 if ( defined &{ $caller . '::' . $name }) { 57 delete ${ $caller . '::' }{$name}; 58 } 59 } 60 } 61 } 62 63 sub build_dom_value { 64 my ($class, $caller) = @_; 65 66 return sub { 67 my $name = shift; 68 my $args = { @_ == 1 ? (fetch => {xpath => $_[0]}) : @_ }; 69 70 my $fetch = $args->{fetch}; 71 my $fetch_xpath = $fetch->{xpath} || $name; 72 my $meta = $caller->meta; 73 $meta->add_method( 74 $name, 75 Moose::Meta::Method->wrap( 76 package_name => $caller, 77 name => $name, 78 body => sub { 79 my $self = shift; 80 $self->dom_root->findvalue($fetch_xpath); 81 } 82 ) 83 ); 84 }; 85 } 86 87 sub build_dom_nodes { 88 my ($class, $caller) = @_; 89 90 return sub { 91 my $name = shift; 92 my $args = { @_ == 1 ? (fetch => $_[0]) : @_ }; 93 94 $args->{into} = $caller; 95 my @methods = ( 96 $class->build_dom_nodes_accessor($name, $args), 97 $class->build_dom_nodes_appender($name, $args), 98 ); 99 100 my $meta = $caller->meta; 101 foreach my $method (@methods) { 102 $meta->add_method($method->{name}, $method->{code}); 103 } 104 } 105 } 106 107 sub build_dom_nodes_appender { 108 my ($class, $name, $args) = @_; 109 110 # I can't figure out this one automatically (I think). 111 # just expect a code, and if I can't find it, not methods are 112 # returned to the callee 113 my $config = ref $args->{append} eq 'HASH' ? $args->{append} : 114 { code => $args->{append} }; 115 my $method = $config->{name} || "add_$name"; 116 my $code = $config->{code}; 117 my $ret; 118 if ($code) { 119 $ret = { 120 $method, 121 Moose::Meta::Method->wrap( 122 package_name => $args->{into}, 123 name => $method, 124 body => $code 125 ) 126 }; 127 } 128 return $ret ? $ret : (); 129 } 130 131 sub build_dom_nodes_accessor { 132 my ($class, $name, $args) = @_; 133 134 my $fetch = $args->{fetch}; 135 my $store = $args->{store}; 136 137 if (! ref $fetch) { 138 my $xpath = $fetch; 139 $fetch = sub { shift->dom_root->findnodes($xpath) }; 140 } 141 142 my $code = <<" EOSUB"; 143 sub { 144 my \$self = shift; 145 my \@ret = \$fetch->(\$self); 146 EOSUB 147 if ($store) { 148 $code .= <<" EOSUB"; 149 if (\@_) { 150 \$store->(\$self, \@_); 151 } 152 EOSUB 153 } 154 155 $code .= <<" EOSUB"; 156 return \@ret; 157 } 158 EOSUB 159 my $cv = eval $code; Carp::confess($@) if $@; 160 161 return { 162 name => $name, 163 code => Moose::Meta::Method->wrap( 164 package_name => $args->{into}, 165 name => $name, 166 body => $cv, 167 ) 168 }; 169 } 170 171 sub build_dom_fetchnodes { 172 my ($class, $caller) = @_; 173 174 return sub { 175 my $args = {@_ == 1 ? (xpath => $_[0]) : @_}; 176 my $filter = $args->{filter}; 177 my $xpath = $args->{xpath}; 178 return $filter ? 179 sub { 180 my $self = shift; 181 return $filter->($self->dom_root->findnodes($xpath)); 182 } : 183 sub { 184 my $self = shift; 185 return $self->dom_root->findnodes($xpath); 186 } 187 }; 188 } 189 190 sub build_dom_to_class { 191 my ($class, $caller) = @_; 192 193 return sub { 194 my $args = {@_ == 1 ? (to_class => $_[0]) : @_}; 195 my $to_class = $args->{to_class}; 196 Class::MOP::load_class($to_class); 197 return sub { 198 map { $to_class->new($_) } @_; 199 } 200 } 201 } 51 202 1; 52 203 … … 55 206 =head1 NAME 56 207 57 MooseX::DOM - Simplistic Object XML Mapper208 MooseX::DOM - Easily Create DOM Based Objects 58 209 59 210 =head1 SYNOPSIS 60 211 61 package MyObject; 62 use MooseX::DOM; 63 64 has_dom_child 'title'; 65 66 no Moose; 67 no MoooseX::DOM; 68 69 my $obj = MyObject->new(node => <<EOXML); 70 <feed> 71 <title>Foo</title> 72 </feed> 73 EOXML 74 75 print $obj->title(), "\n"; # Foo 76 $obj->title('Bar'); 77 print $obj->title(), "\n"; # Bar 212 package RSS; 213 use Moose; 214 use MooseX::DOM; 215 216 dom_value 'version' => '@version'; 217 dom_nodes 'items' => ( 218 fetch => dom_fetchnodes( 219 xpath => 'channel/item', 220 filter => dom_to_class('RSS::Item') 221 ) 222 ); 223 224 # or, easy way (just get some DOM nodes) 225 # dom_nodes 'items' => 'channel/items'; 226 227 # or, create your own way to fetch the nodes 228 # dom_nodes 'items' => ( 229 # fetch => sub { ... } 230 # ); 231 232 no Moose; 233 no MooseX::DOM; 234 235 package RSS::Item; 236 use Moose; 237 use MooseX::DOM; 238 239 dom_value 'title'; 240 dom_value 'description'; 241 dom_value 'link'; 242 243 no Moose; 244 no MooseX::DOM; 245 246 sub BUILDARGS { 247 my $class = shift; 248 my $args = {@_ == 1? (dom_root => $_[0]) : @_}; 249 return $args; 250 } 251 252 package main; 253 254 # parse_file() is automatically created for you. 255 my $rss = RSS->parse_file('rss.xml'); 256 foreach my $item ($rss->items) { 257 print "item link = ", $item->link, "\n"; 258 print "item title = ", $item->title, "\n"; 259 } 78 260 79 261 =head1 DESCRIPTION 80 262 81 This module is intended to be used in conjunction with other modules 82 that encapsulate XML data (for example, XML feeds). 83 84 =head1 DECLARATION 85 86 =head2 has_dom_root $name[, %opts] 87 88 Specifies that the given XML have the specified tag. This specification is 89 also used when creating new root node for creating the underlying XML 90 91 has_dom_root $name => ( 92 # attributes => { ... } 93 ); 94 95 =head2 has_dom_attr $name[, %opts] 96 97 Specifies that the object should contain an attribute by the given name 98 99 =head2 has_dom_child $name[, %opts] 100 101 Specifies that the object should contain a single child by the given name. 102 Will generate accessor that can handle set/get 103 104 has_dom_child 'foo'; 105 106 $obj->foo(); # get the value of child element foo 107 $obj->foo("bar"); # set the value of child element foo to bar 108 109 %opts may contain C<namespace>, C<tag>, and C<filter> 110 111 Specifying C<namespace> forces MooseX::DOM to look for tags in a specific 112 namespace uri. 113 114 Specifying C<tag> allows MooseX::DOM to look for the tag name given in C<tag> 115 while making the generated method name as C<$name> 116 117 The optional C<filter> parameter should be a subroutine that takes the object 118 itself as the first parameter, and the DOM node(s) as the rest of the 119 parameters. You are allowed to transform the node as you like. By default, 120 a filter that converts the node to its text content is used. 121 122 has_dom_child 'foo' => ( 123 filter => sub { 124 my ($self, $node) = @_; 125 # return whatever you want to return, perhaps transforming $node 126 } 127 ); 128 129 The optional C<create> parameter should be a subroutine that does the 130 does the actual insertion of the new node, given the arguments. 131 By default it expects a list of text argument, and creates a child node 132 with those arguments. 133 134 has_dom_child 'foo' => ( 135 create => sub { 136 my($self, %args) = @_; 137 # keys in %args: 138 # child 139 # namespace 140 # tag 141 # value 142 } 143 ); 144 145 =head2 has_dom_children 146 147 Specifies that the object should contain possibly multiple children by the 148 given name 149 150 has_dom_children 'foo'; 151 152 $obj->foo(); # Returns a list of values for each child element foo 153 $obj->foo(qw(1 2 3)); # Discards old values of foo, and create new nodes 154 155 %opts may contain C<namespace>, C<tag>, C<filter>, and C<create> 156 157 The optional C<namespace> parameter forces MooseX::DOM to look for tags in a 158 specific namespace uri. 159 160 The optional C<tag> parameter allows MooseX::DOM to look for the tag name given 161 in C<tag> while making the generated method name as C<$name> 162 163 The optional C<filter> parameter should be a subroutine that takes the object 164 itself as the first parameter, and the DOM node(s) as the rest of the 165 parameters. You are allowed to transform the node as you like. By default, 166 a filter that converts the node to its text content is used. 167 168 has_dom_children 'foo' => ( 169 filter => sub { 170 my ($self, @nodes) = @_; 171 # return whatever you want to return, perhaps transforming @nodes 172 } 173 ); 174 175 The optional C<create> parameter should be a subroutine that does the 176 does the actual insertion of the new nodes, given the arguments. 177 By default it expects a list of text arguments, and creates child nodes 178 with those arguments. 179 180 has_dom_children 'foo' => ( 181 create => sub { 182 my($self, %args) = @_; 183 # keys in %args: 184 # children 185 # namespace 186 # tag 187 # values 188 } 189 ); 190 191 =head2 has_dom_content $name 192 193 If your node only contains text data (that is, your root node does not have any 194 subsequent element nodes as its child), you can access the text data directly 195 with this declaration 263 MooseX::DOM is a tool that allows you to define classes that are based on 264 XML DOM. 265 266 =head1 PROVIDED DSL 267 268 The following DSL is provided upon calling C<MooseX::DOM>. When 269 C<no MooseX::DOM> is used, these functions are removed from your namespace. 270 271 =head2 dom_nodes $name => %spec 272 273 Declares that a method named $name should be built, using the given spec. 274 Returns a list of nodes, or what the filter argument trasnlates them to. 275 276 If %spec is omitted, $name is taken to be the xpath to fetch. 277 278 =head2 dom_value $name => %spec 279 280 Declares that a method named $name should be built, using the given spec. 281 Returns the result of the fetch, whatever that may be. 282 283 If %spec is omitted, $name is taken to be the xpath to fetch. 284 285 =head2 dom_fetchnodes %spec 286 287 Creates a closure that fetches some nodes 288 289 =head2 dom_to_class %spec 290 291 Creates a closure that transforms nodes to something else, typically an object. 292 293 =head1 PROVIDED METHODS 294 295 The following methods are built onto your class automatically. 296 297 =head2 parse_file 298 299 =head2 parse_string 300 301 =head2 parse_fh 302 303 These methods allow you to parse a piece of XML, and build a MooseX::DOM 304 object based on it. 305 306 =head2 dom_findnodes($xpath) 307 308 Does a DOM XPath lookup. Returns a plain DOM object. 309 310 =head2 dom_findvalue($xpath) 311 312 Does a DOM XPath lookup. Returns whatever value the XPath results to. 196 313 197 314 =head1 AUTHOR -
lang/perl/MooseX-DOM/trunk/lib/MooseX/DOM/LibXML.pm
r17756 r21998 2 2 3 3 package MooseX::DOM::LibXML; 4 use Moose::Role; 5 use MooseX::DOM::LibXML::ContextNode; 6 use Moose X::DOM::Meta::LibXML;7 use MooseX::DOM:: Meta::LibXML::Attribute::Content;4 # I want to use MooseX::Singleton, but it generates some warnings, 5 # so thi is a plain moose class with package level global 6 use Moose; 7 use MooseX::DOM::LibXML::XPathContext; 8 8 9 use constant DEFAULT_NAMESPACE_PREFIX => "#default"; 10 11 has 'node' => ( 9 has 'dom_root_attr' => ( 12 10 is => 'rw', 13 isa => 'MooseX::DOM::LibXML::ContextNode', 14 coerce => 1, 11 isa => 'Moose::Meta::Attribute', 12 lazy => 1, 13 builder => 'build_dom_root_attr' 15 14 ); 16 15 17 has 'namespaces' => ( 18 is => 'rw', 19 isa => 'HashRef', 20 required => 1, 21 default => sub { +{} } 22 ); 16 my @METHODS = qw(parse_file parse_string dom_findvalue dom_findnodes); 17 foreach my $method (@METHODS) { 18 my $attr = "${method}_method"; 19 my $builder = "build_${method}_method"; 23 20 24 no Moose; 25 26 sub BUILD { 27 my $self = shift; 28 $self->node->register_namespaces( $self->namespaces ); 29 $self; 30 } 31 32 sub init_meta { 33 # Only MooseX::DOM knows the true caller, so we expect it to 34 # provide us with one 35 my ($class, $caller) = @_; 36 37 Moose::init_meta( 38 $caller, 39 undef, 40 'MooseX::DOM::Meta::LibXML' 21 has $attr=> ( 22 is => 'rw', 23 isa => 'Moose::Meta::Method', 24 lazy => 1, 25 builder => $builder 41 26 ); 42 27 } 43 28 44 BOOTSTRAP: { 45 my $subname = sub { join('::', $_[1] || __PACKAGE__, $_[0]) }; 46 my $subassign = sub { 47 no strict 'refs'; 48 *{$_[0]} = Class::MOP::subname($_[0], $_[1]); 49 }; 29 __PACKAGE__->meta->make_immutable; 30 31 no Moose; 50 32 51 # Used to convert element node to its text content 52 my $textfilter = sub { 53 my $self = shift; 54 return map { blessed $_ && $_->can('textContent') ? $_->textContent : $_ } @_; 55 }; 33 our $INSTANCE; 56 34 57 # Used only in has_dom_children, to create a list of element nodes from 58 # list of text 59 my $text2elements = Class::MOP::subname($subname->('text2elements') => sub { 60 my($self, %args) = @_; 35 sub setup { 36 my ($class, $caller) = @_; 61 37 62 my $values = $args{values}; 63 my $namespace = $args{namespace} || ''; 64 my $tag = $args{tag}; 38 my $meta = $caller->meta; 39 my $self = ($INSTANCE ||= $class->new()); 40 $self->add_attributes($meta); 41 $self->add_methods($meta); 42 $meta->backend($self); 43 } 65 44 66 my $node = $self->node; 45 sub add_attributes { 46 my ($self, $meta) = @_; 67 47 68 my $nsuri = $self->namespaces->{ $namespace }; 69 my $document = $node->ownerDocument; 70 my @children; 71 foreach my $data (@$values) { 72 my $child = ($nsuri) ? 73 $document->createElementNS($nsuri, $tag) : 74 $document->createElement($tag) 75 ; 76 $child->appendTextNode($data); 77 push @children, $child; 78 $node->appendChild($child); 79 } 80 return @children; 81 }); 48 $meta->add_attribute( $self->dom_root_attr ); 49 } 82 50 83 my %exports = ( 84 has_dom_root => sub { 85 return Class::MOP::subname($subname->('has_dom_root') => sub ($;%) { 86 my $caller = caller(); 87 my ($tag, %args) = @_; 88 # tag => $tag 89 # attributes => { attr1 => $val1, attr2 => $val2 } 51 sub add_methods { 52 my ($self, $meta) = @_; 90 53 91 # Find the meta attribute for 'node', and add type constraints 92 93 $tag = $args{tag} if $args{tag}; 94 my $attrs = $args{attributes}; 95 96 my $meta = $caller->meta; 97 my $node_attr = $meta->get_attribute('node'); 98 return () unless $node_attr; 99 100 101 $meta->dom_root( { tag => $tag, attributes => $attrs } ); 102 103 # This needs to be done here so that the /applied/ class 104 # can use it instead of this class, which is a role 105 $meta->add_around_method_modifier(new => sub { 106 my $next = shift; 107 my $self = $next->(@_); 108 $self->meta->assert_root_node($self); 109 return $self; 110 }); 111 $meta->add_after_method_modifier(node => sub { 112 my $self = shift; 113 if (@_) { 114 $self->meta->assert_root($self, @_); 115 } 116 }); 117 }); 118 }, 119 has_dom_content => sub { 120 return Class::MOP::subname($subname->('has_dom_content') => sub ($;%) { 121 my ($name, %args) = @_; 122 my $caller = caller(); 123 my $meta = $caller->meta; 124 my $metaclass = 'MooseX::DOM::Meta::LibXML::Attribute::Content'; 125 my $attr = Moose::Meta::Attribute->interpolate_class_and_new( 126 $name, 127 metaclass => $metaclass, 128 is => 'rw', 129 tag => $name, 130 accessor => $name, 131 %args, 132 ); 133 $meta->add_attribute( $attr ); 134 }); 135 }, 136 has_dom_attr => sub { 137 return Class::MOP::subname($subname->('has_dom_attr') => sub ($;%) { 138 my $caller = caller(); 139 my ($name, %args) = @_; 140 141 my $meta = $caller->meta; 142 my $metaclass = 'MooseX::DOM::Meta::LibXML::Attribute::Attribute'; 143 144 my $attr = Moose::Meta::Attribute->interpolate_class_and_new( 145 $name, 146 metaclass => $metaclass, 147 is => 'rw', 148 accessor => $name, 149 %args, 150 ); 151 $meta->add_attribute( $attr ); 152 }); 153 }, 154 has_dom_children => sub { 155 return Class::MOP::subname($subname->('has_dom_children') => sub ($;%) { 156 my ($name, %args) = @_; 157 my $caller = caller(); 158 my $meta = $caller->meta; 159 my $metaclass = 'MooseX::DOM::Meta::LibXML::Attribute::Element'; 160 my $attr = Moose::Meta::Attribute->interpolate_class_and_new( 161 $name, 162 metaclass => $metaclass, 163 is => 'rw', 164 accessor => $name, 165 tag => $name, 166 create => $text2elements, 167 filter => $textfilter, 168 %args, 169 ); 170 $meta->add_attribute( $attr ); 171 }); 172 }, 173 has_dom_child => sub { 174 return Class::MOP::subname($subname->('has_dom_child') => sub ($;%) { 175 my ($name, %args) = @_; 176 my $caller = caller(); 177 my $meta = $caller->meta; 178 my $metaclass = 'MooseX::DOM::Meta::LibXML::Attribute::Element'; 179 my $attr = Moose::Meta::Attribute->interpolate_class_and_new( 180 $name, 181 metaclass => $metaclass, 182 is => 'rw', 183 accessor => $name, 184 tag => $name, 185 create => $text2elements, 186 filter => $textfilter, 187 single => 1, 188 %args, 189 ); 190 $meta->add_attribute( $attr ); 191 }); 192 } 193 ); 194 195 my $export = Sub::Exporter::build_exporter({ 196 exports => \%exports, 197 groups => { default => [ ':all' ] } 198 }); 199 sub export_dsl { 200 goto &$export if $export; 201 } 202 203 sub unexport_dsl { 204 no strict 'refs'; 205 my $class = caller(); 206 207 # loop through the exports ... 208 foreach my $name ( keys %exports ) { 209 210 # if we find one ... 211 if ( defined &{ $class . '::' . $name } ) { 212 my $keyword = \&{ $class . '::' . $name }; 213 214 # make sure it is from Moose 215 my ($pkg_name) = Class::MOP::get_code_info($keyword); 216 next if $pkg_name ne __PACKAGE__; 217 218 # and if it is from Moose then undef the slot 219 delete ${ $class . '::' }{$name}; 220 } 221 } 54 foreach my $method (@METHODS) { 55 my $attr = "${method}_method"; 56 $meta->add_method($method => $self->$attr); 222 57 } 223 58 } 224 59 225 sub from_xml { 226 my $class = shift; 227 return $class->new(node => XML::LibXML->new->parse_string($_[0])->documentElement); 228 } 229 sub from_file { 230 my $class = shift; 231 return $class->new(node => XML::LibXML->new->parse_file($_[0])->documentElement); 60 sub build_dom_root_attr { 61 Moose::Meta::Attribute->new( 62 dom_root => ( 63 is => 'rw', 64 isa => 'MooseX::DOM::LibXML::XPathContext', 65 coerce => 1, 66 ) 67 ) 232 68 } 233 69 234 sub as_xml{70 sub build_parse_file_method { 235 71 my $self = shift; 236 $self->node->toString(1); 72 return Moose::Meta::Method->wrap( 73 package_name => Scalar::Util::blessed $self, 74 name => 'parse_file', 75 body => sub { 76 my ($class, $file) = @_; 77 $class->new(dom_root => XML::LibXML->new->parse_file($file)); 78 } 79 ); 237 80 } 238 81 82 sub build_parse_string_method { 83 my $self = shift; 84 return Moose::Meta::Method->wrap( 85 package_name => Scalar::Util::blessed $self, 86 name => 'parse_string', 87 body => sub { 88 my ($class, $string) = @_; 89 $class->new(dom_root => XML::LibXML->new->parse_string($string)); 90 } 91 ); 92 } 93 94 sub build_dom_findvalue_method { 95 my $self = shift; 96 return Moose::Meta::Method->wrap( 97 package_name => Scalar::Util::blessed $self, 98 name => 'dom_findvalue', 99 body => sub { 100 my ($self, $args) = @_; 101 if (! ref $args) { 102 $args = { xpath => $args }; 103 } 104 $self->dom_root->findvalue($args->{xpath}); 105 } 106 ); 107 } 108 109 sub build_dom_findnodes_method { 110 my $self = shift; 111 return Moose::Meta::Method->wrap( 112 package_name => Scalar::Util::blessed $self, 113 name => 'dom_findnodes', 114 body => sub { 115 my ($self, $args) = @_; 116 if (! ref $args) { 117 $args = { xpath => $args }; 118 } 119 $self->dom_root->findnodes($args->{xpath}); 120 } 121 ); 122 } 239 123 240 124 1; 241
![(please configure the [header_logo] section in trac.ini)](/share/chrome/site/your_project_logo.png)