src/model.c: support node copying and changing attribute (e.g. ID) on the fly
This commit is contained in:
parent
31d4e575df
commit
e70154923f
62
src/model.c
62
src/model.c
|
@ -38,6 +38,8 @@
|
||||||
|
|
||||||
struct model_t *knownModels = NULL;
|
struct model_t *knownModels = NULL;
|
||||||
|
|
||||||
|
static xmlHashTablePtr hashTable == NULL;
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,11 +50,12 @@ struct model_t *knownModels = NULL;
|
||||||
* @param currentPath The path to the current node.
|
* @param currentPath The path to the current node.
|
||||||
*/
|
*/
|
||||||
void model_populate_hashtable (xmlNode *node,
|
void model_populate_hashtable (xmlNode *node,
|
||||||
xmlHashTablePtr hashTable,
|
|
||||||
char *currentPath)
|
char *currentPath)
|
||||||
{
|
{
|
||||||
if (node == NULL) return;
|
if (node == NULL) return;
|
||||||
|
|
||||||
|
assert(hashTable == NULL);
|
||||||
|
|
||||||
// Skip text nodes and others that are not element nodes
|
// Skip text nodes and others that are not element nodes
|
||||||
if (node->type != XML_ELEMENT_NODE) {
|
if (node->type != XML_ELEMENT_NODE) {
|
||||||
model_populate_hashtable(node->next, hashTable, currentPath);
|
model_populate_hashtable(node->next, hashTable, currentPath);
|
||||||
|
@ -86,6 +89,8 @@ void model_populate_hashtable (xmlNode *node,
|
||||||
*/
|
*/
|
||||||
char* model_find_node_by_path (xmlNode *node, const char *path)
|
char* model_find_node_by_path (xmlNode *node, const char *path)
|
||||||
{
|
{
|
||||||
|
assert(hashTable != NULL);
|
||||||
|
|
||||||
return (xmlNodePtr)xmlHashLookup(hashTable, (const xmlChar *)path);
|
return (xmlNodePtr)xmlHashLookup(hashTable, (const xmlChar *)path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,10 +102,11 @@ char* model_find_node_by_path (xmlNode *node, const char *path)
|
||||||
* @param newContent The new content to set for the node.
|
* @param newContent The new content to set for the node.
|
||||||
* @return 1 if the node was found and modified, 0 otherwise.
|
* @return 1 if the node was found and modified, 0 otherwise.
|
||||||
*/
|
*/
|
||||||
int model_modify_node (xmlHashTablePtr hashTable,
|
int model_modify_node (const char *path,
|
||||||
const char *path,
|
|
||||||
const char *newContent)
|
const char *newContent)
|
||||||
{
|
{
|
||||||
|
assert(hashTable != NULL);
|
||||||
|
|
||||||
xmlNodePtr node = model_find_node_by_path(hashTable, path);
|
xmlNodePtr node = model_find_node_by_path(hashTable, path);
|
||||||
if (node) {
|
if (node) {
|
||||||
// Free the current content of the node, if any
|
// Free the current content of the node, if any
|
||||||
|
@ -120,10 +126,11 @@ int model_modify_node (xmlHashTablePtr hashTable,
|
||||||
* @param attributeName The name of the attribute.
|
* @param attributeName The name of the attribute.
|
||||||
* @return The value of the attribute, or NULL if not found.
|
* @return The value of the attribute, or NULL if not found.
|
||||||
*/
|
*/
|
||||||
char* model_get_attribute (xmlHashTablePtr hashTable,
|
char* model_get_attribute (const char* nodePath,
|
||||||
const char* nodePath,
|
|
||||||
const char* attributeName)
|
const char* attributeName)
|
||||||
{
|
{
|
||||||
|
assert(hashTable != NULL);
|
||||||
|
|
||||||
xmlNodePtr node = (xmlNodePtr)xmlHashLookup(hashTable, (const xmlChar*)nodePath);
|
xmlNodePtr node = (xmlNodePtr)xmlHashLookup(hashTable, (const xmlChar*)nodePath);
|
||||||
if (node) {
|
if (node) {
|
||||||
return getAttributeValue(node, attributeName);
|
return getAttributeValue(node, attributeName);
|
||||||
|
@ -141,11 +148,12 @@ char* model_get_attribute (xmlHashTablePtr hashTable,
|
||||||
* @param attributeValue The value to set for the attribute.
|
* @param attributeValue The value to set for the attribute.
|
||||||
* @return 1 on success, 0 on failure.
|
* @return 1 on success, 0 on failure.
|
||||||
*/
|
*/
|
||||||
int model_set_attribute (xmlHashTablePtr hashTable,
|
int model_set_attribute (const char* nodePath,
|
||||||
const char* nodePath,
|
|
||||||
const char* attributeName,
|
const char* attributeName,
|
||||||
const char* attributeValue)
|
const char* attributeValue)
|
||||||
{
|
{
|
||||||
|
assert(hashTable != NULL);
|
||||||
|
|
||||||
xmlNodePtr node = (xmlNodePtr)xmlHashLookup(hashTable, (const xmlChar*)nodePath);
|
xmlNodePtr node = (xmlNodePtr)xmlHashLookup(hashTable, (const xmlChar*)nodePath);
|
||||||
if (node) {
|
if (node) {
|
||||||
return setAttributeValue(node, attributeName, attributeValue);
|
return setAttributeValue(node, attributeName, attributeValue);
|
||||||
|
@ -154,6 +162,46 @@ int model_set_attribute (xmlHashTablePtr hashTable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies a node recursively to a new sibling node with a modified attribute and updates the hashtable.
|
||||||
|
*
|
||||||
|
* @param doc The document to which the nodes belong.
|
||||||
|
* @param node The node to copy.
|
||||||
|
* @param hashTable The hashtable for tracking nodes by path.
|
||||||
|
* @param originalNodePath The path of the original node in the hashtable.
|
||||||
|
* @param attributeName The name of the attribute to modify in the copied node.
|
||||||
|
* @param newAttributeValue The new value for the specified attribute in the copied node.
|
||||||
|
* @return The copied node with the modified attribute, or NULL on failure.
|
||||||
|
*/
|
||||||
|
xmlNodePtr model_copy_node(struct model_t *self,
|
||||||
|
xmlNodePtr node,
|
||||||
|
const char* originalNodePath,
|
||||||
|
const char* attributeName,
|
||||||
|
const char* newAttributeValue)
|
||||||
|
{
|
||||||
|
assert(hashTable != NULL);
|
||||||
|
|
||||||
|
// Deep copy the node
|
||||||
|
xmlNodePtr copiedNode = xmlDocCopyNode(node, self->doc, 1);
|
||||||
|
if (copiedNode == NULL) {
|
||||||
|
return NULL; // Failed to copy
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modify the specified attribute in the copied node
|
||||||
|
xmlSetProp(copiedNode, (const xmlChar*)attributeName, (const xmlChar*)newAttributeValue);
|
||||||
|
|
||||||
|
// Insert the copied node as the next sibling of the original node
|
||||||
|
xmlAddNextSibling(node, copiedNode);
|
||||||
|
|
||||||
|
// Calculate the new node's path.
|
||||||
|
char newPath[1024];
|
||||||
|
snprintf(newPath, sizeof(newPath), "%s_copy", originalNodePath);
|
||||||
|
|
||||||
|
// Update the hashtable with the new node's path
|
||||||
|
xmlHashAddEntry(hashTable, (const xmlChar*)newPath, copiedNode);
|
||||||
|
|
||||||
|
return copiedNode;
|
||||||
|
}
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
char model_get_dim (struct model_t *self)
|
char model_get_dim (struct model_t *self)
|
||||||
|
|
Loading…
Reference in New Issue