\Q$start\E(?:\s+|\s*>)!gcsi;_节点($current,'raw',$RCDATA{$start}?html_unescape$1:$1);_结束($start,0,\$current);}}#DOCTYPE(文件类型)elsif(定义的$doctype){_node($current,'doctype',$doctype')}#注释elsif(定义的$comment){_node($current,'comment',$comment')}#CDATA(CDATA)elsif(定义的$cdata){节点($current,'cdata',$cdata')}#处理指令(尝试检测XML)elsif(定义$pi){$self->xml($xml=1)if!存在$self->{xml}&&$pi=~/xml/i;_节点($current,'pi',$pi);}}返回$self->tree($tree);}子呈现{_render($[0]->树,$[0]->xml)}子标记{shift->tree(['root',_tag(@_)])}子标记to_html{_render(标记(@_),undef)}子结束(_E){my($end,$xml,$current)=@_;#搜索堆栈中的开始标记my$next=当前$$;做{#忽略无用的结束标记如果$next->[0]eq'root',则返回;#不要遍历容器标签如果$SCOPE{$next->[1]}&&$next->[1]ne$end;,则返回;#右标签return$$current=$next->[3]if$next->[1]eq$end;#短语内容只能跨短语内容如果返回$xml&&$PHRASING{$end}&&$语法{$next->[1]};}而$next=$next->[3];}子节点(_N){my($current,$type,$content)=@_;push@$current,my$new=[$type,$content,$current];削弱$new->[2];}子阅读器(_R){my($tree,$xml)=@_;#标签我的$type=$tree->[0];if($type eq“标签”){#开始标记我的$tag=$tree->[1];my$result=“<$tag”;#属性对于我的$键(排序键%{$tree->[2]){我的$value=$tree->[2]{$key};$结果=$xml?qq{$key=“$key”}:除非定义了$value,否则为“$key”和next;$结果=qq{$key=“}.xml_escape($value).'”;}#没有孩子返回$xml?“$result/>”:$EMPTY{$tag}?“$result>”:“$resort>$tag>“除非$tree->[4];#儿童没有警告“递归”;$result.=“>”。连接“”,映射{_render($_,$xml)}@$tree[4..$#$tree];#结束标记return“$result$tag>";}#文本(转义)如果$type eq'text',则返回xml_escape$tree->[1];#原始文本如果$type eq为“raw”,则返回$tree->[1];#根如果$type eq为“root”,则返回连接“”,映射{_render($_,$xml)}@$tree[1..$#$tree];#DOCTYPE(文件类型)返回'[1] . '>' 如果$type等于'doctype';#注释返回''if$type eq'注释';#CDATA(CDATA)返回'[1] . ']]>' 如果$type eq“cdata”;#加工说明返回'' . $tree->[1] . '?>' 如果$type eq‘pi’;#其他一切返回“”;}子启动(_S){my($start,$attrs,$xml,$current)=@_;#自动关闭可选HTML元素if(!$xml&&$current->[0]ne“根”){if(my$end=$end{$start}){_end($end,0,$current)}elsif(我的$close=$close{$start}){my($allowed,$scope)=@$close;#关闭范围中允许的父元素我的$parent=$$current;while($parent->[0]ne“根”&&!$scope->{$parent->[1]}){_如果$allowed->{$parent->[1]},则结束($parent->[1],0,$current);$parent=$parent->[3];}}}#新标签推送@$$current,我的$new=['tag',$start,$attrs,$$current];削弱$new->[3];$$当前=$新;}子标记(_T){my$tree=['tag',shift,undef,undef];#内容push@$tree,ref$_[-1]eq“CODE”?['raw',pop->()]:['text',pop]如果@_%2;#属性我的$attrs=$tree->[2]={@_};返回$tree除非存在$attrs->{data}&&ref$attrs->{data}eq'HASH';my$data=delete$attrs->{data};@$attrs{map{y/_/-/;lc“data-$_”}键%$data}=值%$data;return$tree;}1;=编码utf8=头1名称Mojo::DOM::HTML-HTML/XML引擎=头1概述使用Mojo::DOM::HTML;#将HTML转换为DOM树my$html=Mojo::DOM::html->new;$html->parse('
');我的$tree=$html->tree;=头1描述L(左)是L使用的HTML/XML引擎,基于L和L.=头1功能L(左)实现以下功能,这些功能可以单独导入。=头2标记_to_htmlmy$str=tag_to_html“div”,id=>“foo”,“安全内容”;生成HTML/XML标记并立即呈现。这是L的一个明显更快的替代方案"tag">用于模板必须生成大量标记的系统。=头1属性L(左)实现以下属性。=头2树我的$tree=$html->tree;$html=$html->tree(['root']);文档对象模型。请注意,由于此结构非常动态,因此只能非常小心地使用。=头2 xml我的$bool=$html->xml;$html=$html->xml($bool);禁用解析器中的HTML语义并激活区分大小写,默认为基于XML声明的自动检测。=头1方法L(左)从L继承所有方法并实现了以下新功能。=头2解析$html=$html->parse('我♥ 莫名其妙!');解析HTML/XML片段。=头部2渲染我的$str=$html->render;将DOM渲染为HTML/XML。=head2标签$html=$html->标记('div',id=>'foo','安全内容');生成HTML/XML标记。=头部1另见L(左),L,L.=切割