2015-10-27 10 views
8

Mam niektóre pliki XML, w których chcę użyć niektórych informacji. Napisałem kod, który odczytuje te pliki, a następnie szuka pewnych warunków.Wyodrębnianie danych z dokumentu XML korzystającego z przestrzeni nazw

Problemem jest to, że plik XML rozpoczyna

<SquishReport version="2.1" xmlns="http://www.froglogic.com/XML2"> 

i Perl nie mógł ich odczytać (przynajmniej w moim kodu!). Ale kiedy jestem dołączanie te linie w pierwszej linii XML pliku

<?xml version="1.0" encoding="UTF-8"?> 
    <?xml-stylesheet type="text/xsl"?> 

działa bardzo dobrze.

Niektóre linie z moim pliku XML test.xml:

<SquishReport version="2.1" xmlns="http://www.froglogic.com/XML2"> 
    <test name="TEST"> 
     <prolog time="2015-10-01T03:45:22+02:00"/> 
     <test name="tst_start_app"> 
      <prolog time="2015-02-01T03:45:23+02:00"/> 
      <message line="38" type="LOG" file="C:\squish\test\sources.py" time="2015-02-01T03:45:23+02:00"> 
       <description> 
       <![CDATA[>> >> >> start: init (global) - testcase C:\squish\test\tst_start_app]]></description> 
      </message> 
     </test> 
    </test> 
</SquishReport> 

oraz kod Perl do odczytu pliku XML:

use strict; 
use warnings; 
use feature 'say'; 
use XML::LibXML; 

# Parse the XML 
my $xml = XML::LibXML->load_xml(location => 'test.xml'); 

# Iterate the entries 
for my $entry ($xml->findnodes('/SquishReport/test/test')) { 
    my $key = $entry->findvalue('@name'); 
    say "$key"; 
} 
+0

Możliwy duplikat [Dlaczego X ML :: LibXML nie znajduje węzłów dla tej kwerendy xpath przy użyciu przestrzeni nazw] (http: // stackoverflow.com/questions/4083550/why-does-xmllibxml-find-no-nodes-for-this-xpath-query-when-using-a-namespace) – nwellnhof

+0

Proszę nie zamykać jako duplikat tego pytania. XML tego pytania jest nielegalne, co komplikuje sprawę i sprawia, że ​​rozwiązanie tego pytania jest nieistotne dla tego pytania. Chciałbym, aby to pytanie było dostępne jako czysty przykład. – ikegami

Odpowiedz

11

korzenia tego dokumentu jest elementem, który ma nazwę SquishReport w przestrzeni nazw http://www.froglogic.com/XML2. Zwięźle, możemy powiedzieć, węzeł główny jest

{http://www.froglogic.com/XML2}SquishReport 


Kiedy ktoś korzysta SquishReport (w przeciwieństwie do prefix:SquishReport) w XPath, która stara się dopasować element, który ma nazwę SquishReport w zerowej przestrzeni nazw. Zwięźle, możemy powiedzieć, że stara się dopasować

{}SquishReport 


Aby określić obszar nazw, jeden używa przedrostków zdefiniowane w context, co następuje:

use strict; 
use warnings; 
use feature qw(say); 

use XML::LibXML    qw(); 
use XML::LibXML::XPathContext qw(); 

my $xpc = XML::LibXML::XPathContext->new(); 
$xpc->registerNs(sr => 'http://www.froglogic.com/XML2'); 

my $doc = XML::LibXML->load_xml(location => 'test.xml'); 
for my $entry ($xpc->findnodes('/sr:SquishReport/sr:test/sr:test', $doc)) { 
    my $key = $entry->findvalue('@name'); 
    say $key; 
} 


Uwaga: Prefiks używany w XPath nie mają żadnego związku z przedrostkami użytymi w dokumencie XML (jeśli istnieją). Powinieneś znać przestrzeń nazw, w której znajdują się elementy, których szukasz, ale nie prefiksy używane przez dany dokument.

+0

Wielkie dzięki za wspaniałą odpowiedź !! – Royeh

+0

To jest naprawdę czyste i jasne! Mam tendencję do korzystania z modułów zbudowanych z 'XML :: LibXML', ale sprawiasz, że wygląda to łatwo tutaj. XML nigdy nie zniknie, a perl ma naprawdę potężne narzędzia do radzenia sobie z nim. –

0

Perl ma tak wiele znakomitych narzędzi XML, dzięki - dzięki wszystkim programistom modułów i libxml2, XML wydaje się prawie łatwy. Jednym z tych narzędzi jest XML::Dataset - wygodny moduł "do rusztowania", który opiera się na XML::LibXML i wykorzystuje "profilowy" język znaczników do pobierania danych ze źródeł XML (NB: Oznaczenie profilu jest wrażliwe na białe znaki i zakończenia linii).

np .:

use XML::Dataset; 
use DDP; 

my $xml = "Squish.xml" ; 
open my $fh, "<", $xml or die "aiiieee!"; 
my $test_data = do { local $/; <$fh> }; 

# describe the data using XML::Dataset simplified markup: 
my $data_profile 
    = q(
      SquishReport 
      test 
       test 
       name = dataset:name); 

# parse it with XML::Dataset profile 
my $parsed_data = parse_using_profile($test_data, $data_profile); 

# view the element with Data::Printer 
foreach my $element ($parsed_data->{name}){ 
    p $element ; 
}; 

Squish.xml:

<SquishReport version="2.1" xmlns="http://www.froglogic.com/XML2"> 
    <test name="TEST"> 
     <prolog time="2015-10-01T03:45:22+02:00"/> 
     <test name="tst_start_app"> 
      <prolog time="2015-02-01T03:45:23+02:00"/> 
      <message line="38" type="LOG" file="C:\squish\test\sources.py" time="2015-02-01T03:45:23+02:00"> 
       <description> 
       <![CDATA[>> >> >> start: init (global) - testcase C:\squish\test\tst_start_app]]></description> 
      </message> 
     </test> 
    </test> 
</SquishReport> 

wyjściowa:

\ [ 
    [0] { 
     name "tst_start_app" 
    } 
] 
Powiązane problemy