int ConfigurationXML::parse(const char* configurationXML) { mxml_node_t *tree, *node; int ret; tree = mxmlLoadString(NULL, configurationXML, MXML_NO_CALLBACK); node = mxmlGetFirstChild(tree); while (node && mxmlGetType(node) != MXML_ELEMENT) node = mxmlWalkNext(node, tree, MXML_NO_DESCEND); ret = configurationsTag(node); node = mxmlGetFirstChild(node); while (node) { if (mxmlGetType(node) != MXML_ELEMENT) { node = mxmlWalkNext(node, tree, MXML_NO_DESCEND); continue; } configurationTag(node); node = mxmlWalkNext(node, tree, MXML_NO_DESCEND); } mxmlDelete(tree); return ret; }
int ConfigurationXML::parse(const char* configurationXML) { mxml_node_t *tree, *node; int ret; // clear counter overflow gSessionData->mCounterOverflow = 0; mIndex = 0; // disable all counters prior to parsing the configuration xml for (int i = 0; i < MAX_PERFORMANCE_COUNTERS; i++) { gSessionData->mCounters[i].setEnabled(false); } tree = mxmlLoadString(NULL, configurationXML, MXML_NO_CALLBACK); node = mxmlGetFirstChild(tree); while (node && mxmlGetType(node) != MXML_ELEMENT) node = mxmlWalkNext(node, tree, MXML_NO_DESCEND); ret = configurationsTag(node); node = mxmlGetFirstChild(node); while (node) { if (mxmlGetType(node) != MXML_ELEMENT) { node = mxmlWalkNext(node, tree, MXML_NO_DESCEND); continue; } configurationTag(node); node = mxmlWalkNext(node, tree, MXML_NO_DESCEND); } mxmlDelete(tree); return ret; }
static int l_mxml_getfirstchild(lua_State *L) { mxml_node_t *node; mxml_node_t **rval; node = l_checkMXML(L, 1); if (mxmlGetFirstChild(node) != NULL) { rval = _l_new_node(L); *rval = mxmlGetFirstChild(node); } else { lua_pushnil(L); } return 1; }
static int l_mxml_haschildren(lua_State *L) { mxml_node_t *node; node = l_checkMXML(L, 1); if (mxmlGetFirstChild(node) != NULL) lua_pushnumber(L, 1); else lua_pushnumber(L, 0); return 1; }
int addSignature( char *unsignedMessage, char *signature, char *signedMessage, int size) { mxml_node_t *xDoc; mxml_node_t *messageNode; mxml_node_t *innerNode; xDoc = mxmlLoadString( NULL, unsignedMessage, MXML_NO_CALLBACK); messageNode = mxmlGetFirstChild(xDoc); innerNode = mxmlNewElement(messageNode, "signature"); mxmlNewText(innerNode, 0, signature); //por em base64 ---PROVOCARE ERRO ____ base64 mxmlSaveString (xDoc, message, size, MXML_NO_CALLBACK); mxmlDelete(xDoc); }
static int next_iter(lua_State *L) { mxml_node_t **parent; mxml_node_t **child; mxml_node_t **sib; child = (mxml_node_t **)lua_touserdata(L, lua_upvalueindex(2)); /* First time through child == NULL */ if (child == NULL) { parent = l_checkMXMLP(L, lua_upvalueindex(1)); child = _l_new_node(L); *child = mxmlGetFirstChild(*parent); if (mxmlGetType(*child) == MXML_ELEMENT) { lua_pushvalue(L, -1); lua_replace(L, lua_upvalueindex(2)); return 1; } } do { *child = mxmlGetNextSibling(*child); } while ((*child) && (mxmlGetType(*child) != MXML_ELEMENT)); if (!*child) { lua_pop(L, 1); return 0; } lua_pushvalue(L, -1); lua_replace(L, lua_upvalueindex(2)); return 1; }
int BCF_Read(bcf_t* bcf, const char* filename) { FILE *fp; mxml_node_t *node, *text; int i; if(bcf->filename != NULL) { free(bcf->filename); } bcf->filename = strdup(filename); fp = fopen(filename, "r"); if(fp == NULL) { fprintf(stderr, "Error opening config file %s for reading.\n", filename); return -1; } bcf->root = mxmlLoadFile(NULL, fp, MXML_TEXT_CALLBACK); fclose(fp); /* Now walk through the file and get all the children */ for(i = 0, node = mxmlFindElement(bcf->root, bcf->root, "child", NULL, NULL, MXML_DESCEND); node != NULL; node = mxmlFindElement(node, bcf->root, "child", NULL, NULL, MXML_DESCEND), i++ ) { text = mxmlGetFirstChild(node); bcf->entries[i] = strdup(mxmlGetText(text, NULL)); } bcf->num = i; /* Now read all the dongles */ for(i = 0, node = mxmlFindElement(bcf->root, bcf->root, "dongle", NULL, NULL, MXML_DESCEND); node != NULL; node = mxmlFindElement(node, bcf->root, "dongle", NULL, NULL, MXML_DESCEND), i++ ) { text = mxmlGetFirstChild(node); bcf->dongles[i] = strdup(mxmlGetText(text, NULL)); } bcf->numDongles = i; /* Clean everything up */ mxmlDelete(bcf->root); bcf->root = NULL; return 0; }
static long sFixLocalSyntax(mxmlCtxt *ctxt, mxmlNode *root) { long count, status; char *copy, *value; mxmlNode *node, *textNode, *cdataNode; mxmlNodeList *nodeList; /* * Local Syntax - Required. */ /* Get the value of this node. */ status = sReadTextNodeValue(ctxt, root, KW_LOCAL_SYNTAX, &value, CMD_REQUIRED); if (status != eOK) return status; /* Get all nodes matching this node name. */ nodeList = mxmlGetElementsByTagName(ctxt, root, KW_LOCAL_SYNTAX); if (! nodeList) { cmd_Error("mxmlGetElementsByTagName: %s", mxmlErrorText(ctxt)); cmd_Error("Could not get requird \"%s\" element(s)", KW_LOCAL_SYNTAX); return eCMD_MISSING_NODE; } /* Get the number of nodes matching this keyword. */ count = mxmlGetNodeListLength(ctxt, nodeList); if (count > 1) { cmd_Error("Found %ld \"%s\" elements - expected 1", KW_LOCAL_SYNTAX, count); return eCMD_TOO_MANY_MATCHES; } /* Get the actual node. */ node = mxmlGetItem(ctxt, nodeList, 0); if (! node) { cmd_Error("mxmlGetItem: %s", mxmlErrorText(ctxt)); cmd_Error("Could not get item from \"%s\" node list", KW_LOCAL_SYNTAX); return mxmlErrorNumber(ctxt); } /* Get the child text node. */ textNode = mxmlGetFirstChild(ctxt, node); if (! textNode) { cmd_Error("mxmlGetFirstChlid: %s", mxmlErrorText(ctxt)); cmd_Error("Could not get child text node"); return mxmlErrorNumber(ctxt); } /* Get the value of this node. */ value = mxmlGetChildTextNodeValue(ctxt, node); if (! value) { cmd_Error("mxmlGetValue: %s", mxmlErrorText(ctxt)); cmd_Error("Could not get value for \"%s\" node", KW_LOCAL_SYNTAX); return mxmlErrorNumber(ctxt); } copy = NULL; misDynStrcpy(©, "\n"); misDynStrcat(©, value); misDynStrcat(©, "\n"); cdataNode = mxmlCreateCDATASection(ctxt, copy); if (status != eOK) { cmd_Error("mxmlCreateCDATASection: %s", mxmlErrorText(ctxt)); cmd_Error("Could not create cdata section"); return mxmlErrorNumber(ctxt); } status = mxmlRemoveChild(ctxt, node, textNode); if (status != eOK) { cmd_Error("mxmlRemoveChild: %s", mxmlErrorText(ctxt)); cmd_Error("Could not remove child node"); return mxmlErrorNumber(ctxt); } cdataNode = mxmlAppendChild(ctxt, node, cdataNode); if (! cdataNode) { cmd_Error("mxmlAppendChlid: %s", mxmlErrorText(ctxt)); cmd_Error("Could not append cdata section"); return mxmlErrorNumber(ctxt); } free(copy); free(value); return eOK; }
void main(void) { FILE *fp; char str[128]; const char *xml_path = "0:\\Zbin\\Utilities\\mxmltest\\test.xml"; fp = fopen(xml_path, "r"); if (fp == NULL) { sprintf(str, "Can't open file: %s", xml_path); ShowMSG(1, (int)str); return; } mxml_node_t *tree = mxmlLoadFile(NULL, fp, MXML_TEXT_CALLBACK); fclose(fp); if (tree == NULL) { ShowMSG(1, (int)"mxmlLoadFile = NULL"); return; } const char *log_path = "0:\\Zbin\\Log\\mxmltest.log"; fp = fopen(log_path, "a"); if (fp == NULL) { sprintf(str, "Can't open file: %s", log_path); ShowMSG(1, (int)str); mxmlDelete(tree); return; } mxml_node_t *node = tree; mxml_node_t *next = NULL; while (node != NULL) { switch (mxmlGetType(node)) { case MXML_ELEMENT: sprintf(str, "MXML_ELEMENT = %s\n", mxmlGetElement(node)); fwrite(str, sizeof(char), strlen(str), fp); break; case MXML_TEXT: sprintf(str, "MXML_TEXT = %s\n", mxmlGetText(node, 0)); fwrite(str, sizeof(char), strlen(str), fp); break; } next = mxmlGetFirstChild(node); if (next != NULL) { node = next; } else { next = mxmlGetNextSibling(node); if (next == NULL) { next = mxmlWalkNext(node, NULL, MXML_DESCEND); } node = next; } } fclose(fp); mxmlDelete(tree); }
std::unique_ptr<mxml_node_t, void (*)(mxml_node_t *)> getTree(lib::Span<const GatorCpu> clusters) { #include "events_xml.h" // defines and initializes char events_xml[] and int events_xml_len char path[PATH_MAX]; mxml_node_t *xml = NULL; FILE *fl; // Avoid unused variable warning (void) events_xml_len; // Load the provided or default events xml if (gSessionData.mEventsXMLPath) { strncpy(path, gSessionData.mEventsXMLPath, PATH_MAX); fl = lib::fopen_cloexec(path, "r"); if (fl) { xml = mxmlLoadFile(NULL, fl, MXML_NO_CALLBACK); if (xml == NULL) { logg.logError("Unable to parse %s", gSessionData.mEventsXMLPath); handleException(); } fclose(fl); } } if (xml == NULL) { logg.logMessage("Unable to locate events.xml, using default"); xml = mxmlLoadString(NULL, reinterpret_cast<const char *>(events_xml), MXML_NO_CALLBACK); } // Append additional events XML if (gSessionData.mEventsXMLAppend) { fl = lib::fopen_cloexec(gSessionData.mEventsXMLAppend, "r"); if (fl == NULL) { logg.logError("Unable to open additional events XML %s", gSessionData.mEventsXMLAppend); handleException(); } mxml_node_t *append = mxmlLoadFile(NULL, fl, MXML_NO_CALLBACK); if (append == NULL) { logg.logError("Unable to parse %s", gSessionData.mEventsXMLAppend); handleException(); } fclose(fl); mxml_node_t *events = mxmlFindElement(xml, xml, TAG_EVENTS, NULL, NULL, MXML_DESCEND); if (!events) { logg.logError("Unable to find <events> node in the events.xml, please ensure the first two lines of events XML starts with:\n" "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<events>"); handleException(); } XMLList *categoryList = NULL; XMLList *eventList = NULL; XMLList *counterSetList = NULL; { // Make list of all categories in xml mxml_node_t *node = xml; while (true) { node = mxmlFindElement(node, xml, TAG_CATEGORY, NULL, NULL, MXML_DESCEND); if (node == NULL) { break; } categoryList = new XMLList(categoryList, node); } // Make list of all events in xml node = xml; while (true) { node = mxmlFindElement(node, xml, TAG_EVENT, NULL, NULL, MXML_DESCEND); if (node == NULL) { break; } eventList = new XMLList(eventList, node); } // Make list of all counter_sets in xml node = xml; while (true) { node = mxmlFindElement(node, xml, TAG_COUNTER_SET, NULL, NULL, MXML_DESCEND); if (node == NULL) { break; } counterSetList = new XMLList(counterSetList, node); } } // Handle counter_sets for (mxml_node_t *node = strcmp(mxmlGetElement(append), TAG_COUNTER_SET) == 0 ? append : mxmlFindElement(append, append, TAG_COUNTER_SET, NULL, NULL, MXML_DESCEND), *next = mxmlFindElement(node, append, TAG_COUNTER_SET, NULL, NULL, MXML_DESCEND); node != NULL; node = next, next = mxmlFindElement(node, append, TAG_COUNTER_SET, NULL, NULL, MXML_DESCEND)) { const char * const name = mxmlElementGetAttr(node, ATTR_NAME); if (name == NULL) { logg.logError("Not all event XML counter_sets have the required name attribute"); handleException(); } // Replace any duplicate counter_sets bool replaced = false; for (XMLList *counterSet = counterSetList; counterSet != NULL; counterSet = counterSet->getPrev()) { const char * const name2 = mxmlElementGetAttr(counterSet->getNode(), ATTR_NAME); if (name2 == NULL) { logg.logError("Not all event XML nodes have the required title and name and parent name attributes"); handleException(); } if (strcmp(name, name2) == 0) { logg.logMessage("Replacing counter %s", name); mxml_node_t *parent = mxmlGetParent(counterSet->getNode()); mxmlDelete(counterSet->getNode()); mxmlAdd(parent, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, node); counterSet->setNode(node); replaced = true; break; } } if (replaced) { continue; } // Add new counter_sets logg.logMessage("Appending counter_set %s", name); mxmlAdd(events, MXML_ADD_AFTER, mxmlGetLastChild(events), node); } // Handle events for (mxml_node_t *node = mxmlFindElement(append, append, TAG_EVENT, NULL, NULL, MXML_DESCEND), *next = mxmlFindElement(node, append, TAG_EVENT, NULL, NULL, MXML_DESCEND); node != NULL; node = next, next = mxmlFindElement(node, append, TAG_EVENT, NULL, NULL, MXML_DESCEND)) { const char * const category = mxmlElementGetAttr(mxmlGetParent(node), ATTR_NAME); const char * const title = mxmlElementGetAttr(node, ATTR_TITLE); const char * const name = mxmlElementGetAttr(node, ATTR_NAME); if (category == NULL || title == NULL || name == NULL) { logg.logError("Not all event XML nodes have the required title and name and parent name attributes"); handleException(); } // Replace any duplicate events for (XMLList *event = eventList; event != NULL; event = event->getPrev()) { const char * const category2 = mxmlElementGetAttr(mxmlGetParent(event->getNode()), ATTR_NAME); const char * const title2 = mxmlElementGetAttr(event->getNode(), ATTR_TITLE); const char * const name2 = mxmlElementGetAttr(event->getNode(), ATTR_NAME); if (category2 == NULL || title2 == NULL || name2 == NULL) { logg.logError("Not all event XML nodes have the required title and name and parent name attributes"); handleException(); } if (strcmp(category, category2) == 0 && strcmp(title, title2) == 0 && strcmp(name, name2) == 0) { logg.logMessage("Replacing counter %s %s: %s", category, title, name); mxml_node_t *parent = mxmlGetParent(event->getNode()); mxmlDelete(event->getNode()); mxmlAdd(parent, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, node); event->setNode(node); break; } } } // Handle categories for (mxml_node_t *node = strcmp(mxmlGetElement(append), TAG_CATEGORY) == 0 ? append : mxmlFindElement(append, append, TAG_CATEGORY, NULL, NULL, MXML_DESCEND), *next = mxmlFindElement(node, append, TAG_CATEGORY, NULL, NULL, MXML_DESCEND); node != NULL; node = next, next = mxmlFindElement(node, append, TAG_CATEGORY, NULL, NULL, MXML_DESCEND)) { // After replacing duplicate events, a category may be empty if (mxmlGetFirstChild(node) == NULL) { continue; } const char * const name = mxmlElementGetAttr(node, ATTR_NAME); if (name == NULL) { logg.logError("Not all event XML category nodes have the required name attribute"); handleException(); } // Merge identically named categories bool merged = false; for (XMLList *category = categoryList; category != NULL; category = category->getPrev()) { const char * const name2 = mxmlElementGetAttr(category->getNode(), ATTR_NAME); if (name2 == NULL) { logg.logError("Not all event XML category nodes have the required name attribute"); handleException(); } if (strcmp(name, name2) == 0) { logg.logMessage("Merging category %s", name); while (true) { mxml_node_t *child = mxmlGetFirstChild(node); if (child == NULL) { break; } mxmlAdd(category->getNode(), MXML_ADD_AFTER, mxmlGetLastChild(category->getNode()), child); } merged = true; break; } } if (merged) { continue; } // Add new categories logg.logMessage("Appending category %s", name); mxmlAdd(events, MXML_ADD_AFTER, mxmlGetLastChild(events), node); } XMLList::free(eventList); XMLList::free(categoryList); XMLList::free(counterSetList); mxmlDelete(append); } // Resolve ${cluster} for (mxml_node_t *node = mxmlFindElement(xml, xml, TAG_EVENT, NULL, NULL, MXML_DESCEND), *next = mxmlFindElement( node, xml, TAG_EVENT, NULL, NULL, MXML_DESCEND); node != NULL; node = next, next = mxmlFindElement(node, xml, TAG_EVENT, NULL, NULL, MXML_DESCEND)) { const char *counter = mxmlElementGetAttr(node, ATTR_COUNTER); if (counter != NULL && strncmp(counter, CLUSTER_VAR, sizeof(CLUSTER_VAR) - 1) == 0) { for (const GatorCpu & cluster : clusters) { mxml_node_t *n = mxmlNewElement(mxmlGetParent(node), TAG_EVENT); copyMxmlElementAttrs(n, node); char buf[1 << 7]; snprintf(buf, sizeof(buf), "%s%s", cluster.getPmncName(), counter + sizeof(CLUSTER_VAR) - 1); mxmlElementSetAttr(n, ATTR_COUNTER, buf); } mxmlDelete(node); } } return {xml, &mxmlDelete}; }
//!!!!!!!!!!!!! yahoo int parse_weather_yahoo(weather_t *w, char *buffer_orig){ int code,retcode=0; char img_buf[MAX_BUF]; mxml_node_t *top, *tree, *node; const char *text; top = mxmlLoadString(NULL, buffer_orig, MXML_TEXT_CALLBACK); tree = mxmlFindElement(top, top, "item",NULL,NULL,MXML_DESCEND); node = mxmlFindElement(tree, top, "yweather:condition",NULL,NULL,MXML_DESCEND); text=mxmlElementGetAttr(node,"code"); code=get_code(text); mylog("Now code=%02d\n",code); if(code==NO_CODE) return RSS_RETRY; w->now_weather_text=codes[lang][code+1]; sprintf(img_buf,BASE_URL "%02d.gif",code); w->now_image_index=get_icon_index(img_buf); if(w->now_image_index==0) retcode=IMAGE_RETRY; else if(w->today_image_index<0) retcode=0; text=mxmlElementGetAttr(node,"temp"); sscanf(text,"%d",&(w->now_celsium)); node = mxmlFindElement(tree, top, "yweather:forecast",NULL,NULL,MXML_DESCEND); text=mxmlElementGetAttr(node,"code"); code=get_code(text); mylog("Today code=%02d\n",code); if(code==NO_CODE) return RSS_RETRY; w->today_forecast_text=codes[lang][code+1]; sprintf(img_buf,BASE_URL "%02d.gif",code); w->today_image_index=get_icon_index(img_buf); if(w->today_image_index==0) retcode=IMAGE_RETRY; else if(w->today_image_index<0) retcode=0; text=mxmlElementGetAttr(node,"low"); sscanf(text,"%d",&(w->today_celsium_low)); text=mxmlElementGetAttr(node,"high"); sscanf(text,"%d",&(w->today_celsium_high)); node = mxmlFindElement(node, top, "yweather:forecast",NULL,NULL,MXML_DESCEND); // node = mxmlFindElement(node, top, "yweather:forecast",NULL,NULL,MXML_NO_DESCEND); // node = mxmlWalkNext(node, top,MXML_NO_DESCEND); text=mxmlElementGetAttr(node,"code"); code=get_code(text); if(code==NO_CODE) return RSS_RETRY; w->tomorrow_forecast_text=codes[lang][code+1]; sprintf(img_buf,BASE_URL "%02d.gif",code); w->tomorrow_image_index=get_icon_index(img_buf); // w->tomorrow_image_index=code; if(w->tomorrow_image_index==0) retcode=IMAGE_RETRY; else if(w->today_image_index<0) retcode=0; text=mxmlElementGetAttr(node,"low"); sscanf(text,"%d",&(w->tomorrow_celsium_low)); text=mxmlElementGetAttr(node,"high"); sscanf(text,"%d",&(w->tomorrow_celsium_high)); #ifdef YAHOO_DYNAMIC_ICON_LOAD node = mxmlFindElement(tree, tree, "description",NULL,NULL,MXML_DESCEND); node=mxmlGetFirstChild(node); text=mxmlGetElement(node); img=strstr(text,"<img src=\""); if(img==NULL) return RSS_RETRY; img+=10; strncpy(img_buf,img,MAX_BUF); end=strstr(img_buf,"\""); if(end==NULL) return RSS_RETRY; *end='\0'; if(w->now_weather_icon==NULL) {w->now_weather_icon=malloc(1);w->now_weather_icon[0]='\0';} len=strlen(img_buf)+1; if(strncmp(w->now_weather_icon,img_buf,len)){ if(w->now_weather_icon) free(w->now_weather_icon); w->now_weather_icon=malloc(len); strncpy(w->now_weather_icon,img_buf,len); w->now_weather_icon[len]='\0'; w->now_image_index=get_icon_index(w->now_weather_icon); } #endif #ifdef DEBUG print_weather(w); #endif return retcode; }
mxml_node_t *EventsXML::getTree() { #include "events_xml.h" // defines and initializes char events_xml[] and int events_xml_len char path[PATH_MAX]; mxml_node_t *xml = NULL; FILE *fl; // Avoid unused variable warning (void)events_xml_len; // Load the provided or default events xml if (gSessionData->mEventsXMLPath) { strncpy(path, gSessionData->mEventsXMLPath, PATH_MAX); fl = fopen_cloexec(path, "r"); if (fl) { xml = mxmlLoadFile(NULL, fl, MXML_NO_CALLBACK); fclose(fl); } } if (xml == NULL) { logg->logMessage("Unable to locate events.xml, using default"); xml = mxmlLoadString(NULL, (const char *)events_xml, MXML_NO_CALLBACK); } // Append additional events XML if (gSessionData->mEventsXMLAppend) { fl = fopen_cloexec(gSessionData->mEventsXMLAppend, "r"); if (fl == NULL) { logg->logError("Unable to open additional events XML %s", gSessionData->mEventsXMLAppend); handleException(); } mxml_node_t *append = mxmlLoadFile(NULL, fl, MXML_NO_CALLBACK); fclose(fl); mxml_node_t *events = mxmlFindElement(xml, xml, "events", NULL, NULL, MXML_DESCEND); if (!events) { logg->logError("Unable to find <events> node in the events.xml, please ensure the first two lines of events XML starts with:\n" "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<events>"); handleException(); } XMLList *categoryList = NULL; XMLList *eventList = NULL; { // Make list of all categories in xml mxml_node_t *node = xml; while (true) { node = mxmlFindElement(node, xml, "category", NULL, NULL, MXML_DESCEND); if (node == NULL) { break; } categoryList = new XMLList(categoryList, node); } // Make list of all events in xml node = xml; while (true) { node = mxmlFindElement(node, xml, "event", NULL, NULL, MXML_DESCEND); if (node == NULL) { break; } eventList = new XMLList(eventList, node); } } // Handle events for (mxml_node_t *node = mxmlFindElement(append, append, "event", NULL, NULL, MXML_DESCEND), *next = mxmlFindElement(node, append, "event", NULL, NULL, MXML_DESCEND); node != NULL; node = next, next = mxmlFindElement(node, append, "event", NULL, NULL, MXML_DESCEND)) { const char *const category = mxmlElementGetAttr(mxmlGetParent(node), "name"); const char *const title = mxmlElementGetAttr(node, "title"); const char *const name = mxmlElementGetAttr(node, "name"); if (category == NULL || title == NULL || name == NULL) { logg->logError("Not all event XML nodes have the required title and name and parent name attributes"); handleException(); } // Replace any duplicate events for (XMLList *event = eventList; event != NULL; event = event->getPrev()) { const char *const category2 = mxmlElementGetAttr(mxmlGetParent(event->getNode()), "name"); const char *const title2 = mxmlElementGetAttr(event->getNode(), "title"); const char *const name2 = mxmlElementGetAttr(event->getNode(), "name"); if (category2 == NULL || title2 == NULL || name2 == NULL) { logg->logError("Not all event XML nodes have the required title and name and parent name attributes"); handleException(); } if (strcmp(category, category2) == 0 && strcmp(title, title2) == 0 && strcmp(name, name2) == 0) { logg->logMessage("Replacing counter %s %s: %s", category, title, name); mxml_node_t *parent = mxmlGetParent(event->getNode()); mxmlDelete(event->getNode()); mxmlAdd(parent, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, node); event->setNode(node); break; } } } // Handle categories for (mxml_node_t *node = strcmp(mxmlGetElement(append), "category") == 0 ? append : mxmlFindElement(append, append, "category", NULL, NULL, MXML_DESCEND), *next = mxmlFindElement(node, append, "category", NULL, NULL, MXML_DESCEND); node != NULL; node = next, next = mxmlFindElement(node, append, "category", NULL, NULL, MXML_DESCEND)) { // After replacing duplicate events, a category may be empty if (mxmlGetFirstChild(node) == NULL) { continue; } const char *const name = mxmlElementGetAttr(node, "name"); if (name == NULL) { logg->logError("Not all event XML categories have the required name attribute"); handleException(); } // Merge identically named categories bool merged = false; for (XMLList *category = categoryList; category != NULL; category = category->getPrev()) { const char *const name2 = mxmlElementGetAttr(category->getNode(), "name"); if (name2 == NULL) { logg->logError("Not all event XML categories have the required name attribute"); handleException(); } if (strcmp(name, name2) == 0) { logg->logMessage("Merging category %s", name); while (true) { mxml_node_t *child = mxmlGetFirstChild(node); if (child == NULL) { break; } mxmlAdd(category->getNode(), MXML_ADD_AFTER, mxmlGetLastChild(category->getNode()), child); } merged = true; break; } } if (merged) { continue; } // Add new categories logg->logMessage("Appending category %s", name); mxmlAdd(events, MXML_ADD_AFTER, mxmlGetLastChild(events), node); } XMLList::free(eventList); XMLList::free(categoryList); mxmlDelete(append); } return xml; }