2015-03-25 1 views
1

Я пытался разделить данные XML с помощью XML::LibXML модуль, но он выдает ошибку, как этотОшибка при попытке разделить XML-файл с помощью модуля XML :: Libxml

Can't call method "findnodes" without a package or object reference 

Мой вход

<xml> 
    <bhap id="1"> 
    <label>cylind - I</label> 
    <title>premier</title> 
    <rect id="S1"> 
     <title>Short</title> 
     <label>1.</label> 
     <p><text>welcome</text></p> 
    </rect> 
    <rect id="S2"> 
     <title>Definite</title> 
     <label>2.</label> 
     <p><text>welcome1</text></p> 
    </rect> 
    </bhap> 
    <bhap id="2"> 
    <label>cylind – II</label> 
    <title>AUTHORITIES AND ITS EMPLOYEES</title> 
    <rect id="S3"> 
     <title>nauty.&#x2014;</title> 
     <label>3.</label> 
     <p><text>welcome3</text></p> 
    </rect> 
    <rect id=S4"> 
     <title>Term</title> 
     <label>4.</label> 
     <p><text>welcome4</text></p> 
    </rect> 
    </bhap> 
</xml> 

выход необходим

файл 1

<xml> 
    <bhap id="1"> 
    <label>cylind - I</label> 
    <title>premier</title> 
    <rect id="S1"> 
     <title>Short</title> 
     <label>1.</label> 
     <p><text>welcome</text></p> 
    </rect> 
    </bhap> 
</xml> 

файл 2

<xml> 
    <bhap id="1"> 
    <label>cylind - I</label> 
    <title>premier</title> 
    <rect id="S2"> 
     <title>Definite</title> 
     <label>2.</label> 
     <p><text>welcome1</text></p> 
    </rect> 
    </bhap> 
</xml> 

файл 3

<xml> 
    <bhap id="2"> 
    <label>cylind – II</label> 
    <title>AUTHORITIES AND ITS EMPLOYEES</title> 
    <rect id="S3"> 
     <title>nauty.&#x2014;</title> 
     <label>3.</label> 
     <p><text>welcome3</text></p> 
    </rect> 
    </bhap> 
</xml> 

файл 4

<xml>  
    <bhap id="2"> 
    <label>cylind – II</label> 
    <title>AUTHORITIES AND ITS EMPLOYEES</title> 
    <rect id=S4"> 
     <title>Term</title> 
     <label>4.</label> 
     <p><text>welcome4</text></p> 
    </rect> 
    </bhap> 
</xml> 

мой код

use XML::LibXML; 

my $file = shift || die "usage $0 <xmlfile>"; 
my $parser = XML::LibXML->new(); 
my $doc = $parser->parse_file($file); 

my @nodes = $doc->findnodes('//bhap'); 
foreach my $node1 (@nodes) { 

    my $bhap = $node1->toString(), "\n"; 

    if ($bhap =~ m/(<bhap.+?>.+?<\/title>)(.+?)(<\/bhap>)/is) { 

     my $bhap1 = $1; 
     my $bhap2 = $2; 
     my $bhap3 = $3; 

     my $nodes1 = $bhap->findnodes('//rect'); 
     foreach my $node (@$nodes1) { 

      my $rect = $node->toString(); 

      if ($rect =~ m/(<rect\s*id="(.+?)">.+?<\/rect>)/is) { 

       my $var1 = $1; 
       my $var2 = $2; 

       print "file" $var2; 
       print "<xml>" print $bhap1; 
       print $var1; 
       print $bhap3; 
       print "</xml>"; 
      } 
     } 
    } 
} 
+0

Это xml_split вариант: http://search.cpan.org/dist/XML-Twig/tools/xml_split/xml_split – Sobrique

+1

Вы назначаете '$ bhap' и т. Д., Затем читаете из' $ bhap'. Использование 'use warnings; используйте строгий, 'ловит такого рода вещи. – reinierpost

+1

'my $ nodes1 = $ bhap-> findnodes ('// rect');' Вы вызываете 'findnodes' строку здесь. – nwellnhof

ответ

1

ОК, так что вы начинаете хорошо, но потом. .. попадают в ловушку «регулярного выражения». XML не очень хорошо разбирается с регулярными выражениями, потому что он слишком сложный - делайте это хорошо, вам нужно обрабатывать/проверять вложенные теги, линейные каналы и всевозможные вещи, которые в основном просто делают ваше регулярное выражение хрупкой частью код. Так что, пожалуйста.

Но самое главное - ВСЕГДА используйте strict и warnings перед отправкой запросов. Это ваш первый порт для устранения неполадок.

Если вы увидите что-то вроде:

print "file" $var2; 

Это не будет работать - на всех. Там есть множество других, которые не будут работать должным образом в «вашем коде», так что это будет отправной точкой.

Кроме того - ваш XML не является допустимым - ваш «S4» Я думаю, что не хватает кавычки.

Во всяком случае, если предположить, что это просто опечатка, я хотел бы начать с XML::Twig (потому что я понимаю его лучше, чем Libxml, а не какой-либо конкретной причины) и сделать что-то вроде этого:

#!/usr/bin/perl 

use strict; 
use warnings; 
use XML::Twig; 

my %children_of; 

#as we process, extract all the 'rect' elements - along with a reference to their context. 
sub process_rect { 
    my ($twig, $rect) = @_; 
    push(@{ $children_of{ $rect->parent } }, $rect->cut); 
} 


my $twig = XML::Twig->new(
    'pretty_print' => 'indented', 
    'twig_handlers' => { 'rect' => \&process_rect }, 

); 

$twig->parse(\*DATA); 

#run through all the 'bhap' elements. 
foreach my $bhap ($twig->root->children('bhap')) { 
    #find the rect elements under this bhap. 
    foreach my $rect (@{ $children_of{$bhap} }) { 
     #create a new XML document - copy the 'root' name from your original document. 
     my $xml = XML::Twig::Elt->new($twig -> root -> name); 
     #duplicate this 'bhap' element by copying it, rather than cutting it, 
     #so we can paste it more than once (e.g. per 'rect') 
     my $subset = $bhap->copy; 
     #insert the 'bhap' into our new xml. 
     $subset->paste(last_child => $xml); 
     #insert our cut rect beneath this bhap. 
     $rect->paste(last_child => $subset); 

     #print the resulting XML. 
     print "--\n"; 
     $xml->print; 
    } 
} 

__DATA__ 
<xml> 

<bhap id="1"> 
       <label>cylind - I</label> 
       <title>premier</title> 
       <rect id="S1"> 
        <title>Short</title> 
        <label>1.</label> 
        <p><text>welcome</text></p> 
       </rect> 
       <rect id="S2"> 
        <title>Definite</title> 
        <label>2.</label> 
        <p><text>welcome1</text></p> 
       </rect> 
     </bhap> 
      <bhap id="2"> 
       <label>cylind - II</label> 
       <title>AUTHORITIES AND ITS EMPLOYEES</title> 

       <rect id="S3"> 
        <title>nauty.&#x2014;</title> 
        <label>3.</label> 
        <p><text>welcome3</text></p> 
       </rect> 

       <rect id="S4"> 
        <title>Term</title> 
        <label>4.</label> 
        <p><text>welcome4</text></p> 
       </rect></bhap> 

</xml> 

Мы Обрабатывает XML, и «вырезать» узлы rect. Затем мы перебираем каждый из узлов bhap - копируем их и вставляем под ними rect.

Это дает выход:

-- 
<xml> 
    <bhap id="1"> 
    <label>cylind - I</label> 
    <title>premier</title> 
    <rect id="S1"> 
     <title>Short</title> 
     <label>1.</label> 
     <p> 
     <text>welcome</text> 
     </p> 
    </rect> 
    </bhap> 
</xml> 
-- 
<xml> 
    <bhap id="1"> 
    <label>cylind - I</label> 
    <title>premier</title> 
    <rect id="S2"> 
     <title>Definite</title> 
     <label>2.</label> 
     <p> 
     <text>welcome1</text> 
     </p> 
    </rect> 
    </bhap> 
</xml> 
-- 
<xml> 
    <bhap id="2"> 
    <label>cylind - II</label> 
    <title>AUTHORITIES AND ITS EMPLOYEES</title> 
    <rect id="S3"> 
     <title>nauty.—</title> 
     <label>3.</label> 
     <p> 
     <text>welcome3</text> 
     </p> 
    </rect> 
    </bhap> 
</xml> 
-- 
<xml> 
    <bhap id="2"> 
    <label>cylind - II</label> 
    <title>AUTHORITIES AND ITS EMPLOYEES</title> 
    <rect id="S4"> 
     <title>Term</title> 
     <label>4.</label> 
     <p> 
     <text>welcome4</text> 
     </p> 
    </rect> 
    </bhap> 
</xml> 

который выглядит, по меньшей мере достоверно близко к тому, что вы пытаетесь произвести. Я пропустил чтение в файлах и распечатывал контент, потому что восстановление XML - это более сложная часть.

Я также предложил бы посмотреть на xml_split, который доступен с XML::Twig, поскольку это может сделать именно то, что вы хотите в любом случае.

+0

Я уверен, что это хороший совет, но заявленная проблема - это ошибка «Невозможно вызвать метод« findnodes »без ссылки на пакет или объект», и вы ничего не сказали об этом. – fortboise

Смежные вопросы