diff --git a/src/model.c b/src/model.c index b2077d3..16b0bad 100644 --- a/src/model.c +++ b/src/model.c @@ -2,7 +2,7 @@ // Model management module // // // // Copyright © 2021 Libre en Communs (contact@a-lec.org) // -// Copyright © 2021 Adrien Bourmault (neox@a-lec.org) // +// Copyright © 2021-2024 Adrien Bourmault (neox@a-lec.org) // // // // This file is part of gem-graph. // // // @@ -40,85 +40,49 @@ struct model_t *knownModels = NULL; /* -------------------------------------------------------------------------- */ -static inline xmlNodePtr getNextChild (xmlNodePtr node, xmlChar *last) -{ - while (node != NULL && xmlStrcmp(node->name, last)) { - // //printf(" <>--- line n°%lu <%s>\n", xmlGetLineNo(node), node->name); - node = node->next; - } - return node; -} +/* + * Finds a node by a path of tags. + * + * @param node The starting node for the search. + * @param path The path to the tag, with '/' as the delimiter. + * @return The content of the tag at the end of the path, or NULL if not found. + */ +char* model_find_node_by_path(xmlNode *node, const char *path) { + char *pathCopy = strdup(path); // Duplicate path to modify it + char *tag = strtok(pathCopy, "/"); // Get the first tag in the path + xmlNode *currentNode = node; -static inline xmlChar* splitStrAtSlash (xmlChar *toSplit) -{ - toSplit = (xmlChar *)xmlStrchr(toSplit, '/'); - toSplit = xmlStrsub (toSplit, 1, xmlStrlen(toSplit)); - return toSplit; -} + while (tag != NULL && currentNode != NULL) { + xmlNode *foundNode = NULL; -static inline xmlChar* getFirstTag (xmlChar *path) -{ - xmlChar *preop = path; - path = (xmlChar *)xmlStrchr(path, '/'); - path = xmlStrsub (path, 1, xmlStrlen(path)); - - return xmlStrsub (preop, 0, xmlStrlen(preop) - xmlStrlen(path) - 1); -} - -static inline xmlChar* getLastTag (xmlChar *path) -{ - while ((ulong)xmlStrchr (path, '/')) - path = splitStrAtSlash ((xmlChar *)path); - - // //printf("last tag in the path = <%s>\n", path); - return path; // which is no more the given path but only its last tag ! -} - -/* -------------------------------------------------------------------------- */ - -static xmlNodePtr model_get_node (struct model_t *self, xmlChar *path) -{ - xmlNodePtr node; - xmlChar *extrait; - xmlChar *reste, *last, *affich; - - // Lookup for node from path in hash table - node = xmlHashLookup(self->hashtable, path); - - // Found a node in hash table - if (node) { - return node; - - // no node found in hash table - } else { - reste = path; - affich = reste; - last = getLastTag(reste); - node = xmlDocGetRootElement(self->doc); - - while (xmlStrchr (reste, '/')) { - extrait = getFirstTag(reste); - reste = splitStrAtSlash((xmlChar *)reste); - node = node->xmlChildrenNode; - node = getNextChild(node, extrait); - } - - if(node && xmlStrcmp(node->name, last)) { - node = node->xmlChildrenNode; - - while (node && xmlStrcmp(node->name, last)) { - node = node->next; + // Search for the tag at the current level + for (xmlNode *child = currentNode->children; child; child = child->next) { + if (child->type == XML_ELEMENT_NODE && strcmp((const char *)child->name, tag) == 0) { + foundNode = child; // Tag found at the current level + break; } - xmlHashAddEntry (self->hashtable, path, node); } - return node; + tag = strtok(NULL, "/"); // Move to the next tag in the path + // If there are more tags to find, continue with the found node's children + if (tag != NULL && foundNode != NULL) { + currentNode = foundNode; + } else { + // If this was the last tag, try to get its content + if (foundNode != NULL && tag == NULL) { + char *content = (char *)xmlNodeGetContent(foundNode); + free(pathCopy); + return content; + } + + currentNode = NULL; // End loop if tag not found + } } - return NULL; + free(pathCopy); + return NULL; // Path not fully matched } - /* -------------------------------------------------------------------------- */ static inline long model_get_node_long_attrib (xmlNodePtr node, char *id)