2009-03-18 22 views
2

J'ai un exemple de script Perl que j'essaye de charger et de valider un fichier par rapport à un schéma, ils interrogent différents nœuds.Perl, LibXML et Schémas

#!/usr/bin/env perl 
use strict; 
use warnings; 
use XML::LibXML; 

my $filename = 'source.xml'; 
my $xml_schema = XML::LibXML::Schema->new(location=>'library.xsd'); 
my $parser = XML::LibXML->new(); 
my $doc = $parser->parse_file ($filename); 

eval { 
    $xml_schema->validate ($doc); 
}; 

if ([email protected]) { 
    print "File failed validation: [email protected]" if [email protected]; 
} 

eval { 
    print "Here\n"; 
    foreach my $book ($doc->findnodes('/library/book')) { 
     my $title = $book->findnodes('./title'); 
     print $title->to_literal(), "\n"; 

    } 
}; 

if ([email protected]) { 
    print "Problem parsing data : [email protected]\n"; 
} 

Malheureusement, bien qu'il soit valider la fin de fichier XML, il ne trouve pas des articles de livres de $ et donc pas l'impression de quoi que ce soit.

Si je supprime le schéma du fichier XML et la validation du fichier PL, cela fonctionne correctement. J'utilise l'espace de nom par défaut. Si je le change pour ne pas utiliser l'espace de noms par défaut (xmlns: lib = "http://libs.domain.com" et préfixer tous les éléments dans le fichier XML avec lib et modifier les expressions XPath pour inclure le préfixe d'espace de noms (/ lib: bibliothèque/lib: livre), il fonctionne à nouveau fichier

Pourquoi et qu'est-ce que je manque

XML.?

<?xml version="1.0" encoding="utf-8"?> 
<library xmlns="http://lib.domain.com" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://lib.domain.com .\library.xsd"> 
    <book> 
     <title>Perl Best Practices</title> 
     <author>Damian Conway</author> 
     <isbn>0596001738</isbn> 
     <pages>542</pages> 
     <image src="http://www.oreilly.com/catalog/covers/perlbp.s.gif" width="145" height="190"/> 
    </book> 
    <book> 
     <title>Perl Cookbook, Second Edition</title> 
     <author>Tom Christiansen</author> 
     <author>Nathan Torkington</author> 
     <isbn>0596003137</isbn> 
     <pages>964</pages> 
     <image src="http://www.oreilly.com/catalog/covers/perlckbk2.s.gif" width="145" height="190"/> 
    </book> 
    <book> 
     <title>Guitar for Dummies</title> 
     <author>Mark Phillips</author> 
     <author>John Chappell</author> 
     <isbn>076455106X</isbn> 
     <pages>392</pages> 
     <image src="http://media.wiley.com/product_data/coverImage/6X/07645510/076455106X.jpg" width="100" height="125"/> 
    </book> 
</library> 

XSD:

<?xml version="1.0" encoding="utf-8"?> 
<xs:schema xmlns="http://lib.domain.com" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://lib.domain.com"> 
    <xs:attributeGroup name="imagegroup"> 
     <xs:attribute name="src" type="xs:string"/> 
     <xs:attribute name="width" type="xs:integer"/> 
     <xs:attribute name="height" type="xs:integer"/> 
    </xs:attributeGroup> 
    <xs:element name="library"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element maxOccurs="unbounded" name="book"> 
        <xs:complexType> 
         <xs:sequence> 
          <xs:element name="title" type="xs:string"/> 
          <xs:element maxOccurs="unbounded" name="author" type="xs:string"/> 
          <xs:element name="isbn" type="xs:string"/> 
          <xs:element name="pages" type="xs:integer"/> 
          <xs:element name="image"> 
           <xs:complexType> 
            <xs:attributeGroup ref="imagegroup"/> 
           </xs:complexType> 
          </xs:element> 
         </xs:sequence> 
        </xs:complexType> 
       </xs:element> 
      </xs:sequence> 
     </xs:complexType> 
    </xs:element> 
</xs:schema> 

Répondre

3

De l'XML::LibXML docs:

Une erreur commune sur XPath est de supposer que les tests de nœud consistant en un nom d'élément sans éléments correspondance de préfixe dans l'espace de noms par défaut. Cette hypothèse est erronée. Selon la spécification XPath , de tels tests de nœud peuvent ne faire correspondre que des éléments qui ne se trouvent dans aucun espace de noms (c'est-à-dire nul). ... (et plus tard) ... ... La méthode recommandée est d'utiliser le XML::LibXML::XPathContext Module

Ainsi, du point de vue XPath, il n'y a aucun espace de noms « par défaut » ... pour Tout espace de noms non nul, vous devez le spécifier dans votre XPath. Le module XML :: LibXML :: XPathContext vous permet de créer un préfixe pour n'importe quel espace de noms à utiliser dans votre expression XPath.