使用 perl XML::LibXML 删除具有某些属性的 XML 节点的标签

问题描述 投票:0回答:1

我正在使用 perl XML::LibXML 模块来操作 XML 文件。

我想删除 XML 节点的开始和结束标记(如果它具有某个属性),使其文本和子节点成为该节点父节点的一部分。

这是一次不成功的尝试。如果失败并显示

insertBefore/insertAfter: HIERARCHY_REQUEST_ERR
:

#!/usr/bin/env perl
use 5.020;
use warnings;
use XML::LibXML;

#the input xml

my $inputstr = <<XML;
<root>
<a>
<b class="deletethistag">keep this text<c>keep this c node</c>keep this text too</b>
<b class="someothertag">don't change this</b>
<b>don't change this node without an attribute</b>
<c class="type1">don't change this either</c>
</a>
</root>
XML

my $desiredstr = <<XML ;
<root>
<a>keep this text<c>keep this c node</c>keep this text too
<b class="someothertag">don't change this</b>
<b>don't change this node without an attribute</b>
<c class="type1">don't change this either</c>
</a>
</root>
XML

my $dom = XML::LibXML->load_xml(
string => $inputstr
);

# Convert $inputstr to $desiredstr *** doesn't work ***
foreach my $node ($dom->findnodes(q#//a/b[@class="deletethistag"]/*#)) {
    my $nodestring = $node->toString(1);
    say STDERR $nodestring;
    my $replacementnode = XML::LibXML->load_xml(string => $nodestring);
    $node->parentNode()->insertAfter($replacementnode, $node);
    $node->unbindNode();
    }
say $dom->toString(1);

我想使用代码从文件中删除

<span lang="en" xml:space="preserve">...</span>
标记,但我已将其作为一个更一般的问题,以便我了解更多使用 XML::LibXML 的细节。

xml perl xml-libxml
1个回答
0
投票

$node->childNodes()
返回 $node 的所有文本节点和其他子节点。

将 $node 的所有子节点插入到 $node 的父节点中与 $node 相同的位置。然后用

$node->unbindNode()

删除原来的$node

这是一个工作脚本:

#!/usr/bin/env perl
use 5.020;
use warnings;
use XML::LibXML;

#the input xml
my $inputstr = <<XML;
<root>
<a>
<b class="deletethistag">keep this text<c>keep this c node</c>keep this text too</b>
<b class="someothertag">don't change this</b>
<b>don't change this node without an attribute</b>
<c class="type1">don't change this either</c>
</a>
</root>
XML

my $desiredstr = <<XML ;
<root>
<a>
keep this text<c>keep this c node</c>keep this text too
<b class="someothertag">don't change this</b>
<b>don't change this node without an attribute</b>
<c class="type1">don't change this either</c>
</a>
</root>
XML

my $dom = XML::LibXML->load_xml(
string => $inputstr
);

for my $node ($dom->findnodes(q#//a/b[@class="deletethistag"]#)) {
    my $parent = $node->parentNode();
    for my $child_node ( $node->childNodes() ) {
        $parent->insertBefore($child_node, $node);
        }
    $node->unbindNode();
    }
say $dom->toString();
© www.soinside.com 2019 - 2024. All rights reserved.