2015-03-13 73 views
-2

假设我有一个文件中的以下行(不认为这是一个XML文件)删除文件多行:找到一个关键

<AVP code="123" name="abcd"> 
    <type> 
     <high/> 
    </type> 
</AVP> 
<AVP code="234" name="ukbkj"> 
    <type> 
     <enum/> 
    <type> 
     <enum name="erdf"/> 
</AVP> 

我想从删除(例如) AVP代码123添加到匹配/ AVP中,以便删除AVP 123的所有数据。我怎样才能做到这一点? 以下是输出结果的样子。我想保存到一个文件,而不是打印到标准输出。

<AVP code="234" name="ukbkj"> 
    <type> 
     <enum/> 
    <type> 
     <enum name="erdf"/> 
</AVP> 
+1

我不太明白。请在您的问题中包括1)所需的输出,2)您尝试过的Python或Perl代码,3)您获得的实际输出。 – 2015-03-13 13:19:57

+0

他正试图删除整个块。 – 2015-03-13 13:20:37

+0

我需要python脚本 – 2015-03-13 13:25:04

回答

1

通过perl。

$ perl -0777pe 's/<AVP code="123".*?<\/AVP> *\n//sg' file 
<AVP code="234" name="ukbkj"> 
<type> 
<enum\> 
<type> 
<enum\> 
<AVP code> 

通过python。

import re 
with open('file') as f: 
    m = f.read() 
    splt = re.findall(r'(?s)<AVP\s+code="\d+".*?</AVP>', m) 
    for i in splt: 
     if '<AVP code="123"' not in i: 
      print(i, end="") 
+0

也许它应该寻找一个结束''标签而不是下一个AVP元素:如果他想删除的是一个序列中的最后一个,该怎么办?那么这不会吞噬文档的其余部分吗? – 2015-03-13 13:23:53

+0

检查我的upadte。 – 2015-03-13 13:26:31

+0

更好;猜测OP希望python,即使他把perl标签放在它上面... – 2015-03-13 13:27:48

0

如果您投入将是XML,它会是这个样子:

<?xml version="1.0"?> 
<root> 
    <AVP code="123" name="abcd"> 
     <type> 
      <high/> 
     </type> 
    </AVP> 
    <AVP code="234" name="ukbkj"> 
     <type> 
      <enum/> 
     </type> 
     <type> 
      <enum/> 
     </type> 
    </AVP> 
</root> 

您可以使用此XSLT删除所有AVP元素。

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:output omit-xml-declaration="no"/> 

    <xsl:template match="node()|@*"> 
     <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="AVP[@code='123']" /> 
</xsl:stylesheet> 

应用它使用Python:

import lxml.etree as ET 

dom = ET.parse("avp.xml") 
xslt = ET.parse("avp.xslt") 
transform = ET.XSLT(xslt) 
newdom = transform(dom) 
with open("avp-out.xml", "wb") as o: 
    o.write(ET.tostring(newdom, pretty_print=True)) 

产出avp-out.xml

<root> 

    <AVP code="234" name="ukbkj"> 
     <type> 
      <enum/> 
     </type> 
     <type> 
      <enum/> 
     </type> 
    </AVP> 
</root> 
+0

谢谢@Lutz Horn – 2015-03-13 13:55:33

+0

正如你用xslt解释过的。但代码可以不同(它将由用户提出)所以在这里我们如何将用户输入代码传递给xslt。 – 2015-03-16 13:38:30

0

更合适的方法,这将使用的XML解析库做的,XML::LibXML是一个很好的。请注意,您目前的例子是有效的XML:

use strict; 
use warnings; 

use XML::LibXML; 

my $xml_filename = $ARGV[0]; 
die "Missing name of xml file to parse" 
    unless $xml_filename; 
open(my $xml_file, '<', $xml_filename) 
    or die "Error opening XML file: $!"; 

my $dom = XML::LibXML->load_xml(IO => $xml_file); 
foreach my $node ($dom->findnodes('/root/AVP')) { 
    $node->unbindNode() 
     if $node->getAttribute('code') == 123; 
} 

open(my $out_fh, '>', "${xml_filename}.out") 
    or die "Unable to open outfile: $!"; 
binmode $out_fh;  

# write XML tree to file 
$dom->toFH($out_fh); 
close($out_fh); 
0

随着XML::Twig - 复制该卢茨霍恩提到的固定XML:

#!/usr/bin/perl 

use strict; 
use warnings; 

use XML::Twig; 

sub delete_if_code_123 { 
    my ($twig, $AVP) = @_; 
    if ($AVP->att('code') eq "123") { 
     $AVP->delete; 
    } 
} 

my $twig = XML::Twig->new(
    pretty_print => 'indented', 
    twig_handlers => { 'AVP' => \&delete_if_code_123 }, 
); 

$twig ->parse(\*DATA); 

$twig -> print; 


__DATA__ 
<?xml version="1.0"?> 
<root> 
    <AVP code="123" name="abcd"> 
     <type> 
      <high/> 
     </type> 
    </AVP> 
    <AVP code="234" name="ukbkj"> 
     <type> 
      <enum/> 
     </type> 
     <type> 
      <enum/> 
     </type> 
    </AVP> 
</root>