XML(LibXML):用具有相同内容的xhtml:h2标记替换xhtml:h1标记的最简单方法

XML(LibXML):用具有相同内容的xhtml:h2标记替换xhtml:h1标记的最简单方法,xml,perl,libxml2,Xml,Perl,Libxml2,我正在使用Perl/CPAN来解析和操作一个有效的XHTML1.1文档,该文档包含几个嵌套的标记,其中包含,等等 现在,我正在从那里提取div,它们的标题以开头,我想转换为以开头(即:h2)→ h1;h3→ h2;h4→ h3等) 如何使用XML::LibXML实现这一点 以下是我到目前为止的情况: foreach my $h_idx (2 .. 6) { foreach my $h_tag ($scene_xpc->findnodes(qq{//xhtml

我正在使用Perl/CPAN来解析和操作一个有效的XHTML1.1文档,该文档包含几个嵌套的标记,其中包含,等等

现在,我正在从那里提取div,它们的标题以开头,我想转换为以开头(即:h2)→ h1;h3→ h2;h4→ h3等)

如何使用XML::LibXML实现这一点

以下是我到目前为止的情况:

    foreach my $h_idx (2 .. 6)
    {
        foreach my $h_tag ($scene_xpc->findnodes(qq{//xhtml:h$h_idx}))
        {
            my $replacement = $h_tag->cloneNode(1);
            # TODO : how do I set the name?
            $replacement->set
            $h_tag->replaceNode($replacement);
        }
    }

正如您从变量名
$scene\u xpc
中猜到的,您需要定义一个
XML::LibXML::XPathContext
,它定义了
xhtml
名称空间。此后,您可以像使用普通的
XML::LibXML
对象一样使用该上下文,但现在可以在元素和属性名称中指定已注册的名称空间

我不清楚为什么要克隆每个节点。据我所知,您只需在每个节点上执行
setNodeName
。所需的只是localname:元素将保留其原始名称空间

这个简短的节目展示了这个想法

use strict;
use warnings;
use 5.014;    # For non-destructive substitution

use XML::LibXML;

my $filename = 'xhtml.html';

my $xml = XML::LibXML->new;
my $doc = $xml->parse_file($filename);

my $xpc = XML::LibXML::XPathContext->new($doc);
$xpc->registerNs('xhtml', 'http://www.w3.org/1999/xhtml');

for my $head ('h2' .. 'h6') {
  my $newhead = $head =~ s/(\d)/$1-1/er;
  for my $node ($xpc->findnodes("//xhtml:$head")) {
    $node->setNodeName($newhead);
  }
}

print $doc->toString;

您好,Borodin,谢谢您的评论-这让我找到了正确的方向,尽管我的代码现在更复杂了,因为XPath是错误的(它应该是“xhtml:h2”而不是“//xhtml:h2”)。抛开这一点不谈,您的代码对我的s///er这件事来说有点太聪明了。我更喜欢用整数。但再次感谢你。