XML :: LibXML findnodes () die Ergebnisse nicht zurück, wenn Xmlns vorhanden ist

stimmen
1

Ich bin mit XML :: LibXML :: Reader ein großen Dokument zu analysieren und habe sie zu einem Problem führen, wobei das Attribut xmlns verursacht findnodes () zum Scheitern verurteilt. Ich reparierte sie durch hinzugefügt Regex die xmls entfernen Attribut, aber ich frage mich, ob es eine elegantere Lösung war keine reguläre Ausdrücke beteiligt sind. Wenn Sie die regex Linie ($ xml = ~ s {Xmlns ...) entfernen werden Sie sehen, dass sagen Loc = $ loc erzeugt keine Ergebnisse.

Hier ist der Code:

use strict;
use warnings;
use feature qw( say );
use XML::LibXML::Reader qw( XML_READER_TYPE_ELEMENT );

my $xml = <<'__EOI__';
<url xmlns=http://www.sitemaps.org/schemas/sitemap/0.9>
    <loc>http://example.com</loc>
    <lastmod>2018-10-19</lastmod>
</url>
__EOI__


$xml =~ s{xmlns=http://www.sitemaps.org/schemas/sitemap/0.9}{};

my $reader = XML::LibXML::Reader->new( string => $xml);
while ( $reader->read ) {
    next unless $reader->nodeType == XML_READER_TYPE_ELEMENT;
    next unless $reader->name eq 'url';
    my $xml = $reader->readOuterXml;
    my $doc = XML::LibXML->load_xml(string => $xml);
    say Doc = $doc;
    my ($loc) = $doc->findnodes('//loc');
    say Loc = $loc;
}
Veröffentlicht am 20/10/2018 um 12:37
quelle vom benutzer
In anderen Sprachen...                            


2 antworten

stimmen
4

Sie fragen Knoten mit Namensraum für null und mit Namen zu finden loc. Es gibt keine solche Knoten in dem Dokument, so findnodesnichts richtig zurückgibt.

Sie mögen die Knoten mit Namensraum finden http://www.sitemaps.org/schemas/sitemap/0.9und mit dem Namen loc. Sie können die folgenden Befehle verwenden , das zu erreichen:

my $doc = XML::LibXML->load_xml( string => $xml );

my $xpc = XML::LibXML::XPathContext->new();
$xpc->registerNs( sm => 'http://www.sitemaps.org/schemas/sitemap/0.9' );

my ($loc) = $xpc->findnodes('//sm:loc', $doc);
Beantwortet am 20/10/2018 um 13:23
quelle vom benutzer

stimmen
1

Der Code beginnt mit der Verwendung von XML::LibXML::ReaderAPI und verwendet dann später XML::LibXML->load_xmleinen DOM aus einem Teil des Dokuments zu erstellen. Die XML::LibXML::ReaderAPI ist in der Regel nur mit großen XML - Dokumenten verwendet , die große Mengen an Speicher verbrauchen würde , wenn sie als DOM geladen. Wenn Ihr XML - Dokument nicht sehr groß ist, dann ist es viel einfacher , einen Ansatz zu verwenden , wie ikegami Antwort , die nur das DOM - API verwendet , um das gesamte Dokument zu laden und dann fragen sie mit XPath.

Wenn Sie jedoch wirklich ein großes XML-Dokument zu tun haben, dann können Sie bei der Lösung des Problems mit dem Reader API interessieren:

my $sitemap_uri = 'http://www.sitemaps.org/schemas/sitemap/0.9';
my $xpc = XML::LibXML::XPathContext->new();
$xpc->registerNs(sm => $sitemap_uri);

my $reader = XML::LibXML::Reader->new(location => './sitemap.xml');
while ($reader->read) {
    $reader->nextElement('url', $sitemap_uri) or last;
    my $doc = $reader->copyCurrentNode(1);
    say "Doc = $doc";
    my ($loc) = $xpc->findnodes('//sm:loc', $doc);
    say "Loc = $loc";
}

Der Aufruf $reader->nextElementist eine schnelle Art und Weise vorwärts zu dem nächsten Auftreten eines bestimmten Elements zu überspringen. In diesem Beispiel abgestimmt ich sowohl auf den Elementnamen und es ist Namespace.

Der Aufruf $reader->copyCurrentNode(1)ist eine bequeme Methode, diesen Knoten zurückgibt und alle ist es geordneten Knoten als DOM - Fragment. Sie werden verwenden müssen , XML::LibXML::XPathContextdass die DOM - Namespace-aware XPath - Anweisungen abfragen.

Meine XML :: LibXML Tutorial gehört Berichte über die Arbeit mit XML - Namen sowie das Arbeiten mit großen Dokumenten .

Beantwortet am 21/10/2018 um 01:29
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more