Perl删除节点

时间:2019-07-02 12:13:07

标签: xml perl xml-libxml

我从Perl开始,我知道回答了一些类似的问题,但是(由于我的经验不足)它们都没有帮助。

我有这样的xml:

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

我需要删除所有具有节点任务=〜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]")

有人会帮助我吗?

2 个答案:

答案 0 :(得分:3)

这里是documentation for the removeChild() method

  

删除孩子

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

这将使子节点与其父节点$node解除绑定。函数返回   未绑定的节点。如果oldNode不是给定Node的子代,则该函数   将失败。

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

也许不是很清楚,但是您需要传递removeChild()节点 object ,而不仅仅是字符串。您将其传递为文字字符串“ task [preTask_L1]”,但我真的不确定您从何处得到这个想法。

我认为您对变量使用了坏名,这让您很困惑。您的$name变量包含一个节点对象,而不是名称。并且您的$node变量包含节点中的文本(可能被视为其“名称”)。

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

say $parent->removeChild($name);

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

答案 1 :(得分:2)

首先,请使用更好的变量名。您的可怕名字($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")]');