.\" Automatically generated by Pod::Man 4.10 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Mojo::DOM 3pm" .TH Mojo::DOM 3pm "2019-02-05" "perl v5.28.1" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Mojo::DOM \- Minimalistic HTML/XML DOM parser with CSS selectors .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use Mojo::DOM; \& \& # Parse \& my $dom = Mojo::DOM\->new(\*(Aq

Test

123

\*(Aq); \& \& # Find \& say $dom\->at(\*(Aq#b\*(Aq)\->text; \& say $dom\->find(\*(Aqp\*(Aq)\->map(\*(Aqtext\*(Aq)\->join("\en"); \& say $dom\->find(\*(Aq[id]\*(Aq)\->map(attr => \*(Aqid\*(Aq)\->join("\en"); \& \& # Iterate \& $dom\->find(\*(Aqp[id]\*(Aq)\->reverse\->each(sub { say $_\->{id} }); \& \& # Loop \& for my $e ($dom\->find(\*(Aqp[id]\*(Aq)\->each) { \& say $e\->{id}, \*(Aq:\*(Aq, $e\->text; \& } \& \& # Modify \& $dom\->find(\*(Aqdiv p\*(Aq)\->last\->append(\*(Aq

456

\*(Aq); \& $dom\->at(\*(Aq#c\*(Aq)\->prepend($dom\->new_tag(\*(Aqp\*(Aq, id => \*(Aqd\*(Aq, \*(Aq789\*(Aq)); \& $dom\->find(\*(Aq:not(p)\*(Aq)\->map(\*(Aqstrip\*(Aq); \& \& # Render \& say "$dom"; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Mojo::DOM is a minimalistic and relaxed \s-1HTML/XML DOM\s0 parser with \s-1CSS\s0 selector support. It will even try to interpret broken \s-1HTML\s0 and \s-1XML,\s0 so you should not use it for validation. .SH "NODES AND ELEMENTS" .IX Header "NODES AND ELEMENTS" When we parse an \s-1HTML/XML\s0 fragment, it gets turned into a tree of nodes. .PP .Vb 5 \& \& \& Hello \& World! \& .Ve .PP There are currently eight different kinds of nodes, \f(CW\*(C`cdata\*(C'\fR, \f(CW\*(C`comment\*(C'\fR, \&\f(CW\*(C`doctype\*(C'\fR, \f(CW\*(C`pi\*(C'\fR, \f(CW\*(C`raw\*(C'\fR, \f(CW\*(C`root\*(C'\fR, \f(CW\*(C`tag\*(C'\fR and \f(CW\*(C`text\*(C'\fR. Elements are nodes of the type \f(CW\*(C`tag\*(C'\fR. .PP .Vb 8 \& root \& |\- doctype (html) \& +\- tag (html) \& |\- tag (head) \& | +\- tag (title) \& | +\- raw (Hello) \& +\- tag (body) \& +\- text (World!) .Ve .PP While all node types are represented as Mojo::DOM objects, some methods like \&\*(L"attr\*(R" and \*(L"namespace\*(R" only apply to elements. .SH "CASE-SENSITIVITY" .IX Header "CASE-SENSITIVITY" Mojo::DOM defaults to \s-1HTML\s0 semantics, that means all tags and attribute names are lowercased and selectors need to be lowercase as well. .PP .Vb 3 \& # HTML semantics \& my $dom = Mojo::DOM\->new(\*(Aq

Hi!

\*(Aq); \& say $dom\->at(\*(Aqp[id]\*(Aq)\->text; .Ve .PP If an \s-1XML\s0 declaration is found, the parser will automatically switch into \s-1XML\s0 mode and everything becomes case-sensitive. .PP .Vb 3 \& # XML semantics \& my $dom = Mojo::DOM\->new(\*(Aq

Hi!

\*(Aq); \& say $dom\->at(\*(AqP[ID]\*(Aq)\->text; .Ve .PP \&\s-1HTML\s0 or \s-1XML\s0 semantics can also be forced with the \*(L"xml\*(R" method. .PP .Vb 3 \& # Force HTML semantics \& my $dom = Mojo::DOM\->new\->xml(0)\->parse(\*(Aq

Hi!

\*(Aq); \& say $dom\->at(\*(Aqp[id]\*(Aq)\->text; \& \& # Force XML semantics \& my $dom = Mojo::DOM\->new\->xml(1)\->parse(\*(Aq

Hi!

\*(Aq); \& say $dom\->at(\*(AqP[ID]\*(Aq)\->text; .Ve .SH "METHODS" .IX Header "METHODS" Mojo::DOM implements the following methods. .SS "all_text" .IX Subsection "all_text" .Vb 1 \& my $text = $dom\->all_text; .Ve .PP Extract text content from all descendant nodes of this element. .PP .Vb 2 \& # "foo\enbarbaz\en" \& $dom\->parse("
foo\en

bar

baz\en
")\->at(\*(Aqdiv\*(Aq)\->all_text; .Ve .SS "ancestors" .IX Subsection "ancestors" .Vb 2 \& my $collection = $dom\->ancestors; \& my $collection = $dom\->ancestors(\*(Aqdiv ~ p\*(Aq); .Ve .PP Find all ancestor elements of this node matching the \s-1CSS\s0 selector and return a Mojo::Collection object containing these elements as Mojo::DOM objects. All selectors from \*(L"\s-1SELECTORS\*(R"\s0 in Mojo::DOM::CSS are supported. .PP .Vb 2 \& # List tag names of ancestor elements \& say $dom\->ancestors\->map(\*(Aqtag\*(Aq)\->join("\en"); .Ve .SS "append" .IX Subsection "append" .Vb 2 \& $dom = $dom\->append(\*(Aq

I ♥ Mojolicious!

\*(Aq); \& $dom = $dom\->append(Mojo::DOM\->new); .Ve .PP Append \s-1HTML/XML\s0 fragment to this node (for all node types other than \f(CW\*(C`root\*(C'\fR). .PP .Vb 3 \& # "

Test

123

" \& $dom\->parse(\*(Aq

Test

\*(Aq) \& \->at(\*(Aqh1\*(Aq)\->append(\*(Aq

123

\*(Aq)\->root; \& \& # "

Test 123

" \& $dom\->parse(\*(Aq

Test

\*(Aq)\->at(\*(Aqp\*(Aq) \& \->child_nodes\->first\->append(\*(Aq 123\*(Aq)\->root; .Ve .SS "append_content" .IX Subsection "append_content" .Vb 2 \& $dom = $dom\->append_content(\*(Aq

I ♥ Mojolicious!

\*(Aq); \& $dom = $dom\->append_content(Mojo::DOM\->new); .Ve .PP Append \s-1HTML/XML\s0 fragment (for \f(CW\*(C`root\*(C'\fR and \f(CW\*(C`tag\*(C'\fR nodes) or raw content to this node's content. .PP .Vb 3 \& # "

Test123

" \& $dom\->parse(\*(Aq

Test

\*(Aq) \& \->at(\*(Aqh1\*(Aq)\->append_content(\*(Aq123\*(Aq)\->root; \& \& # "
" \& $dom\->parse(\*(Aq
\*(Aq) \& \->child_nodes\->first\->append_content(\*(Aq123 \*(Aq)\->root; \& \& # "

Test123

" \& $dom\->parse(\*(Aq

Test

\*(Aq)\->at(\*(Aqp\*(Aq)\->append_content(\*(Aq123\*(Aq)\->root; .Ve .SS "at" .IX Subsection "at" .Vb 2 \& my $result = $dom\->at(\*(Aqdiv ~ p\*(Aq); \& my $result = $dom\->at(\*(Aqsvg|line\*(Aq, svg => \*(Aqhttp://www.w3.org/2000/svg\*(Aq); .Ve .PP Find first descendant element of this element matching the \s-1CSS\s0 selector and return it as a Mojo::DOM object, or \f(CW\*(C`undef\*(C'\fR if none could be found. All selectors from \*(L"\s-1SELECTORS\*(R"\s0 in Mojo::DOM::CSS are supported. .PP .Vb 2 \& # Find first element with "svg" namespace definition \& my $namespace = $dom\->at(\*(Aq[xmlns\e:svg]\*(Aq)\->{\*(Aqxmlns:svg\*(Aq}; .Ve .PP Trailing key/value pairs can be used to declare xml namespace aliases. .PP .Vb 3 \& # "" \& $dom\->parse(\*(Aq\*(Aq) \& \->at(\*(Aqsvg|rect\*(Aq, svg => \*(Aqhttp://www.w3.org/2000/svg\*(Aq); .Ve .SS "attr" .IX Subsection "attr" .Vb 4 \& my $hash = $dom\->attr; \& my $foo = $dom\->attr(\*(Aqfoo\*(Aq); \& $dom = $dom\->attr({foo => \*(Aqbar\*(Aq}); \& $dom = $dom\->attr(foo => \*(Aqbar\*(Aq); .Ve .PP This element's attributes. .PP .Vb 2 \& # Remove an attribute \& delete $dom\->attr\->{id}; \& \& # Attribute without value \& $dom\->attr(selected => undef); \& \& # List id attributes \& say $dom\->find(\*(Aq*\*(Aq)\->map(attr => \*(Aqid\*(Aq)\->compact\->join("\en"); .Ve .SS "child_nodes" .IX Subsection "child_nodes" .Vb 1 \& my $collection = $dom\->child_nodes; .Ve .PP Return a Mojo::Collection object containing all child nodes of this element as Mojo::DOM objects. .PP .Vb 2 \& # "

123

" \& $dom\->parse(\*(Aq

Test123

\*(Aq)\->at(\*(Aqp\*(Aq)\->child_nodes\->first\->remove; \& \& # "" \& $dom\->parse(\*(Aq123\*(Aq)\->child_nodes\->first; \& \& # " Test " \& $dom\->parse(\*(Aq123\*(Aq)\->child_nodes\->last\->content; .Ve .SS "children" .IX Subsection "children" .Vb 2 \& my $collection = $dom\->children; \& my $collection = $dom\->children(\*(Aqdiv ~ p\*(Aq); .Ve .PP Find all child elements of this element matching the \s-1CSS\s0 selector and return a Mojo::Collection object containing these elements as Mojo::DOM objects. All selectors from \*(L"\s-1SELECTORS\*(R"\s0 in Mojo::DOM::CSS are supported. .PP .Vb 2 \& # Show tag name of random child element \& say $dom\->children\->shuffle\->first\->tag; .Ve .SS "content" .IX Subsection "content" .Vb 3 \& my $str = $dom\->content; \& $dom = $dom\->content(\*(Aq

I ♥ Mojolicious!

\*(Aq); \& $dom = $dom\->content(Mojo::DOM\->new); .Ve .PP Return this node's content or replace it with \s-1HTML/XML\s0 fragment (for \f(CW\*(C`root\*(C'\fR and \f(CW\*(C`tag\*(C'\fR nodes) or raw content. .PP .Vb 2 \& # "Test" \& $dom\->parse(\*(Aq
Test
\*(Aq)\->at(\*(Aqdiv\*(Aq)\->content; \& \& # "

123

" \& $dom\->parse(\*(Aq

Test

\*(Aq)\->at(\*(Aqh1\*(Aq)\->content(\*(Aq123\*(Aq)\->root; \& \& # "

123

" \& $dom\->parse(\*(Aq

Test

\*(Aq)\->at(\*(Aqp\*(Aq)\->content(\*(Aq123\*(Aq)\->root; \& \& # "

" \& $dom\->parse(\*(Aq

Test

\*(Aq)\->at(\*(Aqh1\*(Aq)\->content(\*(Aq\*(Aq)\->root; \& \& # " Test " \& $dom\->parse(\*(Aq
\*(Aq)\->child_nodes\->first\->content; \& \& # "
456
" \& $dom\->parse(\*(Aq
456
\*(Aq) \& \->at(\*(Aqdiv\*(Aq)\->child_nodes\->first\->content(\*(Aq 123 \*(Aq)\->root; .Ve .SS "descendant_nodes" .IX Subsection "descendant_nodes" .Vb 1 \& my $collection = $dom\->descendant_nodes; .Ve .PP Return a Mojo::Collection object containing all descendant nodes of this element as Mojo::DOM objects. .PP .Vb 4 \& # "

123

" \& $dom\->parse(\*(Aq

123

\*(Aq) \& \->descendant_nodes\->grep(sub { $_\->type eq \*(Aqcomment\*(Aq }) \& \->map(\*(Aqremove\*(Aq)\->first; \& \& # "

testtest

" \& $dom\->parse(\*(Aq

123456

\*(Aq) \& \->at(\*(Aqp\*(Aq)\->descendant_nodes\->grep(sub { $_\->type eq \*(Aqtext\*(Aq }) \& \->map(content => \*(Aqtest\*(Aq)\->first\->root; .Ve .SS "find" .IX Subsection "find" .Vb 2 \& my $collection = $dom\->find(\*(Aqdiv ~ p\*(Aq); \& my $collection = $dom\->find(\*(Aqsvg|line\*(Aq, svg => \*(Aqhttp://www.w3.org/2000/svg\*(Aq); .Ve .PP Find all descendant elements of this element matching the \s-1CSS\s0 selector and return a Mojo::Collection object containing these elements as Mojo::DOM objects. All selectors from \*(L"\s-1SELECTORS\*(R"\s0 in Mojo::DOM::CSS are supported. .PP .Vb 2 \& # Find a specific element and extract information \& my $id = $dom\->find(\*(Aqdiv\*(Aq)\->[23]{id}; \& \& # Extract information from multiple elements \& my @headers = $dom\->find(\*(Aqh1, h2, h3\*(Aq)\->map(\*(Aqtext\*(Aq)\->each; \& \& # Count all the different tags \& my $hash = $dom\->find(\*(Aq*\*(Aq)\->reduce(sub { $a\->{$b\->tag}++; $a }, {}); \& \& # Find elements with a class that contains dots \& my @divs = $dom\->find(\*(Aqdiv.foo\e.bar\*(Aq)\->each; .Ve .PP Trailing key/value pairs can be used to declare xml namespace aliases. .PP .Vb 3 \& # "" \& $dom\->parse(\*(Aq\*(Aq) \& \->find(\*(Aqsvg|rect\*(Aq, svg => \*(Aqhttp://www.w3.org/2000/svg\*(Aq)\->first; .Ve .SS "following" .IX Subsection "following" .Vb 2 \& my $collection = $dom\->following; \& my $collection = $dom\->following(\*(Aqdiv ~ p\*(Aq); .Ve .PP Find all sibling elements after this node matching the \s-1CSS\s0 selector and return a Mojo::Collection object containing these elements as Mojo::DOM objects. All selectors from \*(L"\s-1SELECTORS\*(R"\s0 in Mojo::DOM::CSS are supported. .PP .Vb 2 \& # List tags of sibling elements after this node \& say $dom\->following\->map(\*(Aqtag\*(Aq)\->join("\en"); .Ve .SS "following_nodes" .IX Subsection "following_nodes" .Vb 1 \& my $collection = $dom\->following_nodes; .Ve .PP Return a Mojo::Collection object containing all sibling nodes after this node as Mojo::DOM objects. .PP .Vb 2 \& # "C" \& $dom\->parse(\*(Aq

A

C\*(Aq)\->at(\*(Aqp\*(Aq)\->following_nodes\->last\->content; .Ve .SS "matches" .IX Subsection "matches" .Vb 2 \& my $bool = $dom\->matches(\*(Aqdiv ~ p\*(Aq); \& my $bool = $dom\->matches(\*(Aqsvg|line\*(Aq, svg => \*(Aqhttp://www.w3.org/2000/svg\*(Aq); .Ve .PP Check if this element matches the \s-1CSS\s0 selector. All selectors from \&\*(L"\s-1SELECTORS\*(R"\s0 in Mojo::DOM::CSS are supported. .PP .Vb 3 \& # True \& $dom\->parse(\*(Aq

A

\*(Aq)\->at(\*(Aqp\*(Aq)\->matches(\*(Aq.a\*(Aq); \& $dom\->parse(\*(Aq

A

\*(Aq)\->at(\*(Aqp\*(Aq)\->matches(\*(Aqp[class]\*(Aq); \& \& # False \& $dom\->parse(\*(Aq

A

\*(Aq)\->at(\*(Aqp\*(Aq)\->matches(\*(Aq.b\*(Aq); \& $dom\->parse(\*(Aq

A

\*(Aq)\->at(\*(Aqp\*(Aq)\->matches(\*(Aqp[id]\*(Aq); .Ve .PP Trailing key/value pairs can be used to declare xml namespace aliases. .PP .Vb 3 \& # True \& $dom\->parse(\*(Aq\*(Aq) \& \->matches(\*(Aqsvg|rect\*(Aq, svg => \*(Aqhttp://www.w3.org/2000/svg\*(Aq); .Ve .SS "namespace" .IX Subsection "namespace" .Vb 1 \& my $namespace = $dom\->namespace; .Ve .PP Find this element's namespace, or return \f(CW\*(C`undef\*(C'\fR if none could be found. .PP .Vb 2 \& # Find namespace for an element with namespace prefix \& my $namespace = $dom\->at(\*(Aqsvg > svg\e:circle\*(Aq)\->namespace; \& \& # Find namespace for an element that may or may not have a namespace prefix \& my $namespace = $dom\->at(\*(Aqsvg > circle\*(Aq)\->namespace; .Ve .SS "new" .IX Subsection "new" .Vb 2 \& my $dom = Mojo::DOM\->new; \& my $dom = Mojo::DOM\->new(\*(AqI ♥ Mojolicious!\*(Aq); .Ve .PP Construct a new scalar-based Mojo::DOM object and \*(L"parse\*(R" \s-1HTML/XML\s0 fragment if necessary. .SS "new_tag" .IX Subsection "new_tag" .Vb 7 \& my $tag = Mojo::DOM\->new_tag(\*(Aqdiv\*(Aq); \& my $tag = $dom\->new_tag(\*(Aqdiv\*(Aq); \& my $tag = $dom\->new_tag(\*(Aqdiv\*(Aq, id => \*(Aqfoo\*(Aq, hidden => undef); \& my $tag = $dom\->new_tag(\*(Aqdiv\*(Aq, \*(Aqsafe content\*(Aq); \& my $tag = $dom\->new_tag(\*(Aqdiv\*(Aq, id => \*(Aqfoo\*(Aq, \*(Aqsafe content\*(Aq); \& my $tag = $dom\->new_tag(\*(Aqdiv\*(Aq, data => {mojo => \*(Aqrocks\*(Aq}, \*(Aqsafe content\*(Aq); \& my $tag = $dom\->new_tag(\*(Aqdiv\*(Aq, id => \*(Aqfoo\*(Aq, sub { \*(Aqunsafe content\*(Aq }); .Ve .PP Construct a new Mojo::DOM object for an \s-1HTML/XML\s0 tag with or without attributes and content. The \f(CW\*(C`data\*(C'\fR attribute may contain a hash reference with key/value pairs to generate attributes from. .PP .Vb 2 \& # "
" \& $dom\->new_tag(\*(Aqbr\*(Aq); \& \& # "
" \& $dom\->new_tag(\*(Aqdiv\*(Aq); \& \& # "" \& $dom\->new_tag(\*(Aqdiv\*(Aq, id => \*(Aqfoo\*(Aq, hidden => undef); \& \& # "
test & 123
" \& $dom\->new_tag(\*(Aqdiv\*(Aq, \*(Aqtest & 123\*(Aq); \& \& # "
test & 123
" \& $dom\->new_tag(\*(Aqdiv\*(Aq, id => \*(Aqfoo\*(Aq, \*(Aqtest & 123\*(Aq); \& \& # "
test & 123
"" \& $dom\->new_tag(\*(Aqdiv\*(Aq, data => {foo => 1, Bar => \*(Aqtest\*(Aq}, \*(Aqtest & 123\*(Aq); \& \& # "
test & 123
" \& $dom\->new_tag(\*(Aqdiv\*(Aq, id => \*(Aqfoo\*(Aq, sub { \*(Aqtest & 123\*(Aq }); \& \& # "
HelloMojo!
" \& $dom\->parse(\*(Aq
Hello
\*(Aq)\->at(\*(Aqdiv\*(Aq) \& \->append_content($dom\->new_tag(\*(Aqb\*(Aq, \*(AqMojo!\*(Aq))\->root; .Ve .SS "next" .IX Subsection "next" .Vb 1 \& my $sibling = $dom\->next; .Ve .PP Return Mojo::DOM object for next sibling element, or \f(CW\*(C`undef\*(C'\fR if there are no more siblings. .PP .Vb 2 \& # "

123

" \& $dom\->parse(\*(Aq

Test

123

\*(Aq)\->at(\*(Aqh1\*(Aq)\->next; .Ve .SS "next_node" .IX Subsection "next_node" .Vb 1 \& my $sibling = $dom\->next_node; .Ve .PP Return Mojo::DOM object for next sibling node, or \f(CW\*(C`undef\*(C'\fR if there are no more siblings. .PP .Vb 3 \& # "456" \& $dom\->parse(\*(Aq

123456

\*(Aq) \& \->at(\*(Aqb\*(Aq)\->next_node\->next_node; \& \& # " Test " \& $dom\->parse(\*(Aq

123456

\*(Aq) \& \->at(\*(Aqb\*(Aq)\->next_node\->content; .Ve .SS "parent" .IX Subsection "parent" .Vb 1 \& my $parent = $dom\->parent; .Ve .PP Return Mojo::DOM object for parent of this node, or \f(CW\*(C`undef\*(C'\fR if this node has no parent. .PP .Vb 2 \& # "Test" \& $dom\->parse(\*(Aq

Test

\*(Aq)\->at(\*(Aqi\*(Aq)\->parent; .Ve .SS "parse" .IX Subsection "parse" .Vb 1 \& $dom = $dom\->parse(\*(AqI ♥ Mojolicious!\*(Aq); .Ve .PP Parse \s-1HTML/XML\s0 fragment with Mojo::DOM::HTML. .PP .Vb 2 \& # Parse XML \& my $dom = Mojo::DOM\->new\->xml(1)\->parse(\*(AqI ♥ Mojolicious!\*(Aq); .Ve .SS "preceding" .IX Subsection "preceding" .Vb 2 \& my $collection = $dom\->preceding; \& my $collection = $dom\->preceding(\*(Aqdiv ~ p\*(Aq); .Ve .PP Find all sibling elements before this node matching the \s-1CSS\s0 selector and return a Mojo::Collection object containing these elements as Mojo::DOM objects. All selectors from \*(L"\s-1SELECTORS\*(R"\s0 in Mojo::DOM::CSS are supported. .PP .Vb 2 \& # List tags of sibling elements before this node \& say $dom\->preceding\->map(\*(Aqtag\*(Aq)\->join("\en"); .Ve .SS "preceding_nodes" .IX Subsection "preceding_nodes" .Vb 1 \& my $collection = $dom\->preceding_nodes; .Ve .PP Return a Mojo::Collection object containing all sibling nodes before this node as Mojo::DOM objects. .PP .Vb 2 \& # "A" \& $dom\->parse(\*(AqA

C

\*(Aq)\->at(\*(Aqp\*(Aq)\->preceding_nodes\->first\->content; .Ve .SS "prepend" .IX Subsection "prepend" .Vb 2 \& $dom = $dom\->prepend(\*(Aq

I ♥ Mojolicious!

\*(Aq); \& $dom = $dom\->prepend(Mojo::DOM\->new); .Ve .PP Prepend \s-1HTML/XML\s0 fragment to this node (for all node types other than \f(CW\*(C`root\*(C'\fR). .PP .Vb 3 \& # "

Test

123

" \& $dom\->parse(\*(Aq

123

\*(Aq) \& \->at(\*(Aqh2\*(Aq)\->prepend(\*(Aq

Test

\*(Aq)\->root; \& \& # "

Test 123

" \& $dom\->parse(\*(Aq

123

\*(Aq) \& \->at(\*(Aqp\*(Aq)\->child_nodes\->first\->prepend(\*(AqTest \*(Aq)\->root; .Ve .SS "prepend_content" .IX Subsection "prepend_content" .Vb 2 \& $dom = $dom\->prepend_content(\*(Aq

I ♥ Mojolicious!

\*(Aq); \& $dom = $dom\->prepend_content(Mojo::DOM\->new); .Ve .PP Prepend \s-1HTML/XML\s0 fragment (for \f(CW\*(C`root\*(C'\fR and \f(CW\*(C`tag\*(C'\fR nodes) or raw content to this node's content. .PP .Vb 3 \& # "

Test123

" \& $dom\->parse(\*(Aq

123

\*(Aq) \& \->at(\*(Aqh2\*(Aq)\->prepend_content(\*(AqTest\*(Aq)\->root; \& \& # "
" \& $dom\->parse(\*(Aq
\*(Aq) \& \->child_nodes\->first\->prepend_content(\*(Aq Test\*(Aq)\->root; \& \& # "

123Test

" \& $dom\->parse(\*(Aq

Test

\*(Aq)\->at(\*(Aqp\*(Aq)\->prepend_content(\*(Aq123\*(Aq)\->root; .Ve .SS "previous" .IX Subsection "previous" .Vb 1 \& my $sibling = $dom\->previous; .Ve .PP Return Mojo::DOM object for previous sibling element, or \f(CW\*(C`undef\*(C'\fR if there are no more siblings. .PP .Vb 2 \& # "

Test

" \& $dom\->parse(\*(Aq

Test

123

\*(Aq)\->at(\*(Aqh2\*(Aq)\->previous; .Ve .SS "previous_node" .IX Subsection "previous_node" .Vb 1 \& my $sibling = $dom\->previous_node; .Ve .PP Return Mojo::DOM object for previous sibling node, or \f(CW\*(C`undef\*(C'\fR if there are no more siblings. .PP .Vb 3 \& # "123" \& $dom\->parse(\*(Aq

123456

\*(Aq) \& \->at(\*(Aqb\*(Aq)\->previous_node\->previous_node; \& \& # " Test " \& $dom\->parse(\*(Aq

123456

\*(Aq) \& \->at(\*(Aqb\*(Aq)\->previous_node\->content; .Ve .SS "remove" .IX Subsection "remove" .Vb 1 \& my $parent = $dom\->remove; .Ve .PP Remove this node and return \*(L"root\*(R" (for \f(CW\*(C`root\*(C'\fR nodes) or \*(L"parent\*(R". .PP .Vb 2 \& # "
" \& $dom\->parse(\*(Aq

Test

\*(Aq)\->at(\*(Aqh1\*(Aq)\->remove; \& \& # "

456

" \& $dom\->parse(\*(Aq

123456

\*(Aq) \& \->at(\*(Aqp\*(Aq)\->child_nodes\->first\->remove\->root; .Ve .SS "replace" .IX Subsection "replace" .Vb 2 \& my $parent = $dom\->replace(\*(Aq
I ♥ Mojolicious!
\*(Aq); \& my $parent = $dom\->replace(Mojo::DOM\->new); .Ve .PP Replace this node with \s-1HTML/XML\s0 fragment and return \*(L"root\*(R" (for \f(CW\*(C`root\*(C'\fR nodes) or \*(L"parent\*(R". .PP .Vb 2 \& # "

123

" \& $dom\->parse(\*(Aq

Test

\*(Aq)\->at(\*(Aqh1\*(Aq)\->replace(\*(Aq

123

\*(Aq); \& \& # "

123

" \& $dom\->parse(\*(Aq

Test

\*(Aq) \& \->at(\*(Aqp\*(Aq)\->child_nodes\->[0]\->replace(\*(Aq123\*(Aq)\->root; .Ve .SS "root" .IX Subsection "root" .Vb 1 \& my $root = $dom\->root; .Ve .PP Return Mojo::DOM object for \f(CW\*(C`root\*(C'\fR node. .SS "selector" .IX Subsection "selector" .Vb 1 \& my $selector = $dom\->selector; .Ve .PP Get a unique \s-1CSS\s0 selector for this element. .PP .Vb 2 \& # "ul:nth\-child(1) > li:nth\-child(2)" \& $dom\->parse(\*(Aq\*(Aq)\->find(\*(Aqli\*(Aq)\->last\->selector; \& \& # "p:nth\-child(1) > b:nth\-child(1) > i:nth\-child(1)" \& $dom\->parse(\*(Aq

Test

\*(Aq)\->at(\*(Aqi\*(Aq)\->selector; .Ve .SS "strip" .IX Subsection "strip" .Vb 1 \& my $parent = $dom\->strip; .Ve .PP Remove this element while preserving its content and return \*(L"parent\*(R". .PP .Vb 2 \& # "
Test
" \& $dom\->parse(\*(Aq

Test

\*(Aq)\->at(\*(Aqh1\*(Aq)\->strip; .Ve .SS "tag" .IX Subsection "tag" .Vb 2 \& my $tag = $dom\->tag; \& $dom = $dom\->tag(\*(Aqdiv\*(Aq); .Ve .PP This element's tag name. .PP .Vb 2 \& # List tag names of child elements \& say $dom\->children\->map(\*(Aqtag\*(Aq)\->join("\en"); .Ve .SS "tap" .IX Subsection "tap" .Vb 1 \& $dom = $dom\->tap(sub {...}); .Ve .PP Alias for \*(L"tap\*(R" in Mojo::Base. .SS "text" .IX Subsection "text" .Vb 1 \& my $text = $dom\->text; .Ve .PP Extract text content from this element only (not including child elements). .PP .Vb 2 \& # "bar" \& $dom\->parse("
foo

bar

baz
")\->at(\*(Aqp\*(Aq)\->text; \& \& # "foo\enbaz\en" \& $dom\->parse("
foo\en

bar

baz\en
")\->at(\*(Aqdiv\*(Aq)\->text; .Ve .SS "to_string" .IX Subsection "to_string" .Vb 1 \& my $str = $dom\->to_string; .Ve .PP Render this node and its content to \s-1HTML/XML.\s0 .PP .Vb 2 \& # "Test" \& $dom\->parse(\*(Aq
Test
\*(Aq)\->at(\*(Aqdiv b\*(Aq)\->to_string; .Ve .SS "tree" .IX Subsection "tree" .Vb 2 \& my $tree = $dom\->tree; \& $dom = $dom\->tree([\*(Aqroot\*(Aq]); .Ve .PP Document Object Model. Note that this structure should only be used very carefully since it is very dynamic. .SS "type" .IX Subsection "type" .Vb 1 \& my $type = $dom\->type; .Ve .PP This node's type, usually \f(CW\*(C`cdata\*(C'\fR, \f(CW\*(C`comment\*(C'\fR, \f(CW\*(C`doctype\*(C'\fR, \f(CW\*(C`pi\*(C'\fR, \f(CW\*(C`raw\*(C'\fR, \&\f(CW\*(C`root\*(C'\fR, \f(CW\*(C`tag\*(C'\fR or \f(CW\*(C`text\*(C'\fR. .PP .Vb 2 \& # "cdata" \& $dom\->parse(\*(Aq\*(Aq)\->child_nodes\->first\->type; \& \& # "comment" \& $dom\->parse(\*(Aq\*(Aq)\->child_nodes\->first\->type; \& \& # "doctype" \& $dom\->parse(\*(Aq\*(Aq)\->child_nodes\->first\->type; \& \& # "pi" \& $dom\->parse(\*(Aq\*(Aq)\->child_nodes\->first\->type; \& \& # "raw" \& $dom\->parse(\*(AqTest\*(Aq)\->at(\*(Aqtitle\*(Aq)\->child_nodes\->first\->type; \& \& # "root" \& $dom\->parse(\*(Aq

Test

\*(Aq)\->type; \& \& # "tag" \& $dom\->parse(\*(Aq

Test

\*(Aq)\->at(\*(Aqp\*(Aq)\->type; \& \& # "text" \& $dom\->parse(\*(Aq

Test

\*(Aq)\->at(\*(Aqp\*(Aq)\->child_nodes\->first\->type; .Ve .SS "val" .IX Subsection "val" .Vb 1 \& my $value = $dom\->val; .Ve .PP Extract value from form element (such as \f(CW\*(C`button\*(C'\fR, \f(CW\*(C`input\*(C'\fR, \f(CW\*(C`option\*(C'\fR, \&\f(CW\*(C`select\*(C'\fR and \f(CW\*(C`textarea\*(C'\fR), or return \f(CW\*(C`undef\*(C'\fR if this element has no value. In the case of \f(CW\*(C`select\*(C'\fR with \f(CW\*(C`multiple\*(C'\fR attribute, find \f(CW\*(C`option\*(C'\fR elements with \&\f(CW\*(C`selected\*(C'\fR attribute and return an array reference with all values, or \f(CW\*(C`undef\*(C'\fR if none could be found. .PP .Vb 2 \& # "a" \& $dom\->parse(\*(Aq\*(Aq)\->at(\*(Aqinput\*(Aq)\->val; \& \& # "b" \& $dom\->parse(\*(Aq\*(Aq)\->at(\*(Aqtextarea\*(Aq)\->val; \& \& # "c" \& $dom\->parse(\*(Aq\*(Aq)\->at(\*(Aqoption\*(Aq)\->val; \& \& # "d" \& $dom\->parse(\*(Aq\*(Aq) \& \->at(\*(Aqselect\*(Aq)\->val; \& \& # "e" \& $dom\->parse(\*(Aq\*(Aq) \& \->at(\*(Aqselect\*(Aq)\->val\->[0]; \& \& # "on" \& $dom\->parse(\*(Aq\*(Aq)\->at(\*(Aqinput\*(Aq)\->val; .Ve .SS "with_roles" .IX Subsection "with_roles" .Vb 3 \& my $new_class = Mojo::DOM\->with_roles(\*(AqMojo::DOM::Role::One\*(Aq); \& my $new_class = Mojo::DOM\->with_roles(\*(Aq+One\*(Aq, \*(Aq+Two\*(Aq); \& $dom = $dom\->with_roles(\*(Aq+One\*(Aq, \*(Aq+Two\*(Aq); .Ve .PP Alias for \*(L"with_roles\*(R" in Mojo::Base. .SS "wrap" .IX Subsection "wrap" .Vb 2 \& $dom = $dom\->wrap(\*(Aq
\*(Aq); \& $dom = $dom\->wrap(Mojo::DOM\->new); .Ve .PP Wrap \s-1HTML/XML\s0 fragment around this node (for all node types other than \f(CW\*(C`root\*(C'\fR), placing it as the last child of the first innermost element. .PP .Vb 2 \& # "

123Test

" \& $dom\->parse(\*(AqTest\*(Aq)\->at(\*(Aqb\*(Aq)\->wrap(\*(Aq

123

\*(Aq)\->root; \& \& # "

Test

123
" \& $dom\->parse(\*(AqTest\*(Aq)\->at(\*(Aqb\*(Aq)\->wrap(\*(Aq

123
\*(Aq)\->root; \& \& # "

Test

123

" \& $dom\->parse(\*(AqTest\*(Aq)\->at(\*(Aqb\*(Aq)\->wrap(\*(Aq

123

\*(Aq)\->root; \& \& # "

Test

" \& $dom\->parse(\*(Aq

Test

\*(Aq)\->at(\*(Aqp\*(Aq)\->child_nodes\->first\->wrap(\*(Aq\*(Aq)\->root; .Ve .SS "wrap_content" .IX Subsection "wrap_content" .Vb 2 \& $dom = $dom\->wrap_content(\*(Aq
\*(Aq); \& $dom = $dom\->wrap_content(Mojo::DOM\->new); .Ve .PP Wrap \s-1HTML/XML\s0 fragment around this node's content (for \f(CW\*(C`root\*(C'\fR and \f(CW\*(C`tag\*(C'\fR nodes), placing it as the last children of the first innermost element. .PP .Vb 2 \& # "

123Test

" \& $dom\->parse(\*(Aq

Test

\*(Aq)\->at(\*(Aqp\*(Aq)\->wrap_content(\*(Aq123\*(Aq)\->root; \& \& # "

Test

123

" \& $dom\->parse(\*(AqTest\*(Aq)\->wrap_content(\*(Aq

123

\*(Aq); .Ve .SS "xml" .IX Subsection "xml" .Vb 2 \& my $bool = $dom\->xml; \& $dom = $dom\->xml($bool); .Ve .PP Disable \s-1HTML\s0 semantics in parser and activate case-sensitivity, defaults to auto-detection based on \s-1XML\s0 declarations. .SH "OPERATORS" .IX Header "OPERATORS" Mojo::DOM overloads the following operators. .SS "array" .IX Subsection "array" .Vb 1 \& my @nodes = @$dom; .Ve .PP Alias for \*(L"child_nodes\*(R". .PP .Vb 2 \& # "" \& $dom\->parse(\*(Aq123\*(Aq)\->[0]; .Ve .SS "bool" .IX Subsection "bool" .Vb 1 \& my $bool = !!$dom; .Ve .PP Always true. .SS "hash" .IX Subsection "hash" .Vb 1 \& my %attrs = %$dom; .Ve .PP Alias for \*(L"attr\*(R". .PP .Vb 2 \& # "test" \& $dom\->parse(\*(Aq
Test
\*(Aq)\->at(\*(Aqdiv\*(Aq)\->{id}; .Ve .SS "stringify" .IX Subsection "stringify" .Vb 1 \& my $str = "$dom"; .Ve .PP Alias for \*(L"to_string\*(R". .SH "SEE ALSO" .IX Header "SEE ALSO" Mojolicious, Mojolicious::Guides, .