Родительский элемент не закрывается после удаления элемента: XML Twig
Я пытаюсь найти элемент с атрибутом с определенным значением и удаляю его из документа.
В этом примере я ищу элемент File с атрибутом "RelativePath", значение которого "....\TS\ETestScenario.inc".
Проблема: последний элемент - </Files>
отсутствует после запуска сценария. Кроме того, закрывающий тег VisualStudioProject печатается дважды. Не уверен, что я здесь делаю.
use strict;
use XML::Twig;
my $fileName = 'Z:\autotest\test.xml';
my $t= new XML::Twig( TwigRoots=>
{ Files => \&upd_files_section
},
twig_print_outside_roots => 1, # print the rest
keep_spaces => 1,
keep_atts_order=>1,
);
$t->parsefile("$fileName");
#$t->parsefile_inplace ("$fileName");
sub upd_files_section{
my ($t, $inputFields)=@_;
my $file_to_delete = $inputFields->get_xpath("./File[\@att='..\..\TS\ETestScenario.inc']");
$inputFields->delete($file_to_delete);
$t->flush;
}
Неверный вывод XML:
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="xxx"
ProjectGUID="{}"
RootNamespace="xx"
SccProjectName="x"
SccLocalPath="."
SccProvider="x"
>
<Files>
<Filter Name="Source Files" Filter="cpp;bat">
<File RelativePath="..\..\TS\ADK_MacCommon_Test.cpp">
</File>
<File RelativePath="..\..\FSO\EADK.cpp">
</File>
<Filter Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" Name="Resource Files">
</Filter>
<File RelativePath="..\..\TS\ETestScenario.inc">
</File>
</VisualStudioProject>
<Globals>
</Globals>
</VisualStudioProject>
1 ответ
Решение
Как уже упоминалось, XML не является допустимым, и код не компилируется.
Тем не менее, если я правильно понимаю, я думаю, что обработчик должен быть:
sub upd_files_section{
my ($t, $inputFields)=@_;
my @files_to_delete = $inputFields->get_xpath("./File[\@RelativePath='..\\..\\TS\\ETestScenario.inc']");
foreach my $file (@files_to_delete) { $file->delete; }
$t->flush;
}
Несколько заметок:
- вам нужно избежать обратной косой черты в выражении XPath, или Perl думает, что они там, чтобы избежать следующего символа; в качестве альтернативы, используйте простые кавычки или
q{}
вокруг выражения:q{./File[@RelativePath='..\..\TS\ETestScenario.inc']}
- в выражении XPath это должно быть
@RelativePath
не@att
get_xpath
возвращает список элементов, которые вы должны удалить- удалить вызов элемента
delete
на этом, нет необходимости проходить через своего родителя, как с DOM - Вы также можете вырезать всех детей одновременно, используя...
cut_children
метод:$inputFields->cut_children( q{File[@RelativePath='..\..\TS\ETestScenario.inc']});