2015-03-13 2 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) фактический результат, который вы получаете. –

+0

он пытался удалить весь блок. –

+0

Мне нужно в скрипте python –

ответ

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: что, если тот, который он хочет удалить, является последним в последовательности? Разве это не сожрает весь остальной документ? –

+0

проверить мой upadte. –

+0

Лучше; угадайте, что OP хочет python, хотя он положил на него тег perl ... –

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 –

+0

Как я объяснил, используя xslt. но код может быть другим (это будет запрос пользователя). Итак, как мы можем передать код ввода пользователя в xslt. –

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, который упоминается Lutz Horn:

#!/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> 
Смежные вопросы