2010-06-28 22 views
11

Tôi đang dán một số mã ở đây để biên dịch không có cảnh báo bằng cách sử dụng tệp gcc.c -lxml2, giả sử rằng libxml2 được cài đặt trong hệ thống của bạn.lỗi libxml2 với không gian tên và 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); 
} 

Vấn đề của tôi là tôi muốn phân tích cú pháp xml sau

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

yếu tố cuốn sách định nghĩa một namespace bên trong phần tử đó. Tôi muốn in giá trị trong xpath/book/section1 và nó trả về NULL. Khi tôi cố gắng trả về phần tử dưới một vùng tên, tôi cũng gặp lỗi, tức là/new: book/section1

Tôi giả sử rằng mã của tôi không thành công vì tôi không sử dụng đúng các tiền tố không gian tên. Tôi hết thời gian. Bạn có thể giúp?

Trả lời

2

đó là sự cố với không gian tên mặc định. Để đối sánh đường dẫn bạn cần/mới: thẻ/mới: thẻ và cứ thế

3

Đây là lỗi gây phiền toái của thư viện libXml. Theo ghi nhận của cateof, vấn đề là việc khai báo không gian tên mặc định:

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

Hai lựa chọn:
(1) thoát khỏi tuyên bố rằng trong thẻ sách của bạn hoặc (2) đặt tên cho thẻ và sử dụng tên đó trong thẻ của bạn.

ví dụ:

xmlns: mới = "http://www.example.com/new"

Sau đó, thẻ của bạn tất cả trông giống như:

mới: Cuốn sách mới: Section1

và vân vân .

+2

Có thể nói 'libxml' rằng một số không gian tên là default/tiềm ẩn đối với tất cả các yếu tố trong một tài liệu để tránh lặp lại nó hơn và hơn trong các truy vấn XPath? – SasQ

28

Hóa ra, khi tôi phát hiện ra từ here, nó không phải là thực sự là một thất bại của libxml, đó là một vấn đề bởi vì libxml đúng sau các chi tiết kỹ thuật XML/XPath.

Các giải pháp được đề xuất bởi R Bourdeau là chính xác, tuy nhiên, nếu bạn có quyền kiểm soát tài liệu xml bạn đang phân tích cú pháp.

Ngữ cảnh cho truy vấn XPATH là độc lập của bộ định danh không gian tên trong tài liệu xml. Không gian tên mặc định buộc tất cả các thẻ con vào một không gian tên; họ không yêu cầu chứng chỉ trong tài liệu nhưng phải đủ điều kiện trong truy vấn xpath. May mắn thay, bạn đã đăng ký không gian tên là new với libXml, vì vậy giải pháp của cateof sẽ hoạt động.

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

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

tôi nội tuyến xml vào đây để visibility:

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

Đây là câu trả lời đầu tiên liên quan đến XPath và không gian tên thực sự giải thích những gì đang diễn ra và cách giải quyết nó. Lời cảm ơn chân thành của tôi đến bạn của tôi. –

Các vấn đề liên quan