2010-06-28 8 views
11

libxml2가 시스템에 설치되었다고 가정하고 gcc file.c -lxml2를 사용하여 경고없이 컴파일하는 일부 코드를 여기 붙여 넣습니다.libxml2에서 네임 스페이스 및 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); 
} 

내 문제는 내가 다음 XML

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

책 요소가 요소 내에 네임 스페이스를 정의를 구문 분석 할 것입니다. 나는 xpath/book/section1에 값을 출력하려고하고 NULL을 반환한다. 요소를 네임 스페이스 아래로 반환하려고하면 오류가 발생합니다. 즉,/new : book/section1

네임 스페이스 접두사를 올바르게 사용하지 않아서 코드가 실패했다고 가정합니다. 나는 시간이 없어. 도와 주실 수 있겠습니까?

답변

2

기본 네임 스페이스에 문제가 있습니다./new : tag/new : 태그 등등

3

이것은 libXml 라이브러리의 성가신 실패입니다.

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

두 가지 선택 : cateof에서 언급 한 바와 같이, 문제는 기본 네임 스페이스 선언입니다
(1)에서 그 선언을 제거 책 태그 또는 (2)에 이름을 지정하고 태그에 해당 이름을 사용하십시오.

의 xmlns : 새로운 = "http://www.example.com/new"

그런 다음 태그 모두는 다음과 같다 :

새로운 : 새 책 : 등등 섹션 1

및 .

+2

이 가능 말할 수 있나요'일부 네임 스페이스를 통해 그것을 반복하지 않도록하기 위해/문서의 모든 요소에 대한 암시 적 기본값임을 libxml' 및 XPath 쿼리에서 끝났습니까? – SasQ

28

는 libXml 가 제대로는 XML/XPATH 사양을 따르기 때문에이 문제입니다, 내가 , here에서 발견으로 정말 libXml의 실패 아니다 밝혀졌습니다.

그러나 분석중인 XML 문서를 제어 할 수있는 경우 R Bourdeau가 제안한 해결 방법은 정확합니다.

XPATH 쿼리의 컨텍스트는 xml 문서의 네임 스페이스 한정자입니다. 기본 네임 스페이스는 모든 하위 태그를 네임 스페이스로 강제합니다. 그들은 의 문서에서을 요구하지 않지만 이 xpath 쿼리에서 규정되어야합니다. 다행스럽게도 libXml을 사용하여 네임 스페이스를 new으로 등록 했으므로 cateof의 솔루션이 작동해야합니다.

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

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

내가 가시성 여기를 XML을 인라인 해요 :

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

XPath와 네임 스페이스와 관련된 첫 번째 대답은 실제로 무엇이 일어나고 있으며 어떻게 해결되는지를 설명합니다. 내 친구 진심으로 감사드립니다. –