📄 tree.c
字号:
(xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
xmlFree((char *)(str));
/**
* xmlFreeDtd:
* @cur: the DTD structure to free up
*
* Free a DTD structure.
*/
void
xmlFreeDtd(xmlDtdPtr cur) {
xmlDictPtr dict = NULL;
if (cur == NULL) {
return;
}
if (cur->doc != NULL) dict = cur->doc->dict;
if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
if (cur->children != NULL) {
xmlNodePtr next, c = cur->children;
/*
* Cleanup all nodes which are not part of the specific lists
* of notations, elements, attributes and entities.
*/
while (c != NULL) {
next = c->next;
if ((c->type != XML_NOTATION_NODE) &&
(c->type != XML_ELEMENT_DECL) &&
(c->type != XML_ATTRIBUTE_DECL) &&
(c->type != XML_ENTITY_DECL)) {
xmlUnlinkNode(c);
xmlFreeNode(c);
}
c = next;
}
}
DICT_FREE(cur->name)
DICT_FREE(cur->SystemID)
DICT_FREE(cur->ExternalID)
/* TODO !!! */
if (cur->notations != NULL)
xmlFreeNotationTable((xmlNotationTablePtr) cur->notations);
if (cur->elements != NULL)
xmlFreeElementTable((xmlElementTablePtr) cur->elements);
if (cur->attributes != NULL)
xmlFreeAttributeTable((xmlAttributeTablePtr) cur->attributes);
if (cur->entities != NULL)
xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->entities);
if (cur->pentities != NULL)
xmlFreeEntitiesTable((xmlEntitiesTablePtr) cur->pentities);
xmlFree(cur);
}
/**
* xmlNewDoc:
* @version: xmlChar string giving the version of XML "1.0"
*
* Creates a new XML document
*
* Returns a new document
*/
xmlDocPtr
xmlNewDoc(const xmlChar *version) {
xmlDocPtr cur;
if (version == NULL)
version = (const xmlChar *) "1.0";
/*
* Allocate a new document and fill the fields.
*/
cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc));
if (cur == NULL) {
xmlTreeErrMemory("building doc");
return(NULL);
}
memset(cur, 0, sizeof(xmlDoc));
cur->type = XML_DOCUMENT_NODE;
cur->version = xmlStrdup(version);
if (cur->version == NULL) {
xmlTreeErrMemory("building doc");
xmlFree(cur);
return(NULL);
}
cur->standalone = -1;
cur->compression = -1; /* not initialized */
cur->doc = cur;
/*
* The in memory encoding is always UTF8
* This field will never change and would
* be obsolete if not for binary compatibility.
*/
cur->charset = XML_CHAR_ENCODING_UTF8;
if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
return(cur);
}
/**
* xmlFreeDoc:
* @cur: pointer to the document
*
* Free up all the structures used by a document, tree included.
*/
void
xmlFreeDoc(xmlDocPtr cur) {
xmlDtdPtr extSubset, intSubset;
xmlDictPtr dict = NULL;
if (cur == NULL) {
#ifdef DEBUG_TREE
xmlGenericError(xmlGenericErrorContext,
"xmlFreeDoc : document == NULL\n");
#endif
return;
}
#ifdef LIBXML_DEBUG_RUNTIME
xmlDebugCheckDocument(stderr, cur);
#endif
if (cur != NULL) dict = cur->dict;
if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
/*
* Do this before freeing the children list to avoid ID lookups
*/
if (cur->ids != NULL) xmlFreeIDTable((xmlIDTablePtr) cur->ids);
cur->ids = NULL;
if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
cur->refs = NULL;
extSubset = cur->extSubset;
intSubset = cur->intSubset;
if (intSubset == extSubset)
extSubset = NULL;
if (extSubset != NULL) {
xmlUnlinkNode((xmlNodePtr) cur->extSubset);
cur->extSubset = NULL;
xmlFreeDtd(extSubset);
}
if (intSubset != NULL) {
xmlUnlinkNode((xmlNodePtr) cur->intSubset);
cur->intSubset = NULL;
xmlFreeDtd(intSubset);
}
if (cur->children != NULL) xmlFreeNodeList(cur->children);
if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
DICT_FREE(cur->version)
DICT_FREE(cur->name)
DICT_FREE(cur->encoding)
DICT_FREE(cur->URL)
xmlFree(cur);
if (dict) xmlDictFree(dict);
}
/**
* xmlStringLenGetNodeList:
* @doc: the document
* @value: the value of the text
* @len: the length of the string value
*
* Parse the value string and build the node list associated. Should
* produce a flat tree with only TEXTs and ENTITY_REFs.
* Returns a pointer to the first child
*/
xmlNodePtr
xmlStringLenGetNodeList(xmlDocPtr doc, const xmlChar *value, int len) {
xmlNodePtr ret = NULL, last = NULL;
xmlNodePtr node;
xmlChar *val;
const xmlChar *cur = value, *end = cur + len;
const xmlChar *q;
xmlEntityPtr ent;
if (value == NULL) return(NULL);
q = cur;
while ((cur < end) && (*cur != 0)) {
if (cur[0] == '&') {
int charval = 0;
xmlChar tmp;
/*
* Save the current text.
*/
if (cur != q) {
if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
xmlNodeAddContentLen(last, q, cur - q);
} else {
node = xmlNewDocTextLen(doc, q, cur - q);
if (node == NULL) return(ret);
if (last == NULL)
last = ret = node;
else {
last->next = node;
node->prev = last;
last = node;
}
}
}
q = cur;
if ((cur + 2 < end) && (cur[1] == '#') && (cur[2] == 'x')) {
cur += 3;
if (cur < end)
tmp = *cur;
else
tmp = 0;
while (tmp != ';') { /* Non input consuming loop */
if ((tmp >= '0') && (tmp <= '9'))
charval = charval * 16 + (tmp - '0');
else if ((tmp >= 'a') && (tmp <= 'f'))
charval = charval * 16 + (tmp - 'a') + 10;
else if ((tmp >= 'A') && (tmp <= 'F'))
charval = charval * 16 + (tmp - 'A') + 10;
else {
xmlTreeErr(XML_TREE_INVALID_HEX, (xmlNodePtr) doc,
NULL);
charval = 0;
break;
}
cur++;
if (cur < end)
tmp = *cur;
else
tmp = 0;
}
if (tmp == ';')
cur++;
q = cur;
} else if ((cur + 1 < end) && (cur[1] == '#')) {
cur += 2;
if (cur < end)
tmp = *cur;
else
tmp = 0;
while (tmp != ';') { /* Non input consuming loops */
if ((tmp >= '0') && (tmp <= '9'))
charval = charval * 10 + (tmp - '0');
else {
xmlTreeErr(XML_TREE_INVALID_DEC, (xmlNodePtr) doc,
NULL);
charval = 0;
break;
}
cur++;
if (cur < end)
tmp = *cur;
else
tmp = 0;
}
if (tmp == ';')
cur++;
q = cur;
} else {
/*
* Read the entity string
*/
cur++;
q = cur;
while ((cur < end) && (*cur != 0) && (*cur != ';')) cur++;
if ((cur >= end) || (*cur == 0)) {
xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY, (xmlNodePtr) doc,
(const char *) q);
return(ret);
}
if (cur != q) {
/*
* Predefined entities don't generate nodes
*/
val = xmlStrndup(q, cur - q);
ent = xmlGetDocEntity(doc, val);
if ((ent != NULL) &&
(ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
if (last == NULL) {
node = xmlNewDocText(doc, ent->content);
last = ret = node;
} else if (last->type != XML_TEXT_NODE) {
node = xmlNewDocText(doc, ent->content);
last = xmlAddNextSibling(last, node);
} else
xmlNodeAddContent(last, ent->content);
} else {
/*
* Create a new REFERENCE_REF node
*/
node = xmlNewReference(doc, val);
if (node == NULL) {
if (val != NULL) xmlFree(val);
return(ret);
}
else if ((ent != NULL) && (ent->children == NULL)) {
xmlNodePtr temp;
ent->children = xmlStringGetNodeList(doc,
(const xmlChar*)node->content);
ent->owner = 1;
temp = ent->children;
while (temp) {
temp->parent = (xmlNodePtr)ent;
ent->last = temp;
temp = temp->next;
}
}
if (last == NULL) {
last = ret = node;
} else {
last = xmlAddNextSibling(last, node);
}
}
xmlFree(val);
}
cur++;
q = cur;
}
if (charval != 0) {
xmlChar buf[10];
int l;
l = xmlCopyCharMultiByte(buf, charval);
buf[l] = 0;
node = xmlNewDocText(doc, buf);
if (node != NULL) {
if (last == NULL) {
last = ret = node;
} else {
last = xmlAddNextSibling(last, node);
}
}
charval = 0;
}
} else
cur++;
}
if ((cur != q) || (ret == NULL)) {
/*
* Handle the last piece of text.
*/
if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
xmlNodeAddContentLen(last, q, cur - q);
} else {
node = xmlNewDocTextLen(doc, q, cur - q);
if (node == NULL) return(ret);
if (last == NULL) {
last = ret = node;
} else {
last = xmlAddNextSibling(last, node);
}
}
}
return(ret);
}
/**
* xmlStringGetNodeList:
* @doc: the document
* @value: the value of the attribute
*
* Parse the value string and build the node list associated. Should
* produce a flat tree with only TEXTs and ENTITY_REFs.
* Returns a pointer to the first child
*/
xmlNodePtr
xmlStringGetNodeList(xmlDocPtr doc, const xmlChar *value) {
xmlNodePtr ret = NULL, last = NULL;
xmlNodePtr node;
xmlChar *val;
const xmlChar *cur = value;
const xmlChar *q;
xmlEntityPtr ent;
if (value == NULL) return(NULL);
q = cur;
while (*cur != 0) {
if (cur[0] == '&') {
int charval = 0;
xmlChar tmp;
/*
* Save the current text.
*/
if (cur != q) {
if ((last != NULL) && (last->type == XML_TEXT_NODE)) {
xmlNodeAddContentLen(last, q, cur - q);
} else {
node = xmlNewDocTextLen(doc, q, cur - q);
if (node == NULL) return(ret);
if (last == NULL)
last = ret = node;
else {
last->next = node;
node->prev = last;
last = node;
}
}
}
q = cur;
if ((cur[1] == '#') && (cur[2] == 'x')) {
cur += 3;
tmp = *cur;
while (tmp != ';') { /* Non input consuming loop */
if ((tmp >= '0') && (tmp <= '9'))
charval = charval * 16 + (tmp - '0');
else if ((tmp >= 'a') && (tmp <= 'f'))
charval = charval * 16 + (tmp - 'a') + 10;
else if ((tmp >= 'A') && (tmp <= 'F'))
charval = charval * 16 + (tmp - 'A') + 10;
else {
xmlTreeErr(XML_TREE_INVALID_HEX, (xmlNodePtr) doc,
NULL);
charval = 0;
break;
}
cur++;
tmp = *cur;
}
if (tmp == ';')
cur++;
q = cur;
} else if (cur[1] == '#') {
cur += 2;
tmp = *cur;
while (tmp != ';') { /* Non input consuming loops */
if ((tmp >= '0') && (tmp <= '9'))
charval = charval * 10 + (tmp - '0');
else {
xmlTreeErr(XML_TREE_INVALID_DEC, (xmlNodePtr) doc,
NULL);
charval = 0;
break;
}
cur++;
tmp = *cur;
}
if (tmp == ';')
cur++;
q = cur;
} else {
/*
* Read the entity string
*/
cur++;
q = cur;
while ((*cur != 0) && (*cur != ';')) cur++;
if (*cur == 0) {
xmlTreeErr(XML_TREE_UNTERMINATED_ENTITY,
(xmlNodePtr) doc, (const char *) q);
return(ret);
}
if (cur != q) {
/*
* Predefined entities don't generate nodes
*/
val = xmlStrndup(q, cur - q);
ent = xmlGetDocEntity(doc, val);
if ((ent != NULL) &&
(ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
if (last == NULL) {
node = xmlNewDocText(doc, ent->content);
last = ret = node;
} else if (last->type != XML_TEXT_NODE) {
node = xmlNewDocText(doc, ent->content);
last = xmlAddNextSibling(last, node);
} else
xmlNodeAddContent(last, ent->content);
} else {
/*
* Create a new REFERENCE_REF node
*/
node = xmlNewReference(doc, val);
if (node == NULL) {
if (val != NULL) xmlFree(val);
return(ret);
}
else if ((ent != NULL) && (ent->children == NULL)) {
xmlNodePtr temp;
ent->children = xmlStringGetNodeList(doc,
(const xmlChar*)node->content);
ent->owner = 1;
temp = ent->children;
while (temp) {
temp->parent = (xmlNodePtr)ent;
temp = temp->next;
}
}
if (last == NULL) {
last = ret = node;
} else {
last = xmlAddNextSibling(last, node);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -