1Mojo::DOM(3) User Contributed Perl Documentation Mojo::DOM(3)
2
3
4
6 Mojo::DOM - Minimalistic HTML/XML DOM parser with CSS selectors
7
9 use Mojo::DOM;
10
11 # Parse
12 my $dom = Mojo::DOM->new('<div><p id="a">Test</p><p id="b">123</p></div>');
13
14 # Find
15 say $dom->at('#b')->text;
16 say $dom->find('p')->map('text')->join("\n");
17 say $dom->find('[id]')->map(attr => 'id')->join("\n");
18
19 # Iterate
20 $dom->find('p[id]')->reverse->each(sub { say $_->{id} });
21
22 # Loop
23 for my $e ($dom->find('p[id]')->each) {
24 say $e->{id}, ':', $e->text;
25 }
26
27 # Modify
28 $dom->find('div p')->last->append('<p id="c">456</p>');
29 $dom->at('#c')->prepend($dom->new_tag('p', id => 'd', '789'));
30 $dom->find(':not(p)')->map('strip');
31
32 # Render
33 say "$dom";
34
36 Mojo::DOM is a minimalistic and relaxed HTML/XML DOM parser with CSS
37 selector support. It will even try to interpret broken HTML and XML, so
38 you should not use it for validation.
39
41 When we parse an HTML/XML fragment, it gets turned into a tree of
42 nodes.
43
44 <!DOCTYPE html>
45 <html>
46 <head><title>Hello</title></head>
47 <body>World!</body>
48 </html>
49
50 There are currently eight different kinds of nodes, "cdata", "comment",
51 "doctype", "pi", "raw", "root", "tag" and "text". Elements are nodes of
52 the type "tag".
53
54 root
55 |- doctype (html)
56 +- tag (html)
57 |- tag (head)
58 | +- tag (title)
59 | +- raw (Hello)
60 +- tag (body)
61 +- text (World!)
62
63 While all node types are represented as Mojo::DOM objects, some methods
64 like "attr" and "namespace" only apply to elements.
65
67 Mojo::DOM defaults to HTML semantics, that means all tags and attribute
68 names are lowercased and selectors need to be lowercase as well.
69
70 # HTML semantics
71 my $dom = Mojo::DOM->new('<P ID="greeting">Hi!</P>');
72 say $dom->at('p[id]')->text;
73
74 If an XML declaration is found, the parser will automatically switch
75 into XML mode and everything becomes case-sensitive.
76
77 # XML semantics
78 my $dom = Mojo::DOM->new('<?xml version="1.0"?><P ID="greeting">Hi!</P>');
79 say $dom->at('P[ID]')->text;
80
81 HTML or XML semantics can also be forced with the "xml" method.
82
83 # Force HTML semantics
84 my $dom = Mojo::DOM->new->xml(0)->parse('<P ID="greeting">Hi!</P>');
85 say $dom->at('p[id]')->text;
86
87 # Force XML semantics
88 my $dom = Mojo::DOM->new->xml(1)->parse('<P ID="greeting">Hi!</P>');
89 say $dom->at('P[ID]')->text;
90
92 Mojo::DOM implements the following methods.
93
94 all_text
95 my $text = $dom->all_text;
96
97 Extract text content from all descendant nodes of this element. For
98 HTML documents "script" and "style" elements are excluded.
99
100 # "foo\nbarbaz\n"
101 $dom->parse("<div>foo\n<p>bar</p>baz\n</div>")->at('div')->all_text;
102
103 ancestors
104 my $collection = $dom->ancestors;
105 my $collection = $dom->ancestors('div ~ p');
106
107 Find all ancestor elements of this node matching the CSS selector and
108 return a Mojo::Collection object containing these elements as Mojo::DOM
109 objects. All selectors from "SELECTORS" in Mojo::DOM::CSS are
110 supported.
111
112 # List tag names of ancestor elements
113 say $dom->ancestors->map('tag')->join("\n");
114
115 append
116 $dom = $dom->append('<p>I ♥ Mojolicious!</p>');
117 $dom = $dom->append(Mojo::DOM->new);
118
119 Append HTML/XML fragment to this node (for all node types other than
120 "root").
121
122 # "<div><h1>Test</h1><h2>123</h2></div>"
123 $dom->parse('<div><h1>Test</h1></div>')
124 ->at('h1')->append('<h2>123</h2>')->root;
125
126 # "<p>Test 123</p>"
127 $dom->parse('<p>Test</p>')->at('p')
128 ->child_nodes->first->append(' 123')->root;
129
130 append_content
131 $dom = $dom->append_content('<p>I ♥ Mojolicious!</p>');
132 $dom = $dom->append_content(Mojo::DOM->new);
133
134 Append HTML/XML fragment (for "root" and "tag" nodes) or raw content to
135 this node's content.
136
137 # "<div><h1>Test123</h1></div>"
138 $dom->parse('<div><h1>Test</h1></div>')
139 ->at('h1')->append_content('123')->root;
140
141 # "<!-- Test 123 --><br>"
142 $dom->parse('<!-- Test --><br>')
143 ->child_nodes->first->append_content('123 ')->root;
144
145 # "<p>Test<i>123</i></p>"
146 $dom->parse('<p>Test</p>')->at('p')->append_content('<i>123</i>')->root;
147
148 at
149 my $result = $dom->at('div ~ p');
150 my $result = $dom->at('svg|line', svg => 'http://www.w3.org/2000/svg');
151
152 Find first descendant element of this element matching the CSS selector
153 and return it as a Mojo::DOM object, or "undef" if none could be found.
154 All selectors from "SELECTORS" in Mojo::DOM::CSS are supported.
155
156 # Find first element with "svg" namespace definition
157 my $namespace = $dom->at('[xmlns\:svg]')->{'xmlns:svg'};
158
159 Trailing key/value pairs can be used to declare xml namespace aliases.
160
161 # "<rect />"
162 $dom->parse('<svg xmlns="http://www.w3.org/2000/svg"><rect /></svg>')
163 ->at('svg|rect', svg => 'http://www.w3.org/2000/svg');
164
165 attr
166 my $hash = $dom->attr;
167 my $foo = $dom->attr('foo');
168 $dom = $dom->attr({foo => 'bar'});
169 $dom = $dom->attr(foo => 'bar');
170
171 This element's attributes.
172
173 # Remove an attribute
174 delete $dom->attr->{id};
175
176 # Attribute without value
177 $dom->attr(selected => undef);
178
179 # List id attributes
180 say $dom->find('*')->map(attr => 'id')->compact->join("\n");
181
182 child_nodes
183 my $collection = $dom->child_nodes;
184
185 Return a Mojo::Collection object containing all child nodes of this
186 element as Mojo::DOM objects.
187
188 # "<p><b>123</b></p>"
189 $dom->parse('<p>Test<b>123</b></p>')->at('p')->child_nodes->first->remove;
190
191 # "<!DOCTYPE html>"
192 $dom->parse('<!DOCTYPE html><b>123</b>')->child_nodes->first;
193
194 # " Test "
195 $dom->parse('<b>123</b><!-- Test -->')->child_nodes->last->content;
196
197 children
198 my $collection = $dom->children;
199 my $collection = $dom->children('div ~ p');
200
201 Find all child elements of this element matching the CSS selector and
202 return a Mojo::Collection object containing these elements as Mojo::DOM
203 objects. All selectors from "SELECTORS" in Mojo::DOM::CSS are
204 supported.
205
206 # Show tag name of random child element
207 say $dom->children->shuffle->first->tag;
208
209 content
210 my $str = $dom->content;
211 $dom = $dom->content('<p>I ♥ Mojolicious!</p>');
212 $dom = $dom->content(Mojo::DOM->new);
213
214 Return this node's content or replace it with HTML/XML fragment (for
215 "root" and "tag" nodes) or raw content.
216
217 # "<b>Test</b>"
218 $dom->parse('<div><b>Test</b></div>')->at('div')->content;
219
220 # "<div><h1>123</h1></div>"
221 $dom->parse('<div><h1>Test</h1></div>')->at('h1')->content('123')->root;
222
223 # "<p><i>123</i></p>"
224 $dom->parse('<p>Test</p>')->at('p')->content('<i>123</i>')->root;
225
226 # "<div><h1></h1></div>"
227 $dom->parse('<div><h1>Test</h1></div>')->at('h1')->content('')->root;
228
229 # " Test "
230 $dom->parse('<!-- Test --><br>')->child_nodes->first->content;
231
232 # "<div><!-- 123 -->456</div>"
233 $dom->parse('<div><!-- Test -->456</div>')
234 ->at('div')->child_nodes->first->content(' 123 ')->root;
235
236 descendant_nodes
237 my $collection = $dom->descendant_nodes;
238
239 Return a Mojo::Collection object containing all descendant nodes of
240 this element as Mojo::DOM objects.
241
242 # "<p><b>123</b></p>"
243 $dom->parse('<p><!-- Test --><b>123<!-- 456 --></b></p>')
244 ->descendant_nodes->grep(sub { $_->type eq 'comment' })
245 ->map('remove')->first;
246
247 # "<p><b>test</b>test</p>"
248 $dom->parse('<p><b>123</b>456</p>')
249 ->at('p')->descendant_nodes->grep(sub { $_->type eq 'text' })
250 ->map(content => 'test')->first->root;
251
252 find
253 my $collection = $dom->find('div ~ p');
254 my $collection = $dom->find('svg|line', svg => 'http://www.w3.org/2000/svg');
255
256 Find all descendant elements of this element matching the CSS selector
257 and return a Mojo::Collection object containing these elements as
258 Mojo::DOM objects. All selectors from "SELECTORS" in Mojo::DOM::CSS are
259 supported.
260
261 # Find a specific element and extract information
262 my $id = $dom->find('div')->[23]{id};
263
264 # Extract information from multiple elements
265 my @headers = $dom->find('h1, h2, h3')->map('text')->each;
266
267 # Count all the different tags
268 my $hash = $dom->find('*')->reduce(sub { $a->{$b->tag}++; $a }, {});
269
270 # Find elements with a class that contains dots
271 my @divs = $dom->find('div.foo\.bar')->each;
272
273 Trailing key/value pairs can be used to declare xml namespace aliases.
274
275 # "<rect />"
276 $dom->parse('<svg xmlns="http://www.w3.org/2000/svg"><rect /></svg>')
277 ->find('svg|rect', svg => 'http://www.w3.org/2000/svg')->first;
278
279 following
280 my $collection = $dom->following;
281 my $collection = $dom->following('div ~ p');
282
283 Find all sibling elements after this node matching the CSS selector and
284 return a Mojo::Collection object containing these elements as Mojo::DOM
285 objects. All selectors from "SELECTORS" in Mojo::DOM::CSS are
286 supported.
287
288 # List tags of sibling elements after this node
289 say $dom->following->map('tag')->join("\n");
290
291 following_nodes
292 my $collection = $dom->following_nodes;
293
294 Return a Mojo::Collection object containing all sibling nodes after
295 this node as Mojo::DOM objects.
296
297 # "C"
298 $dom->parse('<p>A</p><!-- B -->C')->at('p')->following_nodes->last->content;
299
300 matches
301 my $bool = $dom->matches('div ~ p');
302 my $bool = $dom->matches('svg|line', svg => 'http://www.w3.org/2000/svg');
303
304 Check if this element matches the CSS selector. All selectors from
305 "SELECTORS" in Mojo::DOM::CSS are supported.
306
307 # True
308 $dom->parse('<p class="a">A</p>')->at('p')->matches('.a');
309 $dom->parse('<p class="a">A</p>')->at('p')->matches('p[class]');
310
311 # False
312 $dom->parse('<p class="a">A</p>')->at('p')->matches('.b');
313 $dom->parse('<p class="a">A</p>')->at('p')->matches('p[id]');
314
315 Trailing key/value pairs can be used to declare xml namespace aliases.
316
317 # True
318 $dom->parse('<svg xmlns="http://www.w3.org/2000/svg"><rect /></svg>')
319 ->matches('svg|rect', svg => 'http://www.w3.org/2000/svg');
320
321 namespace
322 my $namespace = $dom->namespace;
323
324 Find this element's namespace, or return "undef" if none could be
325 found.
326
327 # "http://www.w3.org/2000/svg"
328 Mojo::DOM->new('<svg xmlns:svg="http://www.w3.org/2000/svg"><svg:circle>3.14</svg:circle></svg>')->at('svg\:circle')->namespace;
329
330 # Find namespace for an element with namespace prefix
331 my $namespace = $dom->at('svg > svg\:circle')->namespace;
332
333 # Find namespace for an element that may or may not have a namespace prefix
334 my $namespace = $dom->at('svg > circle')->namespace;
335
336 new
337 my $dom = Mojo::DOM->new;
338 my $dom = Mojo::DOM->new('<foo bar="baz">I ♥ Mojolicious!</foo>');
339
340 Construct a new scalar-based Mojo::DOM object and "parse" HTML/XML
341 fragment if necessary.
342
343 new_tag
344 my $tag = Mojo::DOM->new_tag('div');
345 my $tag = $dom->new_tag('div');
346 my $tag = $dom->new_tag('div', id => 'foo', hidden => undef);
347 my $tag = $dom->new_tag('div', 'safe content');
348 my $tag = $dom->new_tag('div', id => 'foo', 'safe content');
349 my $tag = $dom->new_tag('div', data => {mojo => 'rocks'}, 'safe content');
350 my $tag = $dom->new_tag('div', id => 'foo', sub { 'unsafe content' });
351
352 Construct a new Mojo::DOM object for an HTML/XML tag with or without
353 attributes and content. The "data" attribute may contain a hash
354 reference with key/value pairs to generate attributes from.
355
356 # "<br>"
357 $dom->new_tag('br');
358
359 # "<div></div>"
360 $dom->new_tag('div');
361
362 # "<div id="foo" hidden></div>"
363 $dom->new_tag('div', id => 'foo', hidden => undef);
364
365 # "<div>test & 123</div>"
366 $dom->new_tag('div', 'test & 123');
367
368 # "<div id="foo">test & 123</div>"
369 $dom->new_tag('div', id => 'foo', 'test & 123');
370
371 # "<div data-foo="1" data-bar="test">test & 123</div>""
372 $dom->new_tag('div', data => {foo => 1, Bar => 'test'}, 'test & 123');
373
374 # "<div id="foo">test & 123</div>"
375 $dom->new_tag('div', id => 'foo', sub { 'test & 123' });
376
377 # "<div>Hello<b>Mojo!</b></div>"
378 $dom->parse('<div>Hello</div>')->at('div')
379 ->append_content($dom->new_tag('b', 'Mojo!'))->root;
380
381 next
382 my $sibling = $dom->next;
383
384 Return Mojo::DOM object for next sibling element, or "undef" if there
385 are no more siblings.
386
387 # "<h2>123</h2>"
388 $dom->parse('<div><h1>Test</h1><h2>123</h2></div>')->at('h1')->next;
389
390 next_node
391 my $sibling = $dom->next_node;
392
393 Return Mojo::DOM object for next sibling node, or "undef" if there are
394 no more siblings.
395
396 # "456"
397 $dom->parse('<p><b>123</b><!-- Test -->456</p>')
398 ->at('b')->next_node->next_node;
399
400 # " Test "
401 $dom->parse('<p><b>123</b><!-- Test -->456</p>')
402 ->at('b')->next_node->content;
403
404 parent
405 my $parent = $dom->parent;
406
407 Return Mojo::DOM object for parent of this node, or "undef" if this
408 node has no parent.
409
410 # "<b><i>Test</i></b>"
411 $dom->parse('<p><b><i>Test</i></b></p>')->at('i')->parent;
412
413 parse
414 $dom = $dom->parse('<foo bar="baz">I ♥ Mojolicious!</foo>');
415
416 Parse HTML/XML fragment with Mojo::DOM::HTML.
417
418 # Parse XML
419 my $dom = Mojo::DOM->new->xml(1)->parse('<foo>I ♥ Mojolicious!</foo>');
420
421 preceding
422 my $collection = $dom->preceding;
423 my $collection = $dom->preceding('div ~ p');
424
425 Find all sibling elements before this node matching the CSS selector
426 and return a Mojo::Collection object containing these elements as
427 Mojo::DOM objects. All selectors from "SELECTORS" in Mojo::DOM::CSS are
428 supported.
429
430 # List tags of sibling elements before this node
431 say $dom->preceding->map('tag')->join("\n");
432
433 preceding_nodes
434 my $collection = $dom->preceding_nodes;
435
436 Return a Mojo::Collection object containing all sibling nodes before
437 this node as Mojo::DOM objects.
438
439 # "A"
440 $dom->parse('A<!-- B --><p>C</p>')->at('p')->preceding_nodes->first->content;
441
442 prepend
443 $dom = $dom->prepend('<p>I ♥ Mojolicious!</p>');
444 $dom = $dom->prepend(Mojo::DOM->new);
445
446 Prepend HTML/XML fragment to this node (for all node types other than
447 "root").
448
449 # "<div><h1>Test</h1><h2>123</h2></div>"
450 $dom->parse('<div><h2>123</h2></div>')
451 ->at('h2')->prepend('<h1>Test</h1>')->root;
452
453 # "<p>Test 123</p>"
454 $dom->parse('<p>123</p>')
455 ->at('p')->child_nodes->first->prepend('Test ')->root;
456
457 prepend_content
458 $dom = $dom->prepend_content('<p>I ♥ Mojolicious!</p>');
459 $dom = $dom->prepend_content(Mojo::DOM->new);
460
461 Prepend HTML/XML fragment (for "root" and "tag" nodes) or raw content
462 to this node's content.
463
464 # "<div><h2>Test123</h2></div>"
465 $dom->parse('<div><h2>123</h2></div>')
466 ->at('h2')->prepend_content('Test')->root;
467
468 # "<!-- Test 123 --><br>"
469 $dom->parse('<!-- 123 --><br>')
470 ->child_nodes->first->prepend_content(' Test')->root;
471
472 # "<p><i>123</i>Test</p>"
473 $dom->parse('<p>Test</p>')->at('p')->prepend_content('<i>123</i>')->root;
474
475 previous
476 my $sibling = $dom->previous;
477
478 Return Mojo::DOM object for previous sibling element, or "undef" if
479 there are no more siblings.
480
481 # "<h1>Test</h1>"
482 $dom->parse('<div><h1>Test</h1><h2>123</h2></div>')->at('h2')->previous;
483
484 previous_node
485 my $sibling = $dom->previous_node;
486
487 Return Mojo::DOM object for previous sibling node, or "undef" if there
488 are no more siblings.
489
490 # "123"
491 $dom->parse('<p>123<!-- Test --><b>456</b></p>')
492 ->at('b')->previous_node->previous_node;
493
494 # " Test "
495 $dom->parse('<p>123<!-- Test --><b>456</b></p>')
496 ->at('b')->previous_node->content;
497
498 remove
499 my $parent = $dom->remove;
500
501 Remove this node and return "root" (for "root" nodes) or "parent".
502
503 # "<div></div>"
504 $dom->parse('<div><h1>Test</h1></div>')->at('h1')->remove;
505
506 # "<p><b>456</b></p>"
507 $dom->parse('<p>123<b>456</b></p>')
508 ->at('p')->child_nodes->first->remove->root;
509
510 replace
511 my $parent = $dom->replace('<div>I ♥ Mojolicious!</div>');
512 my $parent = $dom->replace(Mojo::DOM->new);
513
514 Replace this node with HTML/XML fragment and return "root" (for "root"
515 nodes) or "parent".
516
517 # "<div><h2>123</h2></div>"
518 $dom->parse('<div><h1>Test</h1></div>')->at('h1')->replace('<h2>123</h2>');
519
520 # "<p><b>123</b></p>"
521 $dom->parse('<p>Test</p>')
522 ->at('p')->child_nodes->[0]->replace('<b>123</b>')->root;
523
524 root
525 my $root = $dom->root;
526
527 Return Mojo::DOM object for "root" node.
528
529 selector
530 my $selector = $dom->selector;
531
532 Get a unique CSS selector for this element.
533
534 # "ul:nth-child(1) > li:nth-child(2)"
535 $dom->parse('<ul><li>Test</li><li>123</li></ul>')->find('li')->last->selector;
536
537 # "p:nth-child(1) > b:nth-child(1) > i:nth-child(1)"
538 $dom->parse('<p><b><i>Test</i></b></p>')->at('i')->selector;
539
540 strip
541 my $parent = $dom->strip;
542
543 Remove this element while preserving its content and return "parent".
544
545 # "<div>Test</div>"
546 $dom->parse('<div><h1>Test</h1></div>')->at('h1')->strip;
547
548 tag
549 my $tag = $dom->tag;
550 $dom = $dom->tag('div');
551
552 This element's tag name.
553
554 # List tag names of child elements
555 say $dom->children->map('tag')->join("\n");
556
557 tap
558 $dom = $dom->tap(sub {...});
559
560 Alias for "tap" in Mojo::Base.
561
562 text
563 my $text = $dom->text;
564
565 Extract text content from this element only (not including child
566 elements).
567
568 # "bar"
569 $dom->parse("<div>foo<p>bar</p>baz</div>")->at('p')->text;
570
571 # "foo\nbaz\n"
572 $dom->parse("<div>foo\n<p>bar</p>baz\n</div>")->at('div')->text;
573
574 To extract text content from all descendant nodes see "all_text".
575
576 to_string
577 my $str = $dom->to_string;
578
579 Render this node and its content to HTML/XML.
580
581 # "<b>Test</b>"
582 $dom->parse('<div><b>Test</b></div>')->at('div b')->to_string;
583
584 tree
585 my $tree = $dom->tree;
586 $dom = $dom->tree(['root']);
587
588 Document Object Model. Note that this structure should only be used
589 very carefully since it is very dynamic.
590
591 type
592 my $type = $dom->type;
593
594 This node's type, usually "cdata", "comment", "doctype", "pi", "raw",
595 "root", "tag" or "text".
596
597 # "cdata"
598 $dom->parse('<![CDATA[Test]]>')->child_nodes->first->type;
599
600 # "comment"
601 $dom->parse('<!-- Test -->')->child_nodes->first->type;
602
603 # "doctype"
604 $dom->parse('<!DOCTYPE html>')->child_nodes->first->type;
605
606 # "pi"
607 $dom->parse('<?xml version="1.0"?>')->child_nodes->first->type;
608
609 # "raw"
610 $dom->parse('<title>Test</title>')->at('title')->child_nodes->first->type;
611
612 # "root"
613 $dom->parse('<p>Test</p>')->type;
614
615 # "tag"
616 $dom->parse('<p>Test</p>')->at('p')->type;
617
618 # "text"
619 $dom->parse('<p>Test</p>')->at('p')->child_nodes->first->type;
620
621 val
622 my $value = $dom->val;
623
624 Extract value from form element (such as "button", "input", "option",
625 "select" and "textarea"), or return "undef" if this element has no
626 value. In the case of "select" with "multiple" attribute, find "option"
627 elements with "selected" attribute and return an array reference with
628 all values, or "undef" if none could be found.
629
630 # "a"
631 $dom->parse('<input name=test value=a>')->at('input')->val;
632
633 # "b"
634 $dom->parse('<textarea>b</textarea>')->at('textarea')->val;
635
636 # "c"
637 $dom->parse('<option value="c">Test</option>')->at('option')->val;
638
639 # "d"
640 $dom->parse('<select><option selected>d</option></select>')
641 ->at('select')->val;
642
643 # "e"
644 $dom->parse('<select multiple><option selected>e</option></select>')
645 ->at('select')->val->[0];
646
647 # "on"
648 $dom->parse('<input name=test type=checkbox>')->at('input')->val;
649
650 with_roles
651 my $new_class = Mojo::DOM->with_roles('Mojo::DOM::Role::One');
652 my $new_class = Mojo::DOM->with_roles('+One', '+Two');
653 $dom = $dom->with_roles('+One', '+Two');
654
655 Alias for "with_roles" in Mojo::Base.
656
657 wrap
658 $dom = $dom->wrap('<div></div>');
659 $dom = $dom->wrap(Mojo::DOM->new);
660
661 Wrap HTML/XML fragment around this node (for all node types other than
662 "root"), placing it as the last child of the first innermost element.
663
664 # "<p>123<b>Test</b></p>"
665 $dom->parse('<b>Test</b>')->at('b')->wrap('<p>123</p>')->root;
666
667 # "<div><p><b>Test</b></p>123</div>"
668 $dom->parse('<b>Test</b>')->at('b')->wrap('<div><p></p>123</div>')->root;
669
670 # "<p><b>Test</b></p><p>123</p>"
671 $dom->parse('<b>Test</b>')->at('b')->wrap('<p></p><p>123</p>')->root;
672
673 # "<p><b>Test</b></p>"
674 $dom->parse('<p>Test</p>')->at('p')->child_nodes->first->wrap('<b>')->root;
675
676 wrap_content
677 $dom = $dom->wrap_content('<div></div>');
678 $dom = $dom->wrap_content(Mojo::DOM->new);
679
680 Wrap HTML/XML fragment around this node's content (for "root" and "tag"
681 nodes), placing it as the last children of the first innermost element.
682
683 # "<p><b>123Test</b></p>"
684 $dom->parse('<p>Test<p>')->at('p')->wrap_content('<b>123</b>')->root;
685
686 # "<p><b>Test</b></p><p>123</p>"
687 $dom->parse('<b>Test</b>')->wrap_content('<p></p><p>123</p>');
688
689 xml
690 my $bool = $dom->xml;
691 $dom = $dom->xml($bool);
692
693 Disable HTML semantics in parser and activate case-sensitivity,
694 defaults to auto-detection based on XML declarations.
695
697 Mojo::DOM overloads the following operators.
698
699 array
700 my @nodes = @$dom;
701
702 Alias for "child_nodes".
703
704 # "<!-- Test -->"
705 $dom->parse('<!-- Test --><b>123</b>')->[0];
706
707 bool
708 my $bool = !!$dom;
709
710 Always true.
711
712 hash
713 my %attrs = %$dom;
714
715 Alias for "attr".
716
717 # "test"
718 $dom->parse('<div id="test">Test</div>')->at('div')->{id};
719
720 stringify
721 my $str = "$dom";
722
723 Alias for "to_string".
724
726 Mojolicious, Mojolicious::Guides, <https://mojolicious.org>.
727
728
729
730perl v5.36.0 2023-01-20 Mojo::DOM(3)