📄 tree.c
字号:
xmlFree(val);
}
cur++;
q = cur;
}
if (charval != 0) {
xmlChar buf[10];
int len;
len = xmlCopyCharMultiByte(buf, charval);
buf[len] = 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);
}
/**
* xmlNodeListGetString:
* @doc: the document
* @list: a Node list
* @inLine: should we replace entity contents or show their external form
*
* Build the string equivalent to the text contained in the Node list
* made of TEXTs and ENTITY_REFs
*
* Returns a pointer to the string copy, the caller must free it with xmlFree().
*/
xmlChar *
xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine)
{
xmlNodePtr node = list;
xmlChar *ret = NULL;
xmlEntityPtr ent;
if (list == NULL)
return (NULL);
while (node != NULL) {
if ((node->type == XML_TEXT_NODE) ||
(node->type == XML_CDATA_SECTION_NODE)) {
if (inLine) {
ret = xmlStrcat(ret, node->content);
} else {
xmlChar *buffer;
buffer = xmlEncodeEntitiesReentrant(doc, node->content);
if (buffer != NULL) {
ret = xmlStrcat(ret, buffer);
xmlFree(buffer);
}
}
} else if (node->type == XML_ENTITY_REF_NODE) {
if (inLine) {
ent = xmlGetDocEntity(doc, node->name);
if (ent != NULL) {
xmlChar *buffer;
/* an entity content can be any "well balanced chunk",
* i.e. the result of the content [43] production:
* http://www.w3.org/TR/REC-xml#NT-content.
* So it can contain text, CDATA section or nested
* entity reference nodes (among others).
* -> we recursive call xmlNodeListGetString()
* which handles these types */
buffer = xmlNodeListGetString(doc, ent->children, 1);
if (buffer != NULL) {
ret = xmlStrcat(ret, buffer);
xmlFree(buffer);
}
} else {
ret = xmlStrcat(ret, node->content);
}
} else {
xmlChar buf[2];
buf[0] = '&';
buf[1] = 0;
ret = xmlStrncat(ret, buf, 1);
ret = xmlStrcat(ret, node->name);
buf[0] = ';';
buf[1] = 0;
ret = xmlStrncat(ret, buf, 1);
}
}
#if 0
else {
xmlGenericError(xmlGenericErrorContext,
"xmlGetNodeListString : invalid node type %d\n",
node->type);
}
#endif
node = node->next;
}
return (ret);
}
#ifdef LIBXML_TREE_ENABLED
/**
* xmlNodeListGetRawString:
* @doc: the document
* @list: a Node list
* @inLine: should we replace entity contents or show their external form
*
* Builds the string equivalent to the text contained in the Node list
* made of TEXTs and ENTITY_REFs, contrary to xmlNodeListGetString()
* this function doesn't do any character encoding handling.
*
* Returns a pointer to the string copy, the caller must free it with xmlFree().
*/
xmlChar *
xmlNodeListGetRawString(xmlDocPtr doc, xmlNodePtr list, int inLine)
{
xmlNodePtr node = list;
xmlChar *ret = NULL;
xmlEntityPtr ent;
if (list == NULL)
return (NULL);
while (node != NULL) {
if ((node->type == XML_TEXT_NODE) ||
(node->type == XML_CDATA_SECTION_NODE)) {
if (inLine) {
ret = xmlStrcat(ret, node->content);
} else {
xmlChar *buffer;
buffer = xmlEncodeSpecialChars(doc, node->content);
if (buffer != NULL) {
ret = xmlStrcat(ret, buffer);
xmlFree(buffer);
}
}
} else if (node->type == XML_ENTITY_REF_NODE) {
if (inLine) {
ent = xmlGetDocEntity(doc, node->name);
if (ent != NULL) {
xmlChar *buffer;
/* an entity content can be any "well balanced chunk",
* i.e. the result of the content [43] production:
* http://www.w3.org/TR/REC-xml#NT-content.
* So it can contain text, CDATA section or nested
* entity reference nodes (among others).
* -> we recursive call xmlNodeListGetRawString()
* which handles these types */
buffer =
xmlNodeListGetRawString(doc, ent->children, 1);
if (buffer != NULL) {
ret = xmlStrcat(ret, buffer);
xmlFree(buffer);
}
} else {
ret = xmlStrcat(ret, node->content);
}
} else {
xmlChar buf[2];
buf[0] = '&';
buf[1] = 0;
ret = xmlStrncat(ret, buf, 1);
ret = xmlStrcat(ret, node->name);
buf[0] = ';';
buf[1] = 0;
ret = xmlStrncat(ret, buf, 1);
}
}
#if 0
else {
xmlGenericError(xmlGenericErrorContext,
"xmlGetNodeListString : invalid node type %d\n",
node->type);
}
#endif
node = node->next;
}
return (ret);
}
#endif /* LIBXML_TREE_ENABLED */
static xmlAttrPtr xmlNewPropInternal(xmlNodePtr node, xmlNsPtr ns,
const xmlChar *name, const xmlChar *value, int eatname) {
xmlAttrPtr cur;
xmlDocPtr doc = NULL;
if ((node != NULL) && (node->type != XML_ELEMENT_NODE)) {
if (eatname == 1)
xmlFree((xmlChar *) name);
return(NULL);
}
/*
* Allocate a new property and fill the fields.
*/
cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
if (cur == NULL) {
if (eatname == 1)
xmlFree((xmlChar *) name);
xmlTreeErrMemory("building attribute");
return(NULL);
}
memset(cur, 0, sizeof(xmlAttr));
cur->type = XML_ATTRIBUTE_NODE;
cur->parent = node;
if (node != NULL) {
doc = node->doc;
cur->doc = doc;
}
cur->ns = ns;
if (eatname == 0) {
if ((doc != NULL) && (doc->dict != NULL))
cur->name = (xmlChar *) xmlDictLookup(doc->dict, name, -1);
else
cur->name = xmlStrdup(name);
} else
cur->name = name;
if (value != NULL) {
xmlChar *buffer;
xmlNodePtr tmp;
buffer = xmlEncodeEntitiesReentrant(doc, value);
cur->children = xmlStringGetNodeList(doc, buffer);
cur->last = NULL;
tmp = cur->children;
while (tmp != NULL) {
tmp->parent = (xmlNodePtr) cur;
if (tmp->next == NULL)
cur->last = tmp;
tmp = tmp->next;
}
xmlFree(buffer);
}
/*
* Add it at the end to preserve parsing order ...
*/
if (node != NULL) {
if (node->properties == NULL) {
node->properties = cur;
} else {
xmlAttrPtr prev = node->properties;
while (prev->next != NULL) prev = prev->next;
prev->next = cur;
cur->prev = prev;
}
}
if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
return(cur);
}
#if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \
defined(LIBXML_SCHEMAS_ENABLED)
/**
* xmlNewProp:
* @node: the holding node
* @name: the name of the attribute
* @value: the value of the attribute
*
* Create a new property carried by a node.
* Returns a pointer to the attribute
*/
xmlAttrPtr
xmlNewProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) {
if (name == NULL) {
#ifdef DEBUG_TREE
xmlGenericError(xmlGenericErrorContext,
"xmlNewProp : name == NULL\n");
#endif
return(NULL);
}
return xmlNewPropInternal(node, NULL, name, value, 0);
}
#endif /* LIBXML_TREE_ENABLED */
/**
* xmlNewNsProp:
* @node: the holding node
* @ns: the namespace
* @name: the name of the attribute
* @value: the value of the attribute
*
* Create a new property tagged with a namespace and carried by a node.
* Returns a pointer to the attribute
*/
xmlAttrPtr
xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
const xmlChar *value) {
if (name == NULL) {
#ifdef DEBUG_TREE
xmlGenericError(xmlGenericErrorContext,
"xmlNewNsProp : name == NULL\n");
#endif
return(NULL);
}
return xmlNewPropInternal(node, ns, name, value, 0);
}
/**
* xmlNewNsPropEatName:
* @node: the holding node
* @ns: the namespace
* @name: the name of the attribute
* @value: the value of the attribute
*
* Create a new property tagged with a namespace and carried by a node.
* Returns a pointer to the attribute
*/
xmlAttrPtr
xmlNewNsPropEatName(xmlNodePtr node, xmlNsPtr ns, xmlChar *name,
const xmlChar *value) {
if (name == NULL) {
#ifdef DEBUG_TREE
xmlGenericError(xmlGenericErrorContext,
"xmlNewNsPropEatName : name == NULL\n");
#endif
return(NULL);
}
return xmlNewPropInternal(node, ns, name, value, 1);
}
/**
* xmlNewDocProp:
* @doc: the document
* @name: the name of the attribute
* @value: the value of the attribute
*
* Create a new property carried by a document.
* Returns a pointer to the attribute
*/
xmlAttrPtr
xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value) {
xmlAttrPtr cur;
if (name == NULL) {
#ifdef DEBUG_TREE
xmlGenericError(xmlGenericErrorContext,
"xmlNewDocProp : name == NULL\n");
#endif
return(NULL);
}
/*
* Allocate a new property and fill the fields.
*/
cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
if (cur == NULL) {
xmlTreeErrMemory("building attribute");
return(NULL);
}
memset(cur, 0, sizeof(xmlAttr));
cur->type = XML_ATTRIBUTE_NODE;
if ((doc != NULL) && (doc->dict != NULL))
cur->name = xmlDictLookup(doc->dict, name, -1);
else
cur->name = xmlStrdup(name);
cur->doc = doc;
if (value != NULL) {
xmlNodePtr tmp;
cur->children = xmlStringGetNodeList(doc, value);
cur->last = NULL;
tmp = cur->children;
while (tmp != NULL) {
tmp->parent = (xmlNodePtr) cur;
if (tmp->next == NULL)
cur->last = tmp;
tmp = tmp->next;
}
}
if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
xmlRegisterNodeDefaultValue((xmlNodePtr)cur);
return(cur);
}
/**
* xmlFreePropList:
* @cur: the first property in the list
*
* Free a property and all its siblings, all the children are freed too.
*/
void
xmlFreePropList(xmlAttrPtr cur) {
xmlAttrPtr next;
if (cur == NULL) return;
while (cur != NULL) {
next = cur->next;
xmlFreeProp(cur);
cur = next;
}
}
/**
* xmlFreeProp:
* @cur: an attribute
*
* Free one attribute, all the content is freed too
*/
void
xmlFreeProp(xmlAttrPtr cur) {
xmlDictPtr dict = NULL;
if (cur == NULL) return;
if (cur->doc != NULL) dict = cur->doc->dict;
if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
xmlDeregisterNodeDefaultValue((xmlNodePtr)cur);
/* Check for ID removal -> leading to invalid references ! */
if ((cur->doc != NULL) && (cur->atype == XML_ATTRIBUTE_ID)) {
xmlRemoveID(cur->doc, cur);
}
if (cur->children != NULL) xmlFreeNodeList(cur->children);
DICT_FREE(cur->name)
xmlFree(cur);
}
#ifdef LIBXML_TREE_ENABLED
/**
* xmlRemoveProp:
* @cur: an attribute
*
* Unlink and free one attribute, all the content is freed too
* Note this doesn't work for namespace definition attributes
*
* Returns 0 if success and -1 in case of error.
*/
int
xmlRemoveProp(xmlAttrPtr cur) {
xmlAttrPtr tmp;
if (cur == NULL) {
#ifdef DEBUG_TREE
xmlGenericError(xmlGenericErrorContext,
"xmlRemoveProp : cur == NULL\n");
#endif
return(-1);
}
if (cur->parent == NULL) {
#ifdef DEBUG_TREE
xmlGenericError(xmlGenericErrorContext,
"xmlRemoveProp : cur->parent == NULL\n");
#endif
return(-1);
}
tmp = cur->parent->properties;
if (tmp == cur) {
cur->parent->properties = cur->next;
xmlFreeProp(cur);
return(0);
}
while (tmp != NULL) {
if (tmp->next == cur) {
tmp->next = cur->next;
if (tmp->next != NULL)
tmp->next->prev = tmp;
xmlFreeProp(cur);
return(0);
}
tmp = tmp->next;
}
#ifdef DEBUG_TREE
xmlGenericError(xmlGenericErrorContext,
"xmlRemoveProp : attribute not owned by its node\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -