mirror of
https://github.com/pvvx/rtl00TstMinAmebaV35a.git
synced 2024-11-27 08:40:28 +00:00
1377 lines
32 KiB
C
1377 lines
32 KiB
C
|
/*
|
||
|
Author: Alex Fang
|
||
|
|
||
|
Tree Structure
|
||
|
root root
|
||
|
| ^ ^
|
||
|
child | |
|
||
|
| parent parent
|
||
|
v | |
|
||
|
NULL<-prev-child1-next-><-prev-child2-next->NULL
|
||
|
*/
|
||
|
|
||
|
#include "platform/platform_stdlib.h"
|
||
|
#include "FreeRTOS.h"
|
||
|
#include "xml.h"
|
||
|
|
||
|
static struct xml_node *_xml_new_element(char *prefix, char *name, char *uri, char *attr);
|
||
|
|
||
|
char *xml_strstr(const char *str1, const char *str2) {
|
||
|
char *a, *b;
|
||
|
|
||
|
/* First scan quickly through the two strings looking for a
|
||
|
* single-character match. When it's found, then compare the
|
||
|
* rest of the substring.
|
||
|
*/
|
||
|
|
||
|
b = (char *)str2;
|
||
|
if (*b == 0) {
|
||
|
return (char *)str1;
|
||
|
}
|
||
|
for ( ; *str1 != 0; str1 += 1) {
|
||
|
if (*str1 != *b) {
|
||
|
continue;
|
||
|
}
|
||
|
a = (char *)str1;
|
||
|
while (1) {
|
||
|
if (*b == 0) {
|
||
|
return (char *)str1;
|
||
|
}
|
||
|
if (*a++ != *b++) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
b = (char *)str2;
|
||
|
}
|
||
|
return (char *) 0;
|
||
|
}
|
||
|
|
||
|
static void *xml_malloc(unsigned int size)
|
||
|
{
|
||
|
return pvPortMalloc(size);
|
||
|
}
|
||
|
|
||
|
void xml_free(void *buf)
|
||
|
{
|
||
|
vPortFree(buf);
|
||
|
}
|
||
|
|
||
|
static char *str_strip(char *str, unsigned int str_len)
|
||
|
{
|
||
|
char *front, *rear;
|
||
|
char *strip = NULL;
|
||
|
int strip_len;
|
||
|
|
||
|
if(!str || (str_len <= 0))
|
||
|
return NULL;
|
||
|
|
||
|
for(front = str; front < (str + str_len); front ++)
|
||
|
if(*front != ' ') break;
|
||
|
|
||
|
if(front == (str + str_len))
|
||
|
return NULL;
|
||
|
|
||
|
for(rear = (str + str_len - 1); rear >= front; rear --)
|
||
|
if(*rear != ' ') break;
|
||
|
|
||
|
if(front == rear) {
|
||
|
strip_len = 1;
|
||
|
strip = (char *) xml_malloc(strip_len + 1);
|
||
|
memcpy(strip, front, strip_len);
|
||
|
strip[strip_len] = '\0';
|
||
|
}
|
||
|
else {
|
||
|
strip_len = rear + 1 - front;
|
||
|
strip = (char *) xml_malloc(strip_len + 1);
|
||
|
memcpy(strip, front, strip_len);
|
||
|
strip[strip_len] = '\0';
|
||
|
}
|
||
|
|
||
|
return strip;
|
||
|
}
|
||
|
|
||
|
/* TAG Format:
|
||
|
* STag ::= '<' Name (S Attribute)* S? '>'
|
||
|
* ETag ::= '</' Name S? '>'
|
||
|
* EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
|
||
|
*/
|
||
|
static void _parse_tag(char *tag, char **prefix, char **name, char **uri, char **attr)
|
||
|
{
|
||
|
char *prefix_char, *ns_tag, *ns_front;
|
||
|
int have_prefix = 0;
|
||
|
int have_uri = 0;
|
||
|
|
||
|
prefix_char = strchr(tag, ':');
|
||
|
|
||
|
if(prefix_char) {
|
||
|
char *tag_sep = strchr(tag, ' ');
|
||
|
|
||
|
if(!tag_sep)
|
||
|
have_prefix = 1;
|
||
|
else if(prefix_char < tag_sep)
|
||
|
have_prefix = 1;
|
||
|
}
|
||
|
|
||
|
if(have_prefix) {
|
||
|
*prefix = str_strip(tag, prefix_char - tag);
|
||
|
ns_tag = (char *) xml_malloc(strlen(" xmlns:") + strlen(*prefix) + 1);
|
||
|
sprintf(ns_tag, " xmlns:%s", *prefix);
|
||
|
ns_front = xml_strstr(tag, ns_tag);
|
||
|
xml_free(ns_tag);
|
||
|
}
|
||
|
else {
|
||
|
*prefix = NULL;
|
||
|
ns_tag = " xmlns";
|
||
|
ns_front = xml_strstr(tag, ns_tag);
|
||
|
}
|
||
|
|
||
|
if(ns_front)
|
||
|
have_uri = 1;
|
||
|
|
||
|
if(have_prefix && have_uri) {
|
||
|
char *uri_front, *uri_rear, *tag_sep, ns_sep;
|
||
|
int uri_len;
|
||
|
|
||
|
tag_sep = strchr(prefix_char + 1, ' ');
|
||
|
*name = str_strip(prefix_char + 1, tag_sep - (prefix_char + 1));
|
||
|
|
||
|
if(attr)
|
||
|
*attr = str_strip(tag_sep, tag + strlen(tag) - tag_sep);
|
||
|
|
||
|
if(*(strchr(ns_front, '=') + 1) == '\'')
|
||
|
ns_sep = '\'';
|
||
|
else
|
||
|
ns_sep = '\"';
|
||
|
|
||
|
uri_front = strchr(ns_front, ns_sep) + 1;
|
||
|
uri_rear = strchr(uri_front, ns_sep);
|
||
|
uri_len = uri_rear - uri_front;
|
||
|
*uri = (char *) xml_malloc(uri_len + 1);
|
||
|
memcpy(*uri, uri_front, uri_len);
|
||
|
(*uri)[uri_len] = '\0';
|
||
|
}
|
||
|
else if(have_prefix) {
|
||
|
char *tag_sep;
|
||
|
|
||
|
*uri = NULL;
|
||
|
tag_sep = strchr(prefix_char + 1, ' ');
|
||
|
|
||
|
if(tag_sep) {
|
||
|
*name = str_strip(prefix_char + 1, tag_sep - (prefix_char + 1));
|
||
|
|
||
|
if(attr)
|
||
|
*attr = str_strip(tag_sep, tag + strlen(tag) - tag_sep);
|
||
|
}
|
||
|
else {
|
||
|
*name = str_strip(prefix_char + 1, tag + strlen(tag) - (prefix_char + 1));
|
||
|
|
||
|
if(attr)
|
||
|
*attr = NULL;
|
||
|
}
|
||
|
}
|
||
|
else if(have_uri) {
|
||
|
char *uri_front, *uri_rear, *tag_sep, ns_sep;
|
||
|
int uri_len;
|
||
|
|
||
|
tag_sep = strchr(tag, ' ');
|
||
|
*name = str_strip(tag, tag_sep - tag);
|
||
|
|
||
|
if(attr)
|
||
|
*attr = str_strip(tag_sep, tag + strlen(tag) - tag_sep);
|
||
|
|
||
|
if(*(strchr(ns_front, '=') + 1) == '\'')
|
||
|
ns_sep = '\'';
|
||
|
else
|
||
|
ns_sep = '\"';
|
||
|
|
||
|
uri_front = strchr(ns_front, ns_sep) + 1;
|
||
|
uri_rear = strchr(uri_front, ns_sep);
|
||
|
uri_len = uri_rear - uri_front;
|
||
|
*uri = (char *) xml_malloc(uri_len + 1);
|
||
|
memcpy(*uri, uri_front, uri_len);
|
||
|
(*uri)[uri_len] = '\0';
|
||
|
}
|
||
|
else {
|
||
|
char *tag_sep;
|
||
|
|
||
|
*uri = NULL;
|
||
|
tag_sep = strchr(tag, ' ');
|
||
|
|
||
|
if(tag_sep) {
|
||
|
*name = str_strip(tag, tag_sep - tag);
|
||
|
|
||
|
if(attr)
|
||
|
*attr = str_strip(tag_sep, tag + strlen(tag) - tag_sep);
|
||
|
}
|
||
|
else {
|
||
|
*name = str_strip(tag, strlen(tag));
|
||
|
|
||
|
if(attr)
|
||
|
*attr = NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void parse_tag(char *tag, char **prefix, char **name, char **uri)
|
||
|
{
|
||
|
_parse_tag(tag, prefix, name, uri, NULL);
|
||
|
}
|
||
|
|
||
|
int xml_doc_name(char *doc_buf, int doc_len, char **doc_prefix, char **doc_name, char **doc_uri)
|
||
|
{
|
||
|
char *xml_buf, *cur_pos, *tag_front, *tag_rear;
|
||
|
char *start_tag, *end_tag1, *end_tag2;
|
||
|
int tag_len, ret = -1;
|
||
|
|
||
|
xml_buf = (char *) xml_malloc(doc_len + 1);
|
||
|
memcpy(xml_buf, doc_buf, doc_len);
|
||
|
xml_buf[doc_len] = '\0';
|
||
|
|
||
|
cur_pos = xml_buf;
|
||
|
|
||
|
while(cur_pos < (xml_buf + doc_len)) {
|
||
|
if((tag_front = strchr(cur_pos, '<')) != NULL) {
|
||
|
tag_front ++;
|
||
|
|
||
|
if((tag_rear = strchr(tag_front, '>')) != NULL) {
|
||
|
char *prefix = NULL, *name = NULL, *uri = NULL;
|
||
|
|
||
|
//Element without content
|
||
|
if(*(tag_rear - 1) == '/') {
|
||
|
tag_len = tag_rear - 1 - tag_front;
|
||
|
start_tag = (char *) xml_malloc(tag_len + 1);
|
||
|
memcpy(start_tag, tag_front, tag_len);
|
||
|
start_tag[tag_len] = '\0';
|
||
|
parse_tag(start_tag, &prefix, &name, &uri);
|
||
|
xml_free(start_tag);
|
||
|
*doc_name = name;
|
||
|
*doc_prefix = prefix;
|
||
|
*doc_uri = uri;
|
||
|
ret = 0;
|
||
|
cur_pos = xml_buf + doc_len;
|
||
|
}
|
||
|
//Element with content
|
||
|
else {
|
||
|
tag_len = tag_rear - tag_front;
|
||
|
start_tag = (char *) xml_malloc(tag_len + 1);
|
||
|
memcpy(start_tag, tag_front, tag_len);
|
||
|
start_tag[tag_len] = '\0';
|
||
|
parse_tag(start_tag, &prefix, &name, &uri);
|
||
|
xml_free(start_tag);
|
||
|
|
||
|
if(prefix) {
|
||
|
end_tag1 = (char *) xml_malloc(strlen(prefix) + strlen(name) + 5);
|
||
|
sprintf(end_tag1, "</%s:%s>", prefix, name);
|
||
|
end_tag2 = (char *) xml_malloc(strlen(prefix) + strlen(name) + 5);
|
||
|
sprintf(end_tag2, "</%s:%s ", prefix, name);
|
||
|
}
|
||
|
else {
|
||
|
end_tag1 = (char *) xml_malloc(strlen(name) + 4);
|
||
|
sprintf(end_tag1, "</%s>", name);
|
||
|
end_tag2 = (char *) xml_malloc(strlen(name) + 4);
|
||
|
sprintf(end_tag2, "</%s ", name);
|
||
|
}
|
||
|
|
||
|
if(xml_strstr(tag_rear + 1, end_tag1) || xml_strstr(tag_rear + 1, end_tag2)) {
|
||
|
*doc_name = name;
|
||
|
*doc_prefix = prefix;
|
||
|
*doc_uri = uri;
|
||
|
ret = 0;
|
||
|
cur_pos = xml_buf + doc_len;
|
||
|
}
|
||
|
else {
|
||
|
xml_free(name);
|
||
|
if(prefix) xml_free(prefix);
|
||
|
if(uri) xml_free(uri);
|
||
|
cur_pos = tag_rear + 1;
|
||
|
}
|
||
|
|
||
|
xml_free(end_tag1);
|
||
|
xml_free(end_tag2);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
cur_pos = xml_buf + doc_len;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
cur_pos = xml_buf + doc_len;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
xml_free(xml_buf);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
struct xml_node *_xml_parse_doc(char *doc_buf, int doc_len, struct xml_node *root)
|
||
|
{
|
||
|
char *xml_buf, *cur_pos;
|
||
|
|
||
|
xml_buf = (char *) xml_malloc(doc_len + 1);
|
||
|
memcpy(xml_buf, doc_buf, doc_len);
|
||
|
xml_buf[doc_len] = '\0';
|
||
|
|
||
|
cur_pos = xml_buf;
|
||
|
|
||
|
while(cur_pos < (xml_buf + doc_len)) {
|
||
|
char *tag_front, *tag_rear;
|
||
|
struct xml_node *node;
|
||
|
|
||
|
if((tag_front = strchr(cur_pos, '<')) != NULL) {
|
||
|
tag_front ++;
|
||
|
|
||
|
if((tag_rear = strchr(tag_front, '>')) != NULL) {
|
||
|
char *doc_front, *doc_rear, *start_tag, *end_tag1, *end_tag2;
|
||
|
char *prefix = NULL, *name = NULL, *uri = NULL, *attr = NULL;
|
||
|
int tag_len;
|
||
|
|
||
|
//Element without content
|
||
|
if(*(tag_rear - 1) == '/') {
|
||
|
doc_front = tag_rear + 1;
|
||
|
tag_len = tag_rear - 1 - tag_front;
|
||
|
start_tag = (char *) xml_malloc(tag_len + 1);
|
||
|
memcpy(start_tag, tag_front, tag_len);
|
||
|
start_tag[tag_len] = '\0';
|
||
|
_parse_tag(start_tag, &prefix, &name, &uri, &attr);
|
||
|
node = _xml_new_element(prefix, name, uri, attr);
|
||
|
|
||
|
if(root) {
|
||
|
xml_add_child(root, node);
|
||
|
cur_pos = doc_front;
|
||
|
}
|
||
|
else {
|
||
|
root = node;
|
||
|
cur_pos = xml_buf + doc_len;
|
||
|
}
|
||
|
}
|
||
|
//Element with content
|
||
|
else {
|
||
|
doc_front = tag_rear + 1;
|
||
|
tag_len = tag_rear - tag_front;
|
||
|
start_tag = (char *) xml_malloc(tag_len + 1);
|
||
|
memcpy(start_tag, tag_front, tag_len);
|
||
|
start_tag[tag_len] = '\0';
|
||
|
_parse_tag(start_tag, &prefix, &name, &uri, &attr);
|
||
|
|
||
|
if(prefix) {
|
||
|
end_tag1 = (char *) xml_malloc(strlen(prefix) + strlen(name) + 5);
|
||
|
sprintf(end_tag1, "</%s:%s>", prefix, name);
|
||
|
end_tag2 = (char *) xml_malloc(strlen(prefix) + strlen(name) + 5);
|
||
|
sprintf(end_tag2, "</%s:%s ", prefix, name);
|
||
|
}
|
||
|
else {
|
||
|
end_tag1 = (char *) xml_malloc(strlen(name) + 4);
|
||
|
sprintf(end_tag1, "</%s>", name);
|
||
|
end_tag2 = (char *) xml_malloc(strlen(name) + 4);
|
||
|
sprintf(end_tag2, "</%s ", name);
|
||
|
}
|
||
|
|
||
|
if(xml_strstr(doc_front, end_tag1))
|
||
|
doc_rear = xml_strstr(doc_front, end_tag1);
|
||
|
else if(xml_strstr(doc_front, end_tag2))
|
||
|
doc_rear = xml_strstr(doc_front, end_tag2);
|
||
|
else
|
||
|
doc_rear = NULL;
|
||
|
|
||
|
if(doc_rear) {
|
||
|
node = _xml_new_element(prefix, name, uri, attr);
|
||
|
|
||
|
if(root) {
|
||
|
xml_add_child(root, node);
|
||
|
_xml_parse_doc(doc_front, doc_rear - doc_front, node);
|
||
|
cur_pos = strchr(doc_rear, '>') + 1;
|
||
|
}
|
||
|
else {
|
||
|
root = node;
|
||
|
_xml_parse_doc(doc_front, doc_rear - doc_front, node);
|
||
|
cur_pos = xml_buf + doc_len;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
cur_pos = doc_front;
|
||
|
}
|
||
|
|
||
|
xml_free(end_tag1);
|
||
|
xml_free(end_tag2);
|
||
|
}
|
||
|
|
||
|
xml_free(start_tag);
|
||
|
xml_free(name);
|
||
|
if(prefix) xml_free(prefix);
|
||
|
if(uri) xml_free(uri);
|
||
|
if(attr) xml_free(attr);
|
||
|
}
|
||
|
else {
|
||
|
if(root && !root->child && (strlen(cur_pos) > 0)) {
|
||
|
node = xml_new_text(cur_pos);
|
||
|
xml_add_child(root, node);
|
||
|
}
|
||
|
|
||
|
cur_pos = xml_buf + doc_len;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if(root && !root->child && (strlen(cur_pos) > 0)) {
|
||
|
node = xml_new_text(cur_pos);
|
||
|
xml_add_child(root, node);
|
||
|
}
|
||
|
|
||
|
cur_pos = xml_buf + doc_len;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
xml_free(xml_buf);
|
||
|
|
||
|
return root;
|
||
|
}
|
||
|
|
||
|
/* Note: xml_parse_doc can handle attribute only for namespace */
|
||
|
struct xml_node *xml_parse_doc(char *doc_buf, int doc_len, char *doc_prefix, char *doc_name, char *doc_uri)
|
||
|
{
|
||
|
struct xml_node *root = NULL;
|
||
|
char *xml_buf, *start_tag, *end_tag, *empty_tag, *front, *rear;
|
||
|
|
||
|
xml_buf = (char *) xml_malloc(doc_len + 1);
|
||
|
memcpy(xml_buf, doc_buf, doc_len);
|
||
|
xml_buf[doc_len] = '\0';
|
||
|
|
||
|
if(doc_prefix && doc_uri) {
|
||
|
start_tag = (char *) xml_malloc(2 * strlen(doc_prefix) + strlen(doc_name) + strlen(doc_uri) + 14);
|
||
|
sprintf(start_tag, "<%s:%s xmlns:%s=\"%s\">", doc_prefix, doc_name, doc_prefix, doc_uri);
|
||
|
empty_tag = (char *) xml_malloc(2 * strlen(doc_prefix) + strlen(doc_name) + strlen(doc_uri) + 15);
|
||
|
sprintf(empty_tag, "<%s:%s xmlns:%s=\"%s\"/>", doc_prefix, doc_name, doc_prefix, doc_uri);
|
||
|
|
||
|
}
|
||
|
else if(doc_prefix) {
|
||
|
start_tag = (char *) xml_malloc(strlen(doc_prefix) + strlen(doc_name) + 4);
|
||
|
sprintf(start_tag, "<%s:%s>", doc_prefix, doc_name);
|
||
|
empty_tag = (char *) xml_malloc(strlen(doc_prefix) + strlen(doc_name) + 5);
|
||
|
sprintf(empty_tag, "<%s:%s/>", doc_prefix, doc_name);
|
||
|
}
|
||
|
else if(doc_uri) {
|
||
|
start_tag = (char *) xml_malloc(strlen(doc_name) + strlen(doc_uri) + 12);
|
||
|
sprintf(start_tag, "<%s xmlns=\"%s\">", doc_name, doc_uri);
|
||
|
empty_tag = (char *) xml_malloc(strlen(doc_name) + strlen(doc_uri) + 13);
|
||
|
sprintf(empty_tag, "<%s xmlns=\"%s\"/>", doc_name, doc_uri);
|
||
|
}
|
||
|
else {
|
||
|
start_tag = (char *) xml_malloc(strlen(doc_name) + 3);
|
||
|
sprintf(start_tag, "<%s>", doc_name);
|
||
|
empty_tag = (char *) xml_malloc(strlen(doc_name) + 4);
|
||
|
sprintf(empty_tag, "<%s/>", doc_name);
|
||
|
}
|
||
|
|
||
|
if(doc_prefix) {
|
||
|
end_tag = (char *) xml_malloc(strlen(doc_prefix) + strlen(doc_name) + 5);
|
||
|
sprintf(end_tag, "</%s:%s>", doc_prefix, doc_name);
|
||
|
}
|
||
|
else {
|
||
|
end_tag = (char *) xml_malloc(strlen(doc_name) + 4);
|
||
|
sprintf(end_tag, "</%s>", doc_name);
|
||
|
}
|
||
|
|
||
|
//Root element with content
|
||
|
if((front = xml_strstr(xml_buf, start_tag)) != NULL) {
|
||
|
front += strlen(start_tag);
|
||
|
|
||
|
if((rear = xml_strstr(front, end_tag)) != NULL) {
|
||
|
int xml_len = rear - front;
|
||
|
|
||
|
root = xml_new_element(doc_prefix, doc_name, doc_uri);
|
||
|
_xml_parse_doc(front, xml_len, root);
|
||
|
}
|
||
|
}
|
||
|
//Root element without content
|
||
|
else if((front = xml_strstr(xml_buf, empty_tag)) != NULL) {
|
||
|
root = xml_new_element(doc_prefix, doc_name, doc_uri);
|
||
|
}
|
||
|
|
||
|
xml_free(start_tag);
|
||
|
xml_free(end_tag);
|
||
|
xml_free(empty_tag);
|
||
|
xml_free(xml_buf);
|
||
|
|
||
|
return root;
|
||
|
}
|
||
|
|
||
|
struct xml_node *xml_parse(char *doc_buf, int doc_len)
|
||
|
{
|
||
|
char *proc_inst, *comment, *pos, *prolog_end;
|
||
|
|
||
|
/* Remove XML Prolog */
|
||
|
pos = doc_buf;
|
||
|
while(pos < (doc_buf + doc_len)) {
|
||
|
if((proc_inst = xml_strstr(pos, "<?")) != NULL) {
|
||
|
pos = strchr(proc_inst, '>') + 1;
|
||
|
}
|
||
|
else {
|
||
|
proc_inst = pos;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
pos = doc_buf;
|
||
|
while(pos < (doc_buf + doc_len)) {
|
||
|
if((comment = xml_strstr(pos, "<!")) != NULL) {
|
||
|
pos = strchr(comment, '>') + 1;
|
||
|
}
|
||
|
else {
|
||
|
comment = pos;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if(proc_inst > comment)
|
||
|
prolog_end = proc_inst;
|
||
|
else
|
||
|
prolog_end = comment;
|
||
|
|
||
|
return _xml_parse_doc(prolog_end, doc_buf + doc_len - prolog_end, NULL);
|
||
|
}
|
||
|
|
||
|
static struct xml_node *xml_new_node(void)
|
||
|
{
|
||
|
struct xml_node *node;
|
||
|
|
||
|
node = (struct xml_node *) xml_malloc(sizeof(struct xml_node));
|
||
|
memset(node, 0, sizeof(struct xml_node));
|
||
|
|
||
|
return node;
|
||
|
}
|
||
|
|
||
|
static struct xml_node *_xml_new_element(char *prefix, char *name, char *uri, char *attr)
|
||
|
{
|
||
|
struct xml_node *node;
|
||
|
|
||
|
node = xml_new_node();
|
||
|
node->name = (char *) xml_malloc(strlen(name) + 1);
|
||
|
strcpy(node->name, name);
|
||
|
|
||
|
if(prefix) {
|
||
|
node->prefix = (char *) xml_malloc(strlen(prefix) + 1);
|
||
|
strcpy(node->prefix, prefix);
|
||
|
}
|
||
|
|
||
|
if(uri) {
|
||
|
node->uri = (char *) xml_malloc(strlen(uri) + 1);
|
||
|
strcpy(node->uri, uri);
|
||
|
}
|
||
|
|
||
|
if(attr) {
|
||
|
node->attr = (char *) xml_malloc(strlen(attr) + 1);
|
||
|
strcpy(node->attr, attr);
|
||
|
}
|
||
|
|
||
|
return node;
|
||
|
}
|
||
|
|
||
|
struct xml_node *xml_new_element(char *prefix, char *name, char *uri)
|
||
|
{
|
||
|
struct xml_node *node;
|
||
|
char *attr = NULL;
|
||
|
|
||
|
if(prefix && uri) {
|
||
|
attr = (char *) xml_malloc(strlen(prefix) + strlen(uri) + 10);
|
||
|
sprintf(attr, "xmlns:%s=\"%s\"", prefix, uri);
|
||
|
}
|
||
|
else if(uri) {
|
||
|
attr = (char *) xml_malloc(strlen(uri) + 9);
|
||
|
sprintf(attr, "xmlns=\"%s\"", uri);
|
||
|
}
|
||
|
|
||
|
node = _xml_new_element(prefix, name, uri, attr);
|
||
|
|
||
|
if(attr)
|
||
|
xml_free(attr);
|
||
|
|
||
|
return node;
|
||
|
}
|
||
|
|
||
|
struct xml_node *xml_new_text(char *text)
|
||
|
{
|
||
|
struct xml_node *node;
|
||
|
char *text_buf;
|
||
|
|
||
|
text_buf = (char *) xml_malloc(strlen(text) + 1);
|
||
|
strcpy(text_buf, text);
|
||
|
node = xml_new_node();
|
||
|
node->text = text_buf;
|
||
|
|
||
|
return node;
|
||
|
}
|
||
|
|
||
|
int xml_is_element(struct xml_node *node)
|
||
|
{
|
||
|
int ret = 0;
|
||
|
|
||
|
if((node->name != NULL) && (node->text == NULL))
|
||
|
ret = 1;
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int xml_is_text(struct xml_node *node)
|
||
|
{
|
||
|
int ret = 0;
|
||
|
|
||
|
if((node->name == NULL) && (node->text != NULL))
|
||
|
ret = 1;
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static void _xml_copy_tree(struct xml_node *root, struct xml_node *parent)
|
||
|
{
|
||
|
struct xml_node *copy = NULL;
|
||
|
|
||
|
if(xml_is_text(root)) {
|
||
|
copy = xml_new_text(root->text);
|
||
|
}
|
||
|
else if(xml_is_element(root)) {
|
||
|
struct xml_node *child = root->child;
|
||
|
|
||
|
copy = _xml_new_element(root->prefix, root->name, root->uri, root->attr);
|
||
|
|
||
|
while(child) {
|
||
|
_xml_copy_tree(child, copy);
|
||
|
child = child->next;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(copy)
|
||
|
xml_add_child(parent, copy);
|
||
|
}
|
||
|
|
||
|
struct xml_node* xml_copy_tree(struct xml_node *root)
|
||
|
{
|
||
|
struct xml_node *copy = NULL;
|
||
|
|
||
|
if(xml_is_text(root)) {
|
||
|
copy = xml_new_text(root->text);
|
||
|
}
|
||
|
else if(xml_is_element(root)) {
|
||
|
struct xml_node *child = root->child;
|
||
|
|
||
|
copy = _xml_new_element(root->prefix, root->name, root->uri, root->attr);
|
||
|
|
||
|
while(child) {
|
||
|
_xml_copy_tree(child, copy);
|
||
|
child = child->next;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return copy;
|
||
|
}
|
||
|
|
||
|
void xml_delete_tree(struct xml_node *root)
|
||
|
{
|
||
|
if(root->name)
|
||
|
xml_free(root->name);
|
||
|
|
||
|
if(root->text)
|
||
|
xml_free(root->text);
|
||
|
|
||
|
if(root->prefix)
|
||
|
xml_free(root->prefix);
|
||
|
|
||
|
if(root->uri)
|
||
|
xml_free(root->uri);
|
||
|
|
||
|
if(root->attr)
|
||
|
xml_free(root->attr);
|
||
|
|
||
|
while(root->child)
|
||
|
xml_delete_tree(root->child);
|
||
|
|
||
|
if(root->prev) {
|
||
|
root->prev->next = root->next;
|
||
|
|
||
|
if(root->next)
|
||
|
root->next->prev = root->prev;
|
||
|
}
|
||
|
else if(root->parent) {
|
||
|
root->parent->child = root->next;
|
||
|
|
||
|
if(root->next)
|
||
|
root->next->prev = NULL;
|
||
|
}
|
||
|
|
||
|
xml_free(root);
|
||
|
}
|
||
|
|
||
|
void xml_add_child(struct xml_node *node, struct xml_node *child)
|
||
|
{
|
||
|
if(xml_is_element(node)) {
|
||
|
if(node->child) {
|
||
|
struct xml_node *last_child = node->child;
|
||
|
|
||
|
while(last_child->next != NULL)
|
||
|
last_child = last_child->next;
|
||
|
|
||
|
last_child->next = child;
|
||
|
child->prev = last_child;
|
||
|
}
|
||
|
else {
|
||
|
node->child = child;
|
||
|
}
|
||
|
|
||
|
child->parent = node;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void xml_clear_child(struct xml_node *node)
|
||
|
{
|
||
|
while(node->child)
|
||
|
xml_delete_tree(node->child);
|
||
|
}
|
||
|
|
||
|
struct xml_node* xml_text_child(struct xml_node *node)
|
||
|
{
|
||
|
struct xml_node *child = NULL;
|
||
|
|
||
|
if(node->child) {
|
||
|
if(xml_is_text(node->child))
|
||
|
child = node->child;
|
||
|
}
|
||
|
|
||
|
return child;
|
||
|
}
|
||
|
|
||
|
void xml_set_text(struct xml_node *node, char *text)
|
||
|
{
|
||
|
if(xml_is_text(node)) {
|
||
|
char *text_buf = (char *) xml_malloc(strlen(text) + 1);
|
||
|
strcpy(text_buf, text);
|
||
|
xml_free(node->text);
|
||
|
node->text = text_buf;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void _xml_element_count(struct xml_node *root, char *name, int *count)
|
||
|
{
|
||
|
if(xml_is_element(root)) {
|
||
|
struct xml_node *child = root->child;
|
||
|
|
||
|
if(strcmp(root->name, name) == 0) {
|
||
|
(*count) ++;
|
||
|
}
|
||
|
|
||
|
while(child) {
|
||
|
_xml_element_count(child, name, count);
|
||
|
child = child->next;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int xml_element_count(struct xml_node *root, char *name)
|
||
|
{
|
||
|
int count = 0;
|
||
|
|
||
|
_xml_element_count(root, name, &count);
|
||
|
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
static void _xml_find_element(struct xml_node *root, char *name, struct xml_node_set *node_set)
|
||
|
{
|
||
|
if(xml_is_element(root)) {
|
||
|
struct xml_node *child = root->child;
|
||
|
|
||
|
if(strcmp(root->name, name) == 0) {
|
||
|
node_set->node[node_set->count] = root;
|
||
|
node_set->count ++;
|
||
|
}
|
||
|
|
||
|
while(child) {
|
||
|
_xml_find_element(child, name, node_set);
|
||
|
child = child->next;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
struct xml_node_set* xml_find_element(struct xml_node *root, char *name)
|
||
|
{
|
||
|
struct xml_node_set *node_set = NULL;
|
||
|
int node_count;
|
||
|
|
||
|
node_set = (struct xml_node_set *) xml_malloc(sizeof(struct xml_node_set));
|
||
|
node_set->count = 0;
|
||
|
node_count = xml_element_count(root, name);
|
||
|
|
||
|
if(node_count)
|
||
|
node_set->node = (struct xml_node **) xml_malloc(node_count * sizeof(struct xml_node *));
|
||
|
else
|
||
|
node_set->node = NULL;
|
||
|
|
||
|
_xml_find_element(root, name, node_set);
|
||
|
|
||
|
return node_set;
|
||
|
}
|
||
|
|
||
|
static void _xml_path_count(struct xml_node *root, char *path, int *count)
|
||
|
{
|
||
|
if(xml_is_element(root)) {
|
||
|
char *front = NULL, *rear = NULL;
|
||
|
|
||
|
if((front = strchr(path, '/')) != NULL) {
|
||
|
int prefix_len, name_len;
|
||
|
char *prefix, *name, *prefix_char;
|
||
|
int prefix_matched = 0, name_matched = 0;
|
||
|
|
||
|
front ++;
|
||
|
prefix_char = strchr(front, ':');
|
||
|
|
||
|
if((rear = strchr(front, '/')) != NULL) {
|
||
|
if(prefix_char && (prefix_char < rear)) {
|
||
|
prefix_len = prefix_char - front;
|
||
|
prefix = (char *) xml_malloc(prefix_len + 1);
|
||
|
memcpy(prefix, front, prefix_len);
|
||
|
prefix[prefix_len] = '\0';
|
||
|
|
||
|
name_len = rear - (prefix_char + 1);
|
||
|
name = (char *) xml_malloc(name_len + 1);
|
||
|
memcpy(name, prefix_char + 1, name_len);
|
||
|
name[name_len] = '\0';
|
||
|
}
|
||
|
else {
|
||
|
prefix = NULL;
|
||
|
name_len = rear - front;
|
||
|
name = (char *) xml_malloc(name_len + 1);
|
||
|
memcpy(name, front, name_len);
|
||
|
name[name_len] = '\0';
|
||
|
}
|
||
|
|
||
|
if((!prefix && !root->prefix) ||
|
||
|
(prefix && root->prefix && (strcmp(root->prefix, prefix) == 0)))
|
||
|
prefix_matched = 1;
|
||
|
else
|
||
|
prefix_matched = 0;
|
||
|
|
||
|
if(strcmp(root->name, name) == 0)
|
||
|
name_matched = 1;
|
||
|
else
|
||
|
name_matched = 0;
|
||
|
|
||
|
if(prefix_matched && name_matched) {
|
||
|
struct xml_node *child = root->child;
|
||
|
|
||
|
while(child) {
|
||
|
_xml_path_count(child, rear, count);
|
||
|
child = child->next;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if(prefix_char) {
|
||
|
prefix_len = prefix_char - front;
|
||
|
prefix = (char *) xml_malloc(prefix_len + 1);
|
||
|
memcpy(prefix, front, prefix_len);
|
||
|
prefix[prefix_len] = '\0';
|
||
|
|
||
|
name_len = strlen(path) - (prefix_char + 1 - path);
|
||
|
name = (char *) xml_malloc(name_len + 1);
|
||
|
memcpy(name, prefix_char + 1, name_len);
|
||
|
name[name_len] = '\0';
|
||
|
}
|
||
|
else {
|
||
|
prefix = NULL;
|
||
|
name_len = strlen(path) - (front - path);
|
||
|
name = (char *) xml_malloc(name_len + 1);
|
||
|
memcpy(name, front, name_len);
|
||
|
name[name_len] = '\0';
|
||
|
}
|
||
|
|
||
|
if((!prefix && !root->prefix) ||
|
||
|
(prefix && root->prefix && (strcmp(root->prefix, prefix) == 0)))
|
||
|
prefix_matched = 1;
|
||
|
else
|
||
|
prefix_matched = 0;
|
||
|
|
||
|
if(strcmp(root->name, name) == 0)
|
||
|
name_matched = 1;
|
||
|
else
|
||
|
name_matched = 0;
|
||
|
|
||
|
if(prefix_matched && name_matched)
|
||
|
(*count) ++;
|
||
|
}
|
||
|
|
||
|
if(prefix) xml_free(prefix);
|
||
|
xml_free(name);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int xml_path_count(struct xml_node *root, char *path)
|
||
|
{
|
||
|
int count = 0;
|
||
|
|
||
|
_xml_path_count(root, path, &count);
|
||
|
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
static void _xml_find_path(struct xml_node *root, char *path, struct xml_node_set *node_set)
|
||
|
{
|
||
|
if(xml_is_element(root)) {
|
||
|
char *front = NULL, *rear = NULL;
|
||
|
|
||
|
if((front = strchr(path, '/')) != NULL) {
|
||
|
int prefix_len, name_len;
|
||
|
char *prefix, *name, *prefix_char;
|
||
|
int prefix_matched = 0, name_matched = 0;
|
||
|
|
||
|
front ++;
|
||
|
prefix_char = strchr(front, ':');
|
||
|
|
||
|
if((rear = strchr(front, '/')) != NULL) {
|
||
|
if(prefix_char && (prefix_char < rear)) {
|
||
|
prefix_len = prefix_char - front;
|
||
|
prefix = (char *) xml_malloc(prefix_len + 1);
|
||
|
memcpy(prefix, front, prefix_len);
|
||
|
prefix[prefix_len] = '\0';
|
||
|
|
||
|
name_len = rear - (prefix_char + 1);
|
||
|
name = (char *) xml_malloc(name_len + 1);
|
||
|
memcpy(name, prefix_char + 1, name_len);
|
||
|
name[name_len] = '\0';
|
||
|
}
|
||
|
else {
|
||
|
prefix = NULL;
|
||
|
name_len = rear - front;
|
||
|
name = (char *) xml_malloc(name_len + 1);
|
||
|
memcpy(name, front, name_len);
|
||
|
name[name_len] = '\0';
|
||
|
}
|
||
|
|
||
|
if((!prefix && !root->prefix) ||
|
||
|
(prefix && root->prefix && (strcmp(root->prefix, prefix) == 0)))
|
||
|
prefix_matched = 1;
|
||
|
else
|
||
|
prefix_matched = 0;
|
||
|
|
||
|
if(strcmp(root->name, name) == 0)
|
||
|
name_matched = 1;
|
||
|
else
|
||
|
name_matched = 0;
|
||
|
|
||
|
if(prefix_matched && name_matched) {
|
||
|
struct xml_node *child = root->child;
|
||
|
|
||
|
while(child) {
|
||
|
_xml_find_path(child, rear, node_set);
|
||
|
child = child->next;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if(prefix_char) {
|
||
|
prefix_len = prefix_char - front;
|
||
|
prefix = (char *) xml_malloc(prefix_len + 1);
|
||
|
memcpy(prefix, front, prefix_len);
|
||
|
prefix[prefix_len] = '\0';
|
||
|
|
||
|
name_len = strlen(path) - (prefix_char + 1 - path);
|
||
|
name = (char *) xml_malloc(name_len + 1);
|
||
|
memcpy(name, prefix_char + 1, name_len);
|
||
|
name[name_len] = '\0';
|
||
|
}
|
||
|
else {
|
||
|
prefix = NULL;
|
||
|
name_len = strlen(path) - (front - path);
|
||
|
name = (char *) xml_malloc(name_len + 1);
|
||
|
memcpy(name, front, name_len);
|
||
|
name[name_len] = '\0';
|
||
|
}
|
||
|
|
||
|
if((!prefix && !root->prefix) ||
|
||
|
(prefix && root->prefix && (strcmp(root->prefix, prefix) == 0)))
|
||
|
prefix_matched = 1;
|
||
|
else
|
||
|
prefix_matched = 0;
|
||
|
|
||
|
if(strcmp(root->name, name) == 0)
|
||
|
name_matched = 1;
|
||
|
else
|
||
|
name_matched = 0;
|
||
|
|
||
|
if(prefix_matched && name_matched) {
|
||
|
node_set->node[node_set->count] = root;
|
||
|
node_set->count ++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(prefix) xml_free(prefix);
|
||
|
xml_free(name);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
struct xml_node_set* xml_find_path(struct xml_node *root, char *path)
|
||
|
{
|
||
|
struct xml_node_set *node_set = NULL;
|
||
|
int node_count;
|
||
|
|
||
|
node_set = (struct xml_node_set *) xml_malloc(sizeof(struct xml_node_set));
|
||
|
node_set->count = 0;
|
||
|
node_count = xml_path_count(root, path);
|
||
|
|
||
|
if(node_count)
|
||
|
node_set->node = (struct xml_node **) xml_malloc(node_count * sizeof(struct xml_node *));
|
||
|
else
|
||
|
node_set->node = NULL;
|
||
|
|
||
|
_xml_find_path(root, path, node_set);
|
||
|
|
||
|
return node_set;
|
||
|
}
|
||
|
|
||
|
void xml_delete_set(struct xml_node_set *node_set)
|
||
|
{
|
||
|
if(node_set->node)
|
||
|
xml_free(node_set->node);
|
||
|
|
||
|
xml_free(node_set);
|
||
|
}
|
||
|
|
||
|
static int xml_tree_size(struct xml_node *root, int level, int space)
|
||
|
{
|
||
|
int size = 0;
|
||
|
int next_level = (level)?(level + 1):0;
|
||
|
|
||
|
if(xml_is_text(root)) {
|
||
|
size += strlen(root->text);
|
||
|
}
|
||
|
else if(xml_is_element(root)) {
|
||
|
int start_size, end_size;
|
||
|
struct xml_node *child = root->child;
|
||
|
int is_element_child = 0;
|
||
|
|
||
|
if(root->prefix && root->attr)
|
||
|
/* <prefix:name attr> */
|
||
|
start_size = strlen(root->prefix) + strlen(root->name) + strlen(root->attr) + 4;
|
||
|
else if(root->prefix)
|
||
|
/* <prefix:name> */
|
||
|
start_size = strlen(root->prefix) + strlen(root->name) + 3;
|
||
|
else if(root->attr)
|
||
|
/* <name attr> */
|
||
|
start_size = strlen(root->name) + strlen(root->attr) + 3;
|
||
|
else
|
||
|
/* <name> */
|
||
|
start_size = strlen(root->name) + 2;
|
||
|
|
||
|
size += start_size;
|
||
|
|
||
|
while(child) {
|
||
|
if(((is_element_child = xml_is_element(child)) == 1) && level) {
|
||
|
size ++; /* /n */
|
||
|
size += (level * space); /* space */
|
||
|
}
|
||
|
|
||
|
size += xml_tree_size(child, next_level, space);
|
||
|
child = child->next;
|
||
|
}
|
||
|
|
||
|
if(is_element_child && level) {
|
||
|
size ++; /* /n */
|
||
|
size += ((level - 1) * space); /* space */
|
||
|
}
|
||
|
|
||
|
if(root->prefix)
|
||
|
/* </prefix:name> */
|
||
|
end_size = strlen(root->prefix) + strlen(root->name) + 4;
|
||
|
else
|
||
|
/* </name> */
|
||
|
end_size = strlen(root->name) + 3;
|
||
|
|
||
|
size += end_size;
|
||
|
}
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
static void _xml_dump_tree(struct xml_node *root, char *xml_buf, int level, int space)
|
||
|
{
|
||
|
int next_level = (level)?(level + 1):0;
|
||
|
|
||
|
if(xml_is_text(root)) {
|
||
|
strcat(xml_buf, root->text);
|
||
|
}
|
||
|
else if(xml_is_element(root)) {
|
||
|
struct xml_node *child = root->child;
|
||
|
int is_element_child = 0;
|
||
|
|
||
|
if(root->prefix && root->attr) {
|
||
|
strcat(xml_buf, "<");
|
||
|
strcat(xml_buf, root->prefix);
|
||
|
strcat(xml_buf, ":");
|
||
|
strcat(xml_buf, root->name);
|
||
|
strcat(xml_buf, " ");
|
||
|
strcat(xml_buf, root->attr);
|
||
|
strcat(xml_buf, ">");
|
||
|
}
|
||
|
else if(root->prefix) {
|
||
|
strcat(xml_buf, "<");
|
||
|
strcat(xml_buf, root->prefix);
|
||
|
strcat(xml_buf, ":");
|
||
|
strcat(xml_buf, root->name);
|
||
|
strcat(xml_buf, ">");
|
||
|
}
|
||
|
else if(root->attr) {
|
||
|
strcat(xml_buf, "<");
|
||
|
strcat(xml_buf, root->name);
|
||
|
strcat(xml_buf, " ");
|
||
|
strcat(xml_buf, root->attr);
|
||
|
strcat(xml_buf, ">");
|
||
|
}
|
||
|
else {
|
||
|
strcat(xml_buf, "<");
|
||
|
strcat(xml_buf, root->name);
|
||
|
strcat(xml_buf, ">");
|
||
|
}
|
||
|
|
||
|
while(child) {
|
||
|
if(((is_element_child = xml_is_element(child)) == 1) && level) {
|
||
|
char space_buf[11];
|
||
|
int i;
|
||
|
|
||
|
strcat(xml_buf, "\n");
|
||
|
memset(space_buf, ' ', sizeof(space_buf));
|
||
|
space_buf[space] = '\0';
|
||
|
|
||
|
for(i = 0; i < level; i ++)
|
||
|
strcat(xml_buf, space_buf);
|
||
|
}
|
||
|
|
||
|
_xml_dump_tree(child, xml_buf, next_level, space);
|
||
|
child = child->next;
|
||
|
}
|
||
|
|
||
|
if(is_element_child && level) {
|
||
|
char space_buf[11];
|
||
|
int i;
|
||
|
|
||
|
strcat(xml_buf, "\n");
|
||
|
memset(space_buf, ' ', sizeof(space_buf));
|
||
|
space_buf[space] = '\0';
|
||
|
|
||
|
for(i = 0; i < (level - 1); i ++)
|
||
|
strcat(xml_buf, space_buf);
|
||
|
}
|
||
|
|
||
|
if(root->prefix) {
|
||
|
strcat(xml_buf, "</");
|
||
|
strcat(xml_buf, root->prefix);
|
||
|
strcat(xml_buf, ":");
|
||
|
strcat(xml_buf, root->name);
|
||
|
strcat(xml_buf, ">");
|
||
|
}
|
||
|
else {
|
||
|
strcat(xml_buf, "</");
|
||
|
strcat(xml_buf, root->name);
|
||
|
strcat(xml_buf, ">");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
char *xml_dump_tree(struct xml_node *root)
|
||
|
{
|
||
|
int xml_size;
|
||
|
char *xml_buf;
|
||
|
|
||
|
xml_size = xml_tree_size(root, 0, 0);
|
||
|
xml_buf = (char *) xml_malloc(xml_size + 1);
|
||
|
memset(xml_buf, 0, xml_size + 1);
|
||
|
_xml_dump_tree(root, xml_buf, 0, 0);
|
||
|
|
||
|
return xml_buf;
|
||
|
}
|
||
|
|
||
|
char *xml_dump_tree_ex(struct xml_node *root, char *prolog, int new_line, int space)
|
||
|
{
|
||
|
int xml_size;
|
||
|
char *xml_buf;
|
||
|
|
||
|
/* Max offset of 10 for each level */
|
||
|
if(space > 10)
|
||
|
space = 10;
|
||
|
|
||
|
xml_size = xml_tree_size(root, 1, space);
|
||
|
|
||
|
if(prolog && new_line) {
|
||
|
xml_buf = (char *) xml_malloc(strlen(prolog) + xml_size + 2);
|
||
|
memset(xml_buf, 0, strlen(prolog) + xml_size + 2);
|
||
|
sprintf(xml_buf, "%s\n", prolog);
|
||
|
_xml_dump_tree(root, xml_buf + strlen(prolog), new_line, space);
|
||
|
}
|
||
|
else if(prolog) {
|
||
|
xml_buf = (char *) xml_malloc(strlen(prolog) + xml_size + 1);
|
||
|
memset(xml_buf, 0, strlen(prolog) + xml_size + 1);
|
||
|
strcpy(xml_buf, prolog);
|
||
|
_xml_dump_tree(root, xml_buf + strlen(prolog), new_line, space);
|
||
|
}
|
||
|
else {
|
||
|
xml_buf = (char *) xml_malloc(xml_size + 1);
|
||
|
memset(xml_buf, 0, xml_size + 1);
|
||
|
_xml_dump_tree(root, xml_buf, new_line, space);
|
||
|
}
|
||
|
|
||
|
return xml_buf;
|
||
|
}
|
||
|
|
||
|
void xml_set_attribute(struct xml_node *node, char *attr, char *value)
|
||
|
{
|
||
|
char *ns_tag, *new_attr;
|
||
|
|
||
|
if(node->prefix) {
|
||
|
ns_tag = (char *) xml_malloc(strlen("xmlns:") + strlen(node->prefix) + 1);
|
||
|
sprintf(ns_tag, "xmlns:%s", node->prefix);
|
||
|
|
||
|
if(strcmp(ns_tag, attr) == 0) {
|
||
|
if(node->uri) xml_free(node->uri);
|
||
|
node->uri = (char *) xml_malloc(strlen(value) + 1);
|
||
|
strcpy(node->uri, value);
|
||
|
}
|
||
|
|
||
|
xml_free(ns_tag);
|
||
|
}
|
||
|
else {
|
||
|
ns_tag = "xmlns";
|
||
|
|
||
|
if(strcmp(ns_tag, attr) == 0) {
|
||
|
if(node->uri) xml_free(node->uri);
|
||
|
node->uri = (char *) xml_malloc(strlen(value) + 1);
|
||
|
strcpy(node->uri, value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* attr="value" or attr='value' */
|
||
|
new_attr = (char *) xml_malloc(strlen(attr) + strlen(value) + 4);
|
||
|
|
||
|
if(strchr(value, '\"'))
|
||
|
sprintf(new_attr, "%s=\'%s\'", attr, value);
|
||
|
else
|
||
|
sprintf(new_attr, "%s=\"%s\"", attr, value);
|
||
|
|
||
|
if(node->attr) {
|
||
|
char *attr1, *attr2, *attr_pos, *all_attr, *attr_p1 = NULL, *attr_p2 = NULL;
|
||
|
int attr_existed = 0;
|
||
|
|
||
|
attr1 = (char *) xml_malloc(strlen(attr) + 4);
|
||
|
sprintf(attr1, " %s=\'", attr);
|
||
|
attr2 = (char *) xml_malloc(strlen(attr) + 4);
|
||
|
sprintf(attr2, " %s=\"", attr);
|
||
|
|
||
|
if(((attr_pos = xml_strstr(node->attr, attr1)) != NULL) ||
|
||
|
(xml_strstr(node->attr, attr1 + 1) == node->attr)) {
|
||
|
attr_existed = 1;
|
||
|
|
||
|
if(attr_pos) {
|
||
|
attr_p1 = str_strip(node->attr, attr_pos - node->attr);
|
||
|
attr_p2 = str_strip(strchr(attr_pos + strlen(attr1), '\'') + 1,
|
||
|
node->attr + strlen(node->attr) - (strchr(attr_pos + strlen(attr1), '\'') + 1));
|
||
|
}
|
||
|
else {
|
||
|
attr_p1 = NULL;
|
||
|
attr_p2 = str_strip(strchr(node->attr + strlen(attr1) - 1, '\'') + 1,
|
||
|
node->attr + strlen(node->attr) - (strchr(node->attr + strlen(attr1) - 1, '\'') + 1));
|
||
|
}
|
||
|
}
|
||
|
else if(((attr_pos = xml_strstr(node->attr, attr2)) != NULL) ||
|
||
|
(xml_strstr(node->attr, attr2 + 1) == node->attr)) {
|
||
|
attr_existed = 1;
|
||
|
|
||
|
if(attr_pos) {
|
||
|
attr_p1 = str_strip(node->attr, attr_pos - node->attr);
|
||
|
attr_p2 = str_strip(strchr(attr_pos + strlen(attr2), '\"') + 1,
|
||
|
node->attr + strlen(node->attr) - (strchr(attr_pos + strlen(attr2), '\"') + 1));
|
||
|
}
|
||
|
else {
|
||
|
attr_p1 = NULL;
|
||
|
attr_p2 = str_strip(strchr(node->attr + strlen(attr2) - 1, '\"') + 1,
|
||
|
node->attr + strlen(node->attr) - (strchr(node->attr + strlen(attr2) - 1, '\"') + 1));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(attr_p1 && attr_p2) {
|
||
|
all_attr = (char *) xml_malloc(strlen(attr_p1) + strlen(new_attr) + strlen(attr_p2) + 3);
|
||
|
sprintf(all_attr, "%s %s %s", attr_p1, new_attr, attr_p2);
|
||
|
}
|
||
|
else if(attr_p1) {
|
||
|
all_attr = (char *) xml_malloc(strlen(attr_p1) + strlen(new_attr) + 2);
|
||
|
sprintf(all_attr, "%s %s", attr_p1, new_attr);
|
||
|
}
|
||
|
else if(attr_p2) {
|
||
|
all_attr = (char *) xml_malloc(strlen(new_attr) + strlen(attr_p2) + 2);
|
||
|
sprintf(all_attr, "%s %s", new_attr, attr_p2);
|
||
|
}
|
||
|
else if(attr_existed) {
|
||
|
all_attr = (char *) xml_malloc(strlen(new_attr) + 1);
|
||
|
sprintf(all_attr, "%s", new_attr);
|
||
|
}
|
||
|
else {
|
||
|
all_attr = (char *) xml_malloc(strlen(node->attr) + strlen(new_attr) + 2);
|
||
|
sprintf(all_attr, "%s %s", node->attr, new_attr);
|
||
|
}
|
||
|
|
||
|
xml_free(attr1);
|
||
|
xml_free(attr2);
|
||
|
if(attr_p1) xml_free(attr_p1);
|
||
|
if(attr_p2) xml_free(attr_p2);
|
||
|
xml_free(new_attr);
|
||
|
xml_free(node->attr);
|
||
|
node->attr = all_attr;
|
||
|
}
|
||
|
else {
|
||
|
node->attr = new_attr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
char *xml_get_attribute(struct xml_node *node, char *attr)
|
||
|
{
|
||
|
char *value = NULL;
|
||
|
|
||
|
if(node->attr) {
|
||
|
/* attr=' or attr=" */
|
||
|
char *value_front, *value_rear, *attr1, *attr2, *attr_pos;
|
||
|
int value_len;
|
||
|
|
||
|
attr1 = (char *) xml_malloc(strlen(attr) + 4);
|
||
|
sprintf(attr1, " %s=\'", attr);
|
||
|
attr2 = (char *) xml_malloc(strlen(attr) + 4);
|
||
|
sprintf(attr2, " %s=\"", attr);
|
||
|
|
||
|
if(((attr_pos = xml_strstr(node->attr, attr1)) != NULL) ||
|
||
|
(xml_strstr(node->attr, attr1 + 1) == node->attr)) {
|
||
|
if(attr_pos)
|
||
|
value_front = attr_pos + strlen(attr1);
|
||
|
else
|
||
|
value_front = node->attr + strlen(attr1) - 1;
|
||
|
|
||
|
value_rear = strchr(value_front, '\'');
|
||
|
value_len = value_rear - value_front;
|
||
|
value = (char *) xml_malloc(value_len + 1);
|
||
|
memcpy(value, value_front, value_len);
|
||
|
value[value_len] = '\0';
|
||
|
}
|
||
|
else if(((attr_pos = xml_strstr(node->attr, attr2)) != NULL) ||
|
||
|
(xml_strstr(node->attr, attr2 + 1) == node->attr)) {
|
||
|
if(attr_pos)
|
||
|
value_front = attr_pos + strlen(attr2);
|
||
|
else
|
||
|
value_front = node->attr + strlen(attr2) - 1;
|
||
|
|
||
|
value_rear = strchr(value_front, '\"');
|
||
|
value_len = value_rear - value_front;
|
||
|
value = (char *) xml_malloc(value_len + 1);
|
||
|
memcpy(value, value_front, value_len);
|
||
|
value[value_len] = '\0';
|
||
|
}
|
||
|
|
||
|
xml_free(attr1);
|
||
|
xml_free(attr2);
|
||
|
}
|
||
|
|
||
|
return value;
|
||
|
}
|
||
|
|