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