2012-06-27 194 views
0

我是C編程新手。我想創建可以使用libxml2讀取XML文件的C程序。 我測試此代碼:嘗試解析xml文件時出現分段錯誤

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <libxml/xmlmemory.h> 
#include <libxml/parser.h> 

// Declare functions 
void parseSystemProperties(char *xmlFileName); 
void parseSystemModules(xmlDocPtr doc, xmlNodePtr cur); 
void parseSystemConfiguration(xmlDocPtr doc, xmlNodePtr cur); 
void parseProfiles(xmlDocPtr doc, xmlNodePtr cur); 
void parseMonitoringPort(xmlDocPtr doc, xmlNodePtr cur); 
void parseWebServicePort(xmlDocPtr doc, xmlNodePtr cur); 
void parseBindingInterfaces(xmlDocPtr doc, xmlNodePtr cur); 
void parseExtensions(xmlDocPtr doc, xmlNodePtr cur); 

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

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

    // Get the file name from the argv[1] 
    xmlFileName = argv[1]; 

    // Custom function to parse XML file 
    parseSystemProperties(xmlFileName); 

    return (1); 
} 

// Parsing the XML file and Reading the Element Nodes 

void parseSystemProperties(char *xmlFileName) { 
    xmlDocPtr doc; // pointer to parse xml Document 
    xmlNodePtr cur; // node pointer. It interacts with individual node 

    // Parse XML file 
    doc = xmlParseFile(xmlFileName); 

    // Check to see that the document was successfully parsed. 
    if (doc == NULL) { 
     fprintf(stderr, "Error!. Document is not parsed successfully. \n"); 
     return; 
    } 

    // Retrieve the document's root element - system-properties 
    cur = xmlDocGetRootElement(doc); 

    // Check to make sure the document actually contains something 
    if (cur == NULL) { 
     fprintf(stderr, "Document is Empty\n"); 
     xmlFreeDoc(doc); 
     return; 
    } 

    /* We need to make sure the document is the right type. 
    * "system-properties" is the root type of the documents used in user Config XML file 
    */ 
    if (xmlStrcmp(cur->name, (const xmlChar *) "system-properties")) { 
     fprintf(stderr, "Cannot find system-properties"); 
     xmlFreeDoc(doc); 
     return; 
    } 

    /* Get the first child node of cur. 
    * At this point, cur points at the document root, 
    * which is the element "root" 
    */ 

    cur = cur->xmlChildrenNode; 

    // This loop iterates through the elements that are children of "root" 
    while (cur != NULL) { 
     if ((!xmlStrcmp(cur->name, (const xmlChar *) "system-modules"))) { 
      parseSystemModules(doc, cur); 
     } 
     cur = cur->next; 
    } 


    cur = cur->xmlChildrenNode; 

    // This loop iterates through the elements that are children of "root" 
    while (cur != NULL) { 
     if ((!xmlStrcmp(cur->name, (const xmlChar *) "system-configuration"))) { 
      parseSystemConfiguration(doc, cur); 
     } 
     cur = cur->next; 
    } 

    /* Save XML document to the Disk 
    * Otherwise, you changes will not be reflected to the file. 
    * Currently it's only in the memory 
    */ 
    // xmlSaveFormatFile (xmlFileName, doc, 1); 

    /* free the document */ 
    xmlFreeDoc(doc); 

    /* 
    * Free the global variables that may 
    * have been allocated by the parser. 
    */ 
    xmlCleanupParser(); 

    return; 

} // end of function 

// Get Modules part 
// ------------------------------------------- 

void parseSystemModules(xmlDocPtr doc, xmlNodePtr cur) { 
    xmlChar *key; 
    xmlAttrPtr attr; 

    // Get the sub Element Node of system-configuration node 
    cur = cur->xmlChildrenNode; 

    // This loop iterates through the elements that are children of system-configuration 
    while (cur != NULL) { 
     if ((!xmlStrcmp(cur->name, (const xmlChar *) "extensions"))) { 
      parseExtensions(doc, cur); 
     } 
     cur = cur->next; 
    } 

    return; 

} // end of function() 

void parseExtensions(xmlDocPtr doc, xmlNodePtr cur) { 
    xmlChar *key; 
    xmlAttrPtr attr; 

    // Get the sub Element Node of Profiles node 
    cur = cur->xmlChildrenNode; 

    // This loop iterates through the elements that are children of Profiles 
    while (cur != NULL) { 
     if ((!xmlStrcmp(cur->name, (const xmlChar *) "extension"))) { 
      key = xmlGetProp(cur, (const xmlChar*) "module"); 
      fprintf(stderr, "module: %s\n", key); 
      xmlFree(key); 
     } 
     cur = cur->next; 
    } 

    return; 

} // end of function() 



// Get Configuration part 
// ------------------------------------------- 

void parseSystemConfiguration(xmlDocPtr doc, xmlNodePtr cur) { 
    xmlChar *key; 
    xmlAttrPtr attr; 

    // Get the sub Element Node of system-configuration node 
    cur = cur->xmlChildrenNode; 

    // This loop iterates through the elements that are children of system-configuration 
    while (cur != NULL) { 
     if ((!xmlStrcmp(cur->name, (const xmlChar *) "profiles"))) { 
      parseProfiles(doc, cur); 
     } 
     cur = cur->next; 
    } 

    return; 

} // end of function() 

void parseProfiles(xmlDocPtr doc, xmlNodePtr cur) { 
    xmlChar *key; 
    xmlAttrPtr attr; 

    // Get the sub Element Node of Profiles node 
    cur = cur->xmlChildrenNode; 

    // This loop iterates through the elements that are children of Profiles 
    while (cur != NULL) { 
     if ((!xmlStrcmp(cur->name, (const xmlChar *) "profile"))) { 
      // Get monitoring-port 
      parseMonitoringPort(doc, cur); 
      // Get web-service-port 
      parseWebServicePort(doc, cur); 
      parseBindingInterfaces(doc, cur); 
     } 
     cur = cur->next; 
    } 

    return; 

} // end of function() 


// Monitoring Port 

void parseMonitoringPort(xmlDocPtr doc, xmlNodePtr cur) { 
    xmlChar *key; 
    xmlAttrPtr attr; 

    // Get the sub Element Node of Profile node 
    cur = cur->xmlChildrenNode; 

    // This loop iterates through the elements that are children of Profile 
    while (cur != NULL) { 
     if ((!xmlStrcmp(cur->name, (const xmlChar *) "monitoring-port"))) { 
      key = xmlGetProp(cur, (const xmlChar*) "port"); 
      fprintf(stderr, "monitoring-port: %s\n", key); 
      xmlFree(key); 
     } 
     cur = cur->next; 
    } 

    return; 

} // end of function() 


// web service port 

void parseWebServicePort(xmlDocPtr doc, xmlNodePtr cur) { 
    xmlChar *key; 
    xmlAttrPtr attr; 

    // Get the sub Element Node of Profile node 
    cur = cur->xmlChildrenNode; 

    // This loop iterates through the elements that are children of "root" 
    while (cur != NULL) { 
     if ((!xmlStrcmp(cur->name, (const xmlChar *) "web-service-port"))) { 
      //parseMonitoringPort (doc, cur); 
      key = xmlGetProp(cur, (const xmlChar*) "port"); 
      fprintf(stderr, "web-service-port: %s\n", key); 
      xmlFree(key); 
     } 
     cur = cur->next; 
    } 

    return; 

} // end of function() 


// binding interface 

void parseBindingInterfaces(xmlDocPtr doc, xmlNodePtr cur) { 
    xmlChar *key; 
    xmlAttrPtr attr; 

    // Get the sub Element Node of Profile node 
    cur = cur->xmlChildrenNode; 

    // This loop iterates through the elements that are children of "root" 
    while (cur != NULL) { 
     if ((!xmlStrcmp(cur->name, (const xmlChar *) "socket-binding"))) { 
      //parseMonitoringPort (doc, cur); 
      key = xmlGetProp(cur, (const xmlChar*) "interface"); 
      fprintf(stderr, "interface: %s\n", key); 
      xmlFree(key); 
     } 
     cur = cur->next; 
    } 

    return; 

} // end of function() 

這是我想讀XML:

<?xml version="1.0" encoding="UTF-8"?> 
<system-properties version="1.0"> 
    <system-modules> 
     <extensions> 
      <extension module="NetworkModule"/> 
      <extension module="MonitoringModule"/> 
      <extension module="OracleModule"/> 
      <extension module="DataFilterModule"/>   
     </extensions> 
    </system-modules> 
    <system-configuration> 
     <profiles> 
      <profile name="default"> 
       <monitoring-port port="6051"/> 
       <web-service-port port="7050"/> 
       <socket-binding interface="management" ipaddress="192.168.1.101" port="6050"/> 
       <socket-binding interface="monitoring" ipaddress="192.168.1.106" port="7050"/> 
       <network-pool threads="40"/>      
      </profile> 
     </profiles> 
    </system-configuration> 
</system-properties> 

不幸的是我得到這個錯誤,當我運行示例:

[[email protected] Ctest]$ ./test xmlfile.xml 
module: NetworkModule 
module: MonitoringModule 
module: OracleModule 
module: DataFilterModule 
Segmentation fault (core dumped) 
[[email protected] Ctest]$ 

當我刪除此行代碼的作品:

cur = cur->xmlChildrenNode; 

    // This loop iterates through the elements that are children of "root" 
    while (cur != NULL) { 
     if ((!xmlStrcmp(cur->name, (const xmlChar *) "system-modules"))) { 
      parseSystemModules(doc, cur); 
     } 
     cur = cur->next; 
    } 

你能幫我解決這個問題嗎?

+0

太多的代碼,我會說。請嘗試儘量減少代碼,儘可能以最小的例子來展示問題。 – unwind

+0

問題出在parseSystemProperties函數中。 – user1285928

+0

你能告訴我如何將'parseSystemProperties'分成兩個函數嗎? – user1285928

回答

1

問題是在這裏:

// This loop iterates through the elements that are children of "root" 
while (cur != NULL) { 
    if ((!xmlStrcmp(cur->name, (const xmlChar *) "system-modules"))) { 
     parseSystemModules(doc, cur); 
    } 
    cur = cur->next; 
} 


cur = cur->xmlChildrenNode; 

while退出時curNULL &提領它下一個聲明即。 cur = cur->xmlChildrenNode;因此在cur->xmlChildrenNode崩潰。
也許你可以嘗試做的單迴路的比較,也許在這些線路上:

while (cur != NULL) { 
    if ((!xmlStrcmp(cur->name, (const xmlChar *) "system-modules"))) { 
     parseSystemModules(doc, cur); 
    } 
    else if ((!xmlStrcmp(cur->name, (const xmlChar *) "system-configuration"))) { 
     parseSystemConfiguration(doc, cur); 
    } 
    cur = cur->next; 
} 

希望這有助於!

+0

第二項提案正在起作用。但有沒有更好的方法來編寫'parseSystemProperties'。我想添加更多的XML子元素。 – user1285928

+0

你想在哪裏添加子元素? '系統properties'?上面的解決方案是可行的,因爲'system-properties'有2個子節點'system-module'&'system-configuration'。不需要從根節點獲取下一個子節點,即'system-properties'的* sibling *。如果你添加更多的節點@系統配置和系統模塊的層次,也就是'system-properties'的子節點,你將需要爲它們添加更多的'if - else - if ...'(或者也許更優雅的方式來處理)。如果您在'system-properties'的級別添加,那麼您將需要進行調用以獲取下一個子節點 –

1

嘗試:

cur = (cur) ? cur->xmlChildrenNode : NULL; 

你也可以將其添加到循環邏輯:

for(cur = (cur) ? cur->xmlChildrenNode: NULL; cur; cur = cur->next) { 
// This loop iterates through the elements that are children of "root" 
    if ((!xmlStrcmp(cur->name, (const xmlChar *) "system-modules"))) { 
     parseSystemModules(doc, cur); 
    } 

} 
+0

我測試過了,但沒有任何好的結果。也許解決方案是將函數parseSystemProperties分成兩個小函數。 – user1285928

+0

您可以使用兩次相同的cur變量,而不需要重新初始化。在第一個循環結束時,它將始終爲NULL。 – wildplasser

相關問題