【问题标题】:Parent element does not close after deleting an element: XML Twig删除元素后父元素未关闭:XML Twig
【发布时间】:2013-07-31 21:41:55
【问题描述】:

我正在尝试查找具有特定值的属性的元素并将其从文档中删除。

在本例中,我正在寻找一个 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>

【问题讨论】:

  • 删除flush或替换为purge
  • 你的 perl 脚本和你的 xml 有错误。如果您等待更好的答案,请修复它们。
  • 我已将代码更新到现在的编译位置。 XML 不正确,这是我的问题。下面 mirod 的解决方案就像一个魅力。谢谢!但就转义反斜杠而言,我认为我不必这样做,因为字符串在单引号内。
  • 不是!是双引号。

标签: xml perl xml-twig


【解决方案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-&gt;cut_children( q{File[@RelativePath='..\..\TS\ETestScenario.inc']});

【讨论】:

    猜你喜欢
    • 2014-11-18
    • 1970-01-01
    • 1970-01-01
    • 2012-10-17
    • 2018-01-17
    • 1970-01-01
    • 2016-08-26
    • 2013-01-17
    • 1970-01-01
    相关资源
    最近更新 更多