Узел удаления Perl - PullRequest
       13

Узел удаления Perl

0 голосов
/ 02 июля 2019

Я начинаю с Perl, я знаю, что есть ответы на некоторые похожие вопросы, но (из-за отсутствия опыта) ни один из них не помог.

У меня есть 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]")

Кто-нибудь мне поможет?

Ответы [ 2 ]

3 голосов
/ 02 июля 2019

Вот документация для метода removeChild() :

RemoveChild

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

Это отсоединит дочерний узел от его родителя $node. Функция возвращает несвязанный узел. Если oldNode не является потомком данного узла, функция потерпит неудачу.

(Там есть опечатка - там написано oldNode, я почти уверен, что это означает $childNode.)

Возможно, это не очень понятно, но вам нужно передать removeChild() узел объект , а не просто строку. Вы передаете ему буквальную строку «task [preTask_L1]», и я действительно не уверен, откуда у вас эта идея.

Я думаю, что вы скорее запутались, используя плохие имена для своих переменных. Ваша переменная $name содержит объект узла, а не имя. И ваша $node переменная содержит текст из узла (который можно считать его «именем»).

Я думаю, что самое простое решение - изменить строку кода на:

say $parent->removeChild($name);

Но я действительно рекомендую исправить эти имена переменных. Ваш программист по обслуживанию (который может стать вами через шесть месяцев) поблагодарит вас: -)

2 голосов
/ 02 июля 2019

Прежде всего, пожалуйста, используйте лучшие имена переменных. Ваши ужасные имена ($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")]');
...