问题
I am using the library libxml2 to parse an XML document. And then I saw xmlHashTable in this library. Is it possible to get all the keys of a xmlHashTable? I want to store all the keys in an array.
The XML document is:
<?xml version="1.0" encoding="UTF-8"?>
<?type-proto key="MIPRegistrationRequest" value="mip" ?>
<?avp-proto key="Example-AVP" value="data" ?>
<!DOCTYPE dictionary SYSTEM "dictionary.dtd" [
<!-- Any files added here need to be added to Makefile.am and
packaging/nsis/wireshark.nsi -->
<!ENTITY nasreq SYSTEM "nasreq.xml">
<!ENTITY eap SYSTEM "eap.xml">
<!ENTITY mobileipv4 SYSTEM "mobileipv4.xml">
<!ENTITY chargecontrol SYSTEM "chargecontrol.xml">
<!ENTITY sunping SYSTEM "sunping.xml">
<!ENTITY TGPP SYSTEM "TGPP.xml">
<!ENTITY TGPP2 SYSTEM "TGPP2.xml">
<!ENTITY sip SYSTEM "sip.xml">
<!ENTITY etsie2e4 SYSTEM "etsie2e4.xml">
<!ENTITY Ericsson SYSTEM "Ericsson.xml">
<!ENTITY mobileipv6 SYSTEM "mobileipv6.xml">
<!ENTITY Cisco SYSTEM "Cisco.xml">
<!ENTITY Starent SYSTEM "Starent.xml">
<!ENTITY Vodafone SYSTEM "Vodafone.xml">
<!ENTITY AlcatelLucent SYSTEM "AlcatelLucent.xml">
<!ENTITY Nokia SYSTEM "Nokia.xml">
<!ENTITY NokiaSolutionsAndNetworks SYSTEM "NokiaSolutionsAndNetworks.xml">
<!ENTITY HP SYSTEM "HP.xml">
<!ENTITY Oracle SYSTEM "Oracle.xml">
<!ENTITY Custom SYSTEM "Custom.xml">
]>
<dictionary>
...
<dictionary>
I am trying to get the all the keys of the external (parsed) entities (such as nasreq, eap etc):
ddict_t *ddict_scan(const char* system_directory, const char* filename)
{
char *path = g_strconcat((const gchar*) system_directory, (const gchar*)filename, (const gchar *)'\0');
xmlDocPtr p1 = getdoc((const char *)path);
xmlEntitiesTablePtr ptr2 = p1->intSubset->entities;
//to be added
}
The type of xmlEntitiesTable is a xmlHashTable.
回答1:
There is the xmlHashScan() function (and its pickier relatives), which can be used to have a user-provided xmlHashScanner function called back by the library for each entry in the xmlHashTable. The xmlHashScanner is given the name of each entry as parameter, so it should be easy to assemble a list of all the keys that way.
回答2:
Your question is a typical XY problem. An easier way to get the entity declarations is to iterate the children of the DTD node:
xmlDtdPtr dtd = doc->intSubset;
for (xmlNodePtr child = dtd->children; child; child = child->next) {
if (child->type == XML_ENTITY_DECL) {
printf("%s\n", child->name);
}
}
回答3:
For those who want to know more details (especially the code), you can look at my following code which helps me get the key list:
typedef struct _entities_key_list{
xmlChar *name;
struct _entities_key_list *next;
} entities_key_list;
static entities_key_list *head_key_list = NULL;
static entities_key_list *current_key_list = NULL;
/**
* @brief Callback when scanning data in a hash with the simple scanner
* @param the data in the hash
* @param extra scanner data
* @param the name associated
* @return void
*/
void the_callback_function(void *payload, void *data, xmlChar *name){
if(!head_key_list)
{
head_key_list = current_key_list = g_new(entities_key_list, 1);
head_key_list->name = name;
head_key_list->next = NULL;
}
else
{
current_key_list = current_key_list->next = g_new(entities_key_list, 1);
current_key_list->name = name;
current_key_list->next = NULL;
}
}
/**
* @brief Parses the entity inforamtion in the XML document: dictionary.xml
* @param ptr pointer to an XML document
* @return pointer to a linked list of type entity_t
*/
entity_t *parse_entities(xmlDocPtr ptr)
{
xmlHashScanner ptr27 = &the_callback_function;
xmlHashTablePtr ptr28 = (xmlHashTablePtr) ptr->intSubset->entities;
xmlHashScan(ptr28, ptr27, NULL);
puts("**************************************************");
puts("let's test if I have got the great result!");
printf("the result is: %s\n", head_key_list->name);
printf("the result is: %s\n", head_key_list->next->name);
puts("**************************************************");
... //code that is not interesting anymore
}
来源:https://stackoverflow.com/questions/38699706/how-to-get-the-keys-of-a-xmlhashtable-libxml2