add part of xinclude/xpointer

This commit is contained in:
Nishi 2026-03-09 23:06:21 +09:00
commit d0379fc869
Signed by: nishi
GPG key ID: 27EF69B208EB9343
6 changed files with 167 additions and 14 deletions

View file

@ -10,7 +10,10 @@ xemil_t* xl_open(xl_driver_t* driver, void* arg) {
handle->pre = NULL;
handle->root = NULL;
handle->new_text = 0;
handle->path = NULL;
handle->new_text = 0;
handle->do_xinclude = 0;
if(!handle->driver->open(handle)) {
free(handle);
@ -560,6 +563,10 @@ int xl_parse(xemil_t* handle) {
CLEANUP;
if(handle->do_xinclude) {
xl_xinclude_scan(handle, handle->root);
}
return 1;
}
@ -589,8 +596,82 @@ static void recursive_free(xl_node_t* node) {
free(node);
}
void xl_free(xl_node_t* node) {
xl_node_t* parent = node->parent;
xl_node_t* child;
child = parent->first_child;
if(child != NULL && child == node) {
parent->first_child = child->next;
if(child->next != NULL) child->next->prev = NULL;
child = child->next;
}
while(child != NULL) {
xl_node_t* next = child->next;
if(child == node) {
if(child->prev != NULL) child->prev->next = child->next;
if(child->next != NULL) child->next->prev = child->prev;
}
child = next;
}
recursive_free(node);
}
void xl_replace(xl_node_t* node, xl_node_t* new) {
xl_node_t* parent = node->parent;
xl_node_t* child;
if(new->parent != NULL&& new->parent->first_child == new) {
new->parent->first_child = new->next;
if(new->next->prev != NULL) new->next->prev = NULL;
}
if(new->parent != NULL) {
child = new->parent->first_child;
while(child != NULL) {
if(child == new) {
if(child->prev != NULL) child->prev->next = child->next;
if(child->next != NULL) child->next->prev = child->prev;
}
child = child->next;
}
}
child = parent->first_child;
if(child != NULL && child == node) {
parent->first_child = new;
new->parent = parent;
new->prev = NULL;
new->next = child->next;
child = child->next;
}
while(child != NULL) {
if(child == node) {
new->parent = parent;
new->next = child->next;
new->prev = child->prev;
if(child->prev != NULL) child->prev->next = new;
if(child->next != NULL) child->next->prev = new;
}
child = child->next;
}
recursive_free(node);
}
void xl_close(xemil_t* handle) {
if(handle->root != NULL) recursive_free(handle->root);
if(handle->path != NULL) free(handle->path);
handle->driver->close(handle);
free(handle);

View file

@ -1,8 +1,19 @@
#include <xemil.h>
static int xl_driver_file_open(xemil_t* handle) {
char* s;
if((handle->drv_opaque = fopen(handle->drv_arg, "rb")) == NULL) return 0;
handle->path = xl_util_strdup(handle->drv_arg);
if((s = strrchr(handle->path, '/')) == NULL) {
free(handle->path);
handle->path = xl_util_strdup("./");
} else {
s[1] = 0;
}
return 1;
}

51
src/xinclude.c Normal file
View file

@ -0,0 +1,51 @@
#include <xemil.h>
void xl_xinclude_scan(xemil_t* handle, xl_node_t* node) {
xl_node_t* child;
if(node->type == XL_NODE_NODE && node->name != NULL && strcmp(node->name, "xi:include") == 0) {
char* href = xl_get_attribute(node, "href");
char* parse = xl_get_attribute(node, "parse");
char* xpointer = xl_get_attribute(node, "xpointer");
if(href != NULL) {
xemil_t* new;
if(handle->path == NULL) {
href = xl_util_strdup(href);
} else {
href = xl_util_strvacat(handle->path, href, NULL);
}
if(parse == NULL) parse = "xml";
if(xpointer == NULL) xpointer = "element(/)";
if((new = xl_open_file(href)) != NULL) {
new->do_xinclude = 1;
new->new_text = handle->new_text;
if(xl_parse(new) && new->root != NULL) {
xl_node_t** nodes;
if((nodes = xl_xpointer(new->root, xpointer)) != NULL) {
xl_replace(node, nodes[0]);
if(nodes[0] == new->root) new->root = NULL;
free(nodes);
}
}
}
if(new != NULL) xl_close(new);
free(href);
}
}
child = node->first_child;
while(child != NULL) {
xl_xinclude_scan(handle, child);
child = child->next;
}
}