2010-06-28 21 views
11

estoy pegando un cierto código que compila aquí sin previo aviso usando gcc file.c -lxml2, suponiendo que libxml2 está instalado en su sistema.error libxml2 con espacios de nombres y XPath

#include <libxml/parser.h> 
#include <libxml/xpath.h> 
#include <assert.h> 
#include <libxml/tree.h> 
#include <libxml/xpathInternals.h> 

xmlDocPtr 
getdoc (char *docname) { 
    xmlDocPtr doc; 
    doc = xmlParseFile(docname); 

    if (doc == NULL) { 
     fprintf(stderr,"Document not parsed successfully. \n"); 
     return NULL; 
    } 

    return doc; 
} 

xmlXPathObjectPtr 
getnodeset (xmlDocPtr doc, xmlChar *xpath){ 

    xmlXPathContextPtr context; 
    xmlXPathObjectPtr result; 

    context = xmlXPathNewContext(doc); 
    if (context == NULL) { 
     printf("Error in xmlXPathNewContext\n"); 
     return NULL; 
    } 

    if(xmlXPathRegisterNs(context, BAD_CAST "new", BAD_CAST "http://www.example.com/new") != 0) { 
     fprintf(stderr,"Error: unable to register NS with prefix"); 
     return NULL; 
    } 

    result = xmlXPathEvalExpression(xpath, context); 
    xmlXPathFreeContext(context); 
    if (result == NULL) { 
     printf("Error in xmlXPathEvalExpression\n"); 
     return NULL; 
    } 
    if(xmlXPathNodeSetIsEmpty(result->nodesetval)){ 
     xmlXPathFreeObject(result); 
       printf("No result\n"); 
     return NULL; 
    } 
    return result; 
} 

int 
main(int argc, char **argv) { 

    char *docname; 
    xmlDocPtr doc; 
    xmlChar *xpath = (xmlChar*) "/new:book/section1"; 
    xmlNodeSetPtr nodeset; 
    xmlXPathObjectPtr result; 
    int i; 
    xmlChar *keyword; 

    if (argc <= 1) { 
     printf("Usage: %s docname\n", argv[0]); 
     return(0); 
    } 

    docname = argv[1]; 
    doc = getdoc(docname); 
    result = getnodeset (doc, xpath); 
    if (result) { 
     nodeset = result->nodesetval; 
     for (i=0; i < nodeset->nodeNr; i++) { 
      keyword = xmlNodeListGetString(doc, nodeset->nodeTab[i]->xmlChildrenNode, 1); 
     printf("keyword: %s\n", keyword); 
     xmlFree(keyword); 
     } 
     xmlXPathFreeObject (result); 
    } 

    xmlFreeDoc(doc); 
    xmlCleanupParser(); 
    return (1); 
} 

Mi problema es que quiero analizar el siguiente código XML

<?xml version="1.0" encoding="UTF-8"?> 
<book xmlns="http://www.example.com/new"> 
    <section1>Sec_1</section1> 
    <section2>Sec_2</section2> 
</book> 

el elemento libro define un espacio de nombres dentro de ese elemento. Quiero imprimir el valor en xpath/book/section1 y devuelve NULL. Cuando intento devolver el elemento en un espacio de nombres, también obtengo errores, es decir,/nuevo: libro/sección1

Supongo que mi código falla porque no estoy usando correctamente los prefijos del espacio de nombres. Me quedo sin tiempo. ¿Podrias ayudarme por favor?

Respuesta

2

que es un problema con el espacio de nombres predeterminado. Para que coincida con una ruta que necesita/nueva: etiqueta/nueva: etiqueta y así sucesivamente

3

Esto es una falla molesta de la biblioteca libXml. Como se ha señalado por cateof, el problema es la declaración de espacio de nombres por defecto:

xmlns = "" http://www.example.com/new

dos opciones:
(1) deshacerse de esa declaración su etiqueta del libro o (2) le dan un nombre, y el uso de ese nombre en sus etiquetas.

p. Ej.

xmlns: nueva = "http://www.example.com/new"

A continuación, las etiquetas de todos se parecen:

nuevo: Libro nueva: section1

etc. .

+2

¿Es posible decir 'libxml' que algún espacio de nombres por defecto es/implícita para todos los elementos de un documento para evitar repetir una y más en consultas XPath? – SasQ

28

Resulta que, como descubrí de here, no es realmente un fracaso de LibXML, es un problema porque LibXML correctamente sigue las especificaciones de XML/XPath.

Las soluciones propuestas por R Bourdeau son correctas, sin embargo, si usted tiene el control del documento XML que está analizando.

El contexto de la consulta XPATH es independiente de los calificadores del espacio de nombres en el documento xml. El espacio de nombre predeterminado fuerza a todas las etiquetas secundarias a un espacio de nombres; que no requieren cualificación en el documento pero deben ser calificados en la consulta XPath. Afortunadamente, registró el espacio de nombres como new con libXml, por lo que la solución de cateof debería funcionar.

xmlXPathRegisterNs(context, BAD_CAST "new", BAD_CAST "http://www.example.com/new" 

xmlChar *xpath = (xmlChar*) "/new:book/new:section1"; 

estoy Inlining el xml aquí para la visibilidad:

<?xml version="1.0" encoding="UTF-8"?> 
<book xmlns="http://www.example.com/new"> 
    <section1>Sec_1</section1> 
    <section2>Sec_2</section2> 
</book> 
+2

Esta es la primera respuesta relacionada con XPath y el espacio de nombres que realmente explicaron qué estaba pasando y cómo resolverlo. Mi más sincero agradecimiento a usted, mi amigo. –

Cuestiones relacionadas