删除多行XML节点的Perl代码

我有一个 xml 文件 test.xml

<many-nested-roots>

    <foo>
      <bar>
      </bar>
    </foo>
    
    <other-random-nodes></other-random-nodes>

    <foo>
      <bar>
        <foobar>
        </foobar>
      </bar>
    </foo>
    
    <!-- multiple such blocks not in any particular order -->

</many-nested-roots>

我需要删除 xml 节点<foo><bar></bar></foo>而不是<foo><bar><foobar></foobar></bar></foo>.

编辑:该节点<foo><bar></bar></foo>在严重嵌套的 XML 中随机出现多次。

我试过哪些不起作用:

perl -ne 'print unless /^s*<foo>ns*<bar>ns*<bar>ns*</foo>/' test.xml

^ 这与换行符不匹配

perl -ne 'print unless /<foo>/ ... /</foo>/' test.xml

^ 这将删除所有标签,包括 <foobar>

perl -ne 'print unless /<foo>.*?<bar>.*?</bar>.*?</foo>/s' test.xml

^ 我曾经/s.匹配换行。不起作用。

回答

一个单行使用XML::LibXML和一个 XPath 表达式来查找要删除的节点:

perl -MXML::LibXML -E '
  my $dom = XML::LibXML->load_xml(location => $ARGV[0]);
  $_->unbindNode for $dom->documentElement->find("//foo/bar[count(*)=0]/..")->@*;
  print $dom->serialize' test.xml

(旧版本的 perl 需要@{$dom->...}而不是$dom->...->@*

或者使用xmlstarlet(不是 perl,但对于 XML 文件的脚本操作非常方便):

 xmlstarlet ed -d '//foo/bar[count(*)=0]/..' test.xml


以上是删除多行XML节点的Perl代码的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>