Perl 删除节点

Perl removing node

我从 Perl 开始,我知道有一些类似的问题得到了回答,但是(由于我缺乏经验)none 其中有帮助。

我有 xml 这样的:

<workflowVertices>
    <workflowVertex>
    <alias />
    <task>Task_L2</task>
    <vertexId>128</vertexId>
</workflowVertex>
<workflowVertex>
     <alias />
     <task>preTask_L1</task>
         <vertexId>129</vertexId>
   </workflowVertex>
</workflowVertices>

我需要删除所有具有节点任务的 workflowVertex 节点 =~ m/_L1/

我现在拥有的:

my $dom = XML::LibXML->load_xml(location => $filename);

foreach my $name ($dom->findnodes('workflowVertices/workflowVertex/task')) 
{
#say $name->to_literal();
if ($name->to_literal() =~ m/_L1/) {
    say "JobName: " . $name->to_literal() . " to be deleted\n";
    my $node = $name->to_literal();
    my $parent = $name-> parentNode();
    say $parent-> removeChild("task[$node]")
    }
}

但是当我执行它时却报错:

XML::LibXML::Node::removeChild() -- node is not a blessed SV reference at 

xmltransform.pl 第 28 行。

第 28 行。在我的代码中是

say $parent-> removeChild("task[$node]")

有人愿意帮助我吗?

这里是 documentation for the removeChild() method:

removeChild

$childnode = $node->removeChild( $childnode );

This will unbind the Child Node from its parent $node. The function returns the unbound node. If oldNode is not a child of the given Node the function will fail.

(这里有一个错字 - 上面写着 oldNode,我很确定它的意思是 $childNode。)

可能不是很清楚,但是你需要传递removeChild()一个节点对象,而不仅仅是一个字符串。您将文字字符串 "task[preTask_L1]" 传递给它,我真的不确定您从哪里得到这个想法。

我认为您为变量使用了错误的名称而使自己感到困惑。您的 $name 变量包含一个节点对象,而不是名称。并且您的 $node 变量包含来自节点的文本(可能被认为是它的 "name")。

我认为最简单的解决方法是将您的代码行更改为:

say $parent->removeChild($name);

但我真的建议也修复那些变量名。您的维护程序员(六个月后很可能成为您)会感谢您:-)

首先,请使用更好的变量名。你可怕的名字($name 是一个 task 节点,$node 根本不是一个节点,不清楚 $parent 指的是谁的父节点,等等)使你的代码极难阅读。


您可以使用

$vertex_node->parent->removeChild($vertex_node);

$vertex_node->unbindNode;

删除节点。固定:

my $dom = XML::LibXML->load_xml( location => $filename );

for my $task_node ($dom->findnodes('/workflowVertices/workflowVertex/task')) {
    my $task_name = $task_node->textContent();
    if ($task_name =~ /_L1/) {
        my $vertex_node = $task_node->parent;
        $vertex_node->unbindNode;
        say "Deleted task $task_name.";
    }
}

替代方法:

my $dom = XML::LibXML->load_xml( location => $filename );

for my $vertex_node ($dom->findnodes('/workflowVertices/workflowVertex')) {
    my $task_name = $vertex_node->findvalue('task/text()');
    if ($task_name =~ /_L1/) {
        $vertex_node->unbindNode;
        say "Deleted task $task_name.";
    }
}

如果不需要打印任务名称,甚至可以缩减为:

my $dom = XML::LibXML->load_xml( location => $filename );

$_->unbindNode
    for $dom->findnodes('/workflowVertices/workflowVertex[contains(task/text(), "_L1")]');