findnodes XML :: LibXML () δεν επιστρέφει αποτελέσματα όταν xmlns υπάρχει

ψήφοι
1

Είμαι με τη χρήση XML :: LibXML :: Reader για να αναλύσει ένα μεγάλο έγγραφο και έχουν τρέξει σε ένα ζήτημα το οποίο οι xmlns χαρακτηριστικό προκαλεί findnodes () για να αποτύχει. Μου καθορίζεται από προστεθεί ένα regex για να απομακρυνθούν οι XMLs αποδίδουν αλλά Αναρωτιόμουν αν υπήρχε μια πιο κομψή λύση συνεπάγεται κανένα regexes. Αν αφαιρέσετε τη γραμμή regex ($ xml = ~ s {xmlns ...) θα δείτε ότι λέει Loc = $ loc παράγει κανένα αποτέλεσμα.

Εδώ είναι ο κώδικας:

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;
}
Δημοσιεύθηκε 20/10/2018 στις 12:37
πηγή χρήστη
Σε άλλες γλώσσες...                            


2 απαντήσεις

ψήφοι
4

Θα ζητήσω να βρείτε κόμβους με namespace άκυρη και με το όνομα loc. Δεν υπάρχουν τέτοια κόμβους στο έγγραφο, οπότε findnodesσωστά επιστρέφει τίποτα.

Θέλετε να βρείτε τους κόμβους με namespace http://www.sitemaps.org/schemas/sitemap/0.9και το όνομα loc. Μπορείτε να χρησιμοποιήσετε το παρακάτω για να επιτευχθεί αυτό:

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);
Απαντήθηκε 20/10/2018 στις 13:23
πηγή χρήστη

ψήφοι
1

Ο κωδικός σας ξεκινά με τη χρήση του XML::LibXML::ReaderAPI και στη συνέχεια χρησιμοποιεί αργότερα XML::LibXML->load_xmlγια να δημιουργήσει ένα DOM από μέρος του εγγράφου. Το XML::LibXML::ReaderAPI χρησιμοποιείται συνήθως μόνο με τεράστια έγγραφα XML που θα καταναλώνουν μεγάλες ποσότητες μνήμης, όταν φορτωθεί ως DOM. Αν το έγγραφο XML σας δεν είναι τεράστια, τότε είναι πολύ πιο απλό να χρησιμοποιήσει μια προσέγγιση σαν απάντηση της Ikegami που χρησιμοποιεί μόνο το DOM API για να φορτώσει ολόκληρο το έγγραφο και, στη συνέχεια, το ερώτημα αυτό με XPath.

Ωστόσο, αν πραγματικά έχουν μια τεράστια έγγραφο XML, τότε μπορεί να ενδιαφέρονται για την επίλυση του προβλήματος με τη χρήση του API Reader:

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";
}

Η πρόσκληση για $reader->nextElementείναι ένας γρήγορος τρόπος για να μεταβείτε στην επόμενη εμφάνιση του συγκεκριμένου στοιχείου. Σε αυτό το παράδειγμα ταιριάζει τόσο το όνομα του στοιχείου και είναι namespace.

Η πρόσκληση για $reader->copyCurrentNode(1)είναι μια μέθοδος ευκολία που επιστρέφει αυτόν τον κόμβο και όλα είναι παιδί κόμβους ως τμήμα DOM. Θα πρέπει να χρησιμοποιήσετε XML::LibXML::XPathContextτο ερώτημα αυτό το DOM, χρησιμοποιώντας δηλώσεις XPath ονομάτων με επίγνωση.

XML :: LibXML μου φροντιστήριο περιλαμβάνει την κάλυψη της εργασίας με ονομάτων XML , καθώς και σε συνεργασία με μεγάλα έγγραφα .

Απαντήθηκε 21/10/2018 στις 01:29
πηγή χρήστη

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