diff options
Diffstat (limited to 'bundle/libxml/tree.c')
-rw-r--r-- | bundle/libxml/tree.c | 7566 |
1 files changed, 0 insertions, 7566 deletions
diff --git a/bundle/libxml/tree.c b/bundle/libxml/tree.c deleted file mode 100644 index c3d304501f..0000000000 --- a/bundle/libxml/tree.c +++ /dev/null @@ -1,7566 +0,0 @@ -/* - * tree.c : implementation of access function for an XML tree. - * - * References: - * XHTML 1.0 W3C REC: http://www.w3.org/TR/2002/REC-xhtml1-20020801/ - * - * See Copyright for the status of this software. - * - * daniel@veillard.com - * - */ - -#define IN_LIBXML -#include "libxml.h" - -#include <string.h> /* for memset() only ! */ - -#ifdef HAVE_CTYPE_H -#include <ctype.h> -#endif -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif -#ifdef HAVE_ZLIB_H -#include <zlib.h> -#endif - -#include <libxml/xmlmemory.h> -#include <libxml/tree.h> -#include <libxml/parser.h> -#include <libxml/uri.h> -#include <libxml/entities.h> -#include <libxml/valid.h> -#include <libxml/xmlerror.h> -#include <libxml/parserInternals.h> -#include <libxml/globals.h> -#ifdef LIBXML_HTML_ENABLED -#include <libxml/HTMLtree.h> -#endif - -xmlNsPtr xmlNewReconciliedNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns); - -/************************************************************************ - * * - * A few static variables and macros * - * * - ************************************************************************/ -/* #undef xmlStringText */ -const xmlChar xmlStringText[] = { 't', 'e', 'x', 't', 0 }; -/* #undef xmlStringTextNoenc */ -const xmlChar xmlStringTextNoenc[] = - { 't', 'e', 'x', 't', 'n', 'o', 'e', 'n', 'c', 0 }; -/* #undef xmlStringComment */ -const xmlChar xmlStringComment[] = { 'c', 'o', 'm', 'm', 'e', 'n', 't', 0 }; - -static int xmlCompressMode = 0; -static int xmlCheckDTD = 1; - -#define UPDATE_LAST_CHILD_AND_PARENT(n) if ((n) != NULL) { \ - xmlNodePtr ulccur = (n)->children; \ - if (ulccur == NULL) { \ - (n)->last = NULL; \ - } else { \ - while (ulccur->next != NULL) { \ - ulccur->parent = (n); \ - ulccur = ulccur->next; \ - } \ - ulccur->parent = (n); \ - (n)->last = ulccur; \ -}} - -/* #define DEBUG_BUFFER */ -/* #define DEBUG_TREE */ - -/************************************************************************ - * * - * Functions to move to entities.c once the * - * API freeze is smoothen and they can be made public. * - * * - ************************************************************************/ -#include <libxml/hash.h> - -/** - * xmlGetEntityFromDtd: - * @dtd: A pointer to the DTD to search - * @name: The entity name - * - * Do an entity lookup in the DTD entity hash table and - * return the corresponding entity, if found. - * - * Returns A pointer to the entity structure or NULL if not found. - */ -static xmlEntityPtr -xmlGetEntityFromDtd(xmlDtdPtr dtd, const xmlChar *name) { - xmlEntitiesTablePtr table; - - if((dtd != NULL) && (dtd->entities != NULL)) { - table = (xmlEntitiesTablePtr) dtd->entities; - return((xmlEntityPtr) xmlHashLookup(table, name)); - /* return(xmlGetEntityFromTable(table, name)); */ - } - return(NULL); -} -/** - * xmlGetParameterEntityFromDtd: - * @dtd: A pointer to the DTD to search - * @name: The entity name - * - * Do an entity lookup in the DTD pararmeter entity hash table and - * return the corresponding entity, if found. - * - * Returns A pointer to the entity structure or NULL if not found. - */ -static xmlEntityPtr -xmlGetParameterEntityFromDtd(xmlDtdPtr dtd, const xmlChar *name) { - xmlEntitiesTablePtr table; - - if ((dtd != NULL) && (dtd->pentities != NULL)) { - table = (xmlEntitiesTablePtr) dtd->pentities; - return((xmlEntityPtr) xmlHashLookup(table, name)); - /* return(xmlGetEntityFromTable(table, name)); */ - } - return(NULL); -} - -/************************************************************************ - * * - * Allocation and deallocation of basic structures * - * * - ************************************************************************/ - -/** - * xmlSetBufferAllocationScheme: - * @scheme: allocation method to use - * - * Set the buffer allocation method. Types are - * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down - * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed, - * improves performance - */ -void -xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme) { - xmlBufferAllocScheme = scheme; -} - -/** - * xmlGetBufferAllocationScheme: - * - * Types are - * XML_BUFFER_ALLOC_EXACT - use exact sizes, keeps memory usage down - * XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed, - * improves performance - * - * Returns the current allocation scheme - */ -xmlBufferAllocationScheme -xmlGetBufferAllocationScheme(void) { - return(xmlBufferAllocScheme); -} - -/** - * xmlNewNs: - * @node: the element carrying the namespace - * @href: the URI associated - * @prefix: the prefix for the namespace - * - * Creation of a new Namespace. This function will refuse to create - * a namespace with a similar prefix than an existing one present on this - * node. - * We use href==NULL in the case of an element creation where the namespace - * was not defined. - * Returns a new namespace pointer or NULL - */ -xmlNsPtr -xmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) { - xmlNsPtr cur; - - if ((node != NULL) && (node->type != XML_ELEMENT_NODE)) - return(NULL); - - if ((prefix != NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) - return(NULL); - - /* - * Allocate a new Namespace and fill the fields. - */ - cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); - if (cur == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlNewNs : malloc failed\n"); - return(NULL); - } - memset(cur, 0, sizeof(xmlNs)); - cur->type = XML_LOCAL_NAMESPACE; - - if (href != NULL) - cur->href = xmlStrdup(href); - if (prefix != NULL) - cur->prefix = xmlStrdup(prefix); - - /* - * Add it at the end to preserve parsing order ... - * and checks for existing use of the prefix - */ - if (node != NULL) { - if (node->nsDef == NULL) { - node->nsDef = cur; - } else { - xmlNsPtr prev = node->nsDef; - - if (((prev->prefix == NULL) && (cur->prefix == NULL)) || - (xmlStrEqual(prev->prefix, cur->prefix))) { - xmlFreeNs(cur); - return(NULL); - } - while (prev->next != NULL) { - prev = prev->next; - if (((prev->prefix == NULL) && (cur->prefix == NULL)) || - (xmlStrEqual(prev->prefix, cur->prefix))) { - xmlFreeNs(cur); - return(NULL); - } - } - prev->next = cur; - } - } - return(cur); -} - -/** - * xmlSetNs: - * @node: a node in the document - * @ns: a namespace pointer - * - * Associate a namespace to a node, a posteriori. - */ -void -xmlSetNs(xmlNodePtr node, xmlNsPtr ns) { - if (node == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlSetNs: node == NULL\n"); -#endif - return; - } - node->ns = ns; -} - -/** - * xmlFreeNs: - * @cur: the namespace pointer - * - * Free up the structures associated to a namespace - */ -void -xmlFreeNs(xmlNsPtr cur) { - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlFreeNs : ns == NULL\n"); -#endif - return; - } - if (cur->href != NULL) xmlFree((char *) cur->href); - if (cur->prefix != NULL) xmlFree((char *) cur->prefix); - xmlFree(cur); -} - -/** - * xmlFreeNsList: - * @cur: the first namespace pointer - * - * Free up all the structures associated to the chained namespaces. - */ -void -xmlFreeNsList(xmlNsPtr cur) { - xmlNsPtr next; - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlFreeNsList : ns == NULL\n"); -#endif - return; - } - while (cur != NULL) { - next = cur->next; - xmlFreeNs(cur); - cur = next; - } -} - -/** - * xmlNewDtd: - * @doc: the document pointer - * @name: the DTD name - * @ExternalID: the external ID - * @SystemID: the system ID - * - * Creation of a new DTD for the external subset. To create an - * internal subset, use xmlCreateIntSubset(). - * - * Returns a pointer to the new DTD structure - */ -xmlDtdPtr -xmlNewDtd(xmlDocPtr doc, const xmlChar *name, - const xmlChar *ExternalID, const xmlChar *SystemID) { - xmlDtdPtr cur; - - if ((doc != NULL) && (doc->extSubset != NULL)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewDtd(%s): document %s already have a DTD %s\n", - /* !!! */ (char *) name, doc->name, - /* !!! */ (char *)doc->extSubset->name); -#endif - return(NULL); - } - - /* - * Allocate a new DTD and fill the fields. - */ - cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd)); - if (cur == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlNewDtd : malloc failed\n"); - return(NULL); - } - memset(cur, 0 , sizeof(xmlDtd)); - cur->type = XML_DTD_NODE; - - if (name != NULL) - cur->name = xmlStrdup(name); - if (ExternalID != NULL) - cur->ExternalID = xmlStrdup(ExternalID); - if (SystemID != NULL) - cur->SystemID = xmlStrdup(SystemID); - if (doc != NULL) - doc->extSubset = cur; - cur->doc = doc; - - return(cur); -} - -/** - * xmlGetIntSubset: - * @doc: the document pointer - * - * Get the internal subset of a document - * Returns a pointer to the DTD structure or NULL if not found - */ - -xmlDtdPtr -xmlGetIntSubset(xmlDocPtr doc) { - xmlNodePtr cur; - - if (doc == NULL) - return(NULL); - cur = doc->children; - while (cur != NULL) { - if (cur->type == XML_DTD_NODE) - return((xmlDtdPtr) cur); - cur = cur->next; - } - return((xmlDtdPtr) doc->intSubset); -} - -/** - * xmlCreateIntSubset: - * @doc: the document pointer - * @name: the DTD name - * @ExternalID: the external (PUBLIC) ID - * @SystemID: the system ID - * - * Create the internal subset of a document - * Returns a pointer to the new DTD structure - */ -xmlDtdPtr -xmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name, - const xmlChar *ExternalID, const xmlChar *SystemID) { - xmlDtdPtr cur; - - if ((doc != NULL) && (xmlGetIntSubset(doc) != NULL)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - - "xmlCreateIntSubset(): document %s already have an internal subset\n", - doc->name); -#endif - return(NULL); - } - - /* - * Allocate a new DTD and fill the fields. - */ - cur = (xmlDtdPtr) xmlMalloc(sizeof(xmlDtd)); - if (cur == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlCreateIntSubset : malloc failed\n"); - return(NULL); - } - memset(cur, 0, sizeof(xmlDtd)); - cur->type = XML_DTD_NODE; - - if (name != NULL) - cur->name = xmlStrdup(name); - if (ExternalID != NULL) - cur->ExternalID = xmlStrdup(ExternalID); - if (SystemID != NULL) - cur->SystemID = xmlStrdup(SystemID); - if (doc != NULL) { - doc->intSubset = cur; - cur->parent = doc; - cur->doc = doc; - if (doc->children == NULL) { - doc->children = (xmlNodePtr) cur; - doc->last = (xmlNodePtr) cur; - } else { - if (doc->type == XML_HTML_DOCUMENT_NODE) { - xmlNodePtr prev; - - prev = doc->children; - prev->prev = (xmlNodePtr) cur; - cur->next = prev; - doc->children = (xmlNodePtr) cur; - } else { - xmlNodePtr next; - - next = doc->children; - while ((next != NULL) && (next->type != XML_ELEMENT_NODE)) - next = next->next; - if (next == NULL) { - cur->prev = doc->last; - cur->prev->next = (xmlNodePtr) cur; - cur->next = NULL; - doc->last = (xmlNodePtr) cur; - } else { - cur->next = next; - cur->prev = next->prev; - if (cur->prev == NULL) - doc->children = (xmlNodePtr) cur; - else - cur->prev->next = (xmlNodePtr) cur; - next->prev = (xmlNodePtr) cur; - } - } - } - } - return(cur); -} - -/** - * xmlFreeDtd: - * @cur: the DTD structure to free up - * - * Free a DTD structure. - */ -void -xmlFreeDtd(xmlDtdPtr cur) { - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlFreeDtd : DTD == NULL\n"); -#endif - return; - } - if (cur->children != NULL) { - xmlNodePtr next, c = cur->children; - - /* - * Cleanup all the DTD comments they are not in the DTD - * indexes. - */ - while (c != NULL) { - next = c->next; - if (c->type == XML_COMMENT_NODE) { - xmlUnlinkNode(c); - xmlFreeNode(c); - } - c = next; - } - } - if (cur->name != NULL) xmlFree((char *) cur->name); - if (cur->SystemID != NULL) xmlFree((char *) cur->SystemID); - if (cur->ExternalID != NULL) xmlFree((char *) 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) { - xmlGenericError(xmlGenericErrorContext, - "xmlNewDoc : malloc failed\n"); - return(NULL); - } - memset(cur, 0, sizeof(xmlDoc)); - cur->type = XML_DOCUMENT_NODE; - - cur->version = xmlStrdup(version); - cur->standalone = -1; - cur->compression = -1; /* not initialized */ - cur->doc = cur; - cur->charset = XML_CHAR_ENCODING_UTF8; - 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; - - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlFreeDoc : document == NULL\n"); -#endif - return; - } - /* - * 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->version != NULL) xmlFree((char *) cur->version); - if (cur->name != NULL) xmlFree((char *) cur->name); - if (cur->encoding != NULL) xmlFree((char *) cur->encoding); - if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs); - if (cur->URL != NULL) xmlFree((char *) cur->URL); - xmlFree(cur); -} - -/** - * 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; - const xmlChar *q; - xmlEntityPtr ent; - - if (value == NULL) return(NULL); - - q = cur; - while ((*cur != 0) && (cur - value < len)) { - if (*cur == '&') { - /* - * 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; - } - } - } - /* - * Read the entity string - */ - cur++; - q = cur; - while ((*cur != 0) && (cur - value < len) && (*cur != ';')) cur++; - if ((*cur == 0) || (cur - value >= len)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlStringLenGetNodeList: unterminated entity %30s\n", q); -#endif - 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 - 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 tmp; - - ent->children = - xmlStringGetNodeList(doc, (const xmlChar*)node->content); - tmp = ent->children; - while (tmp) { - tmp->parent = (xmlNodePtr)ent; - tmp = tmp->next; - } - } - if (last == NULL) - last = ret = node; - else { - last->next = node; - node->prev = last; - last = node; - } - } - xmlFree(val); - } - cur++; - q = cur; - } else - cur++; - } - if (cur != q) { - /* - * 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->next = node; - node->prev = last; - 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 { - xmlGenericError(xmlGenericErrorContext, - "xmlStringGetNodeList: invalid hexadecimal charvalue\n"); - 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 { - xmlGenericError(xmlGenericErrorContext, - "xmlStringGetNodeList: invalid decimal charvalue\n"); - 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) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlStringGetNodeList: unterminated entity %30s\n", q); -#endif - 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); - temp = ent->children; - while (temp) { - temp->parent = (xmlNodePtr)ent; - 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 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); -} -/** - * 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); -} - -/** - * 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) { - xmlAttrPtr cur; - xmlDocPtr doc = NULL; - - if (name == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewProp : name == NULL\n"); -#endif - return(NULL); - } - - /* - * Allocate a new property and fill the fields. - */ - cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr)); - if (cur == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlNewProp : malloc failed\n"); - 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->name = xmlStrdup(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; - tmp->doc = doc; - 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; - } - } - return(cur); -} - -/** - * 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) { - xmlAttrPtr cur; - xmlDocPtr doc = NULL; - - if (name == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewNsProp : name == NULL\n"); -#endif - return(NULL); - } - - /* - * Allocate a new property and fill the fields. - */ - cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr)); - if (cur == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlNewNsProp : malloc failed\n"); - 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; - cur->name = xmlStrdup(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; - } - } - return(cur); -} - -/** - * 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) { - xmlAttrPtr cur; - xmlDocPtr doc = NULL; - - if (name == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewNsPropEatName : name == NULL\n"); -#endif - return(NULL); - } - - /* - * Allocate a new property and fill the fields. - */ - cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr)); - if (cur == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlNewNsPropEatName : malloc failed\n"); - 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; - 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; - } - } - return(cur); -} - -/** - * 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) { - xmlGenericError(xmlGenericErrorContext, - "xmlNewDocProp : malloc failed\n"); - return(NULL); - } - memset(cur, 0, sizeof(xmlAttr)); - cur->type = XML_ATTRIBUTE_NODE; - - 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; - } - } - 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) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlFreePropList : property == NULL\n"); -#endif - 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) { - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlFreeProp : property == NULL\n"); -#endif - return; - } - /* Check for ID removal -> leading to invalid references ! */ - if ((cur->parent != NULL) && (cur->parent->doc != NULL) && - ((cur->parent->doc->intSubset != NULL) || - (cur->parent->doc->extSubset != NULL))) { - if (xmlIsID(cur->parent->doc, cur->parent, cur)) - xmlRemoveID(cur->parent->doc, cur); - } - if (cur->name != NULL) xmlFree((char *) cur->name); - if (cur->children != NULL) xmlFreeNodeList(cur->children); - xmlFree(cur); -} - -/** - * 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"); -#endif - return(-1); -} - -/** - * xmlNewPI: - * @name: the processing instruction name - * @content: the PI content - * - * Creation of a processing instruction element. - * Returns a pointer to the new node object. - */ -xmlNodePtr -xmlNewPI(const xmlChar *name, const xmlChar *content) { - xmlNodePtr cur; - - if (name == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewPI : name == NULL\n"); -#endif - return(NULL); - } - - /* - * Allocate a new node and fill the fields. - */ - cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlNewPI : malloc failed\n"); - return(NULL); - } - memset(cur, 0, sizeof(xmlNode)); - cur->type = XML_PI_NODE; - - cur->name = xmlStrdup(name); - if (content != NULL) { - cur->content = xmlStrdup(content); - } - return(cur); -} - -/** - * xmlNewNode: - * @ns: namespace if any - * @name: the node name - * - * Creation of a new node element. @ns is optional (NULL). - * - * Returns a pointer to the new node object. - */ -xmlNodePtr -xmlNewNode(xmlNsPtr ns, const xmlChar *name) { - xmlNodePtr cur; - - if (name == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewNode : name == NULL\n"); -#endif - return(NULL); - } - - /* - * Allocate a new node and fill the fields. - */ - cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlNewNode : malloc failed\n"); - return(NULL); - } - memset(cur, 0, sizeof(xmlNode)); - cur->type = XML_ELEMENT_NODE; - - cur->name = xmlStrdup(name); - cur->ns = ns; - return(cur); -} - -/** - * xmlNewNodeEatName: - * @ns: namespace if any - * @name: the node name - * - * Creation of a new node element. @ns is optional (NULL). - * - * Returns a pointer to the new node object. - */ -xmlNodePtr -xmlNewNodeEatName(xmlNsPtr ns, xmlChar *name) { - xmlNodePtr cur; - - if (name == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewNode : name == NULL\n"); -#endif - return(NULL); - } - - /* - * Allocate a new node and fill the fields. - */ - cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlNewNode : malloc failed\n"); - return(NULL); - } - memset(cur, 0, sizeof(xmlNode)); - cur->type = XML_ELEMENT_NODE; - - cur->name = name; - cur->ns = ns; - return(cur); -} - -/** - * xmlNewDocNode: - * @doc: the document - * @ns: namespace if any - * @name: the node name - * @content: the XML text content if any - * - * Creation of a new node element within a document. @ns and @content - * are optional (NULL). - * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities - * references, but XML special chars need to be escaped first by using - * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't - * need entities support. - * - * Returns a pointer to the new node object. - */ -xmlNodePtr -xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns, - const xmlChar *name, const xmlChar *content) { - xmlNodePtr cur; - - cur = xmlNewNode(ns, name); - if (cur != NULL) { - cur->doc = doc; - if (content != NULL) { - cur->children = xmlStringGetNodeList(doc, content); - UPDATE_LAST_CHILD_AND_PARENT(cur) - } - } - return(cur); -} - -/** - * xmlNewDocNodeEatName: - * @doc: the document - * @ns: namespace if any - * @name: the node name - * @content: the XML text content if any - * - * Creation of a new node element within a document. @ns and @content - * are optional (NULL). - * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities - * references, but XML special chars need to be escaped first by using - * xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't - * need entities support. - * - * Returns a pointer to the new node object. - */ -xmlNodePtr -xmlNewDocNodeEatName(xmlDocPtr doc, xmlNsPtr ns, - xmlChar *name, const xmlChar *content) { - xmlNodePtr cur; - - cur = xmlNewNodeEatName(ns, name); - if (cur != NULL) { - cur->doc = doc; - if (content != NULL) { - cur->children = xmlStringGetNodeList(doc, content); - UPDATE_LAST_CHILD_AND_PARENT(cur) - } - } - return(cur); -} - - -/** - * xmlNewDocRawNode: - * @doc: the document - * @ns: namespace if any - * @name: the node name - * @content: the text content if any - * - * Creation of a new node element within a document. @ns and @content - * are optional (NULL). - * - * Returns a pointer to the new node object. - */ -xmlNodePtr -xmlNewDocRawNode(xmlDocPtr doc, xmlNsPtr ns, - const xmlChar *name, const xmlChar *content) { - xmlNodePtr cur; - - cur = xmlNewNode(ns, name); - if (cur != NULL) { - cur->doc = doc; - if (content != NULL) { - cur->children = xmlNewDocText(doc, content); - UPDATE_LAST_CHILD_AND_PARENT(cur) - } - } - return(cur); -} - -/** - * xmlNewDocFragment: - * @doc: the document owning the fragment - * - * Creation of a new Fragment node. - * Returns a pointer to the new node object. - */ -xmlNodePtr -xmlNewDocFragment(xmlDocPtr doc) { - xmlNodePtr cur; - - /* - * Allocate a new DocumentFragment node and fill the fields. - */ - cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlNewDocFragment : malloc failed\n"); - return(NULL); - } - memset(cur, 0, sizeof(xmlNode)); - cur->type = XML_DOCUMENT_FRAG_NODE; - - cur->doc = doc; - return(cur); -} - -/** - * xmlNewText: - * @content: the text content - * - * Creation of a new text node. - * Returns a pointer to the new node object. - */ -xmlNodePtr -xmlNewText(const xmlChar *content) { - xmlNodePtr cur; - - /* - * Allocate a new node and fill the fields. - */ - cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlNewText : malloc failed\n"); - return(NULL); - } - memset(cur, 0, sizeof(xmlNode)); - cur->type = XML_TEXT_NODE; - - cur->name = xmlStringText; - if (content != NULL) { - cur->content = xmlStrdup(content); - } - return(cur); -} - -/** - * xmlNewTextChild: - * @parent: the parent node - * @ns: a namespace if any - * @name: the name of the child - * @content: the text content of the child if any. - * - * Creation of a new child element, added at the end of @parent children list. - * @ns and @content parameters are optional (NULL). If content is non NULL, - * a child TEXT node will be created containing the string content. - * - * Returns a pointer to the new node object. - */ -xmlNodePtr -xmlNewTextChild(xmlNodePtr parent, xmlNsPtr ns, - const xmlChar *name, const xmlChar *content) { - xmlNodePtr cur, prev; - - if (parent == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewTextChild : parent == NULL\n"); -#endif - return(NULL); - } - - if (name == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewTextChild : name == NULL\n"); -#endif - return(NULL); - } - - /* - * Allocate a new node - */ - if (ns == NULL) - cur = xmlNewDocRawNode(parent->doc, parent->ns, name, content); - else - cur = xmlNewDocRawNode(parent->doc, ns, name, content); - if (cur == NULL) return(NULL); - - /* - * add the new element at the end of the children list. - */ - cur->type = XML_ELEMENT_NODE; - cur->parent = parent; - cur->doc = parent->doc; - if (parent->children == NULL) { - parent->children = cur; - parent->last = cur; - } else { - prev = parent->last; - prev->next = cur; - cur->prev = prev; - parent->last = cur; - } - - return(cur); -} - -/** - * xmlNewCharRef: - * @doc: the document - * @name: the char ref string, starting with # or "&# ... ;" - * - * Creation of a new character reference node. - * Returns a pointer to the new node object. - */ -xmlNodePtr -xmlNewCharRef(xmlDocPtr doc, const xmlChar *name) { - xmlNodePtr cur; - - /* - * Allocate a new node and fill the fields. - */ - cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlNewCharRef : malloc failed\n"); - return(NULL); - } - memset(cur, 0, sizeof(xmlNode)); - cur->type = XML_ENTITY_REF_NODE; - - cur->doc = doc; - if (name[0] == '&') { - int len; - name++; - len = xmlStrlen(name); - if (name[len - 1] == ';') - cur->name = xmlStrndup(name, len - 1); - else - cur->name = xmlStrndup(name, len); - } else - cur->name = xmlStrdup(name); - return(cur); -} - -/** - * xmlNewReference: - * @doc: the document - * @name: the reference name, or the reference string with & and ; - * - * Creation of a new reference node. - * Returns a pointer to the new node object. - */ -xmlNodePtr -xmlNewReference(xmlDocPtr doc, const xmlChar *name) { - xmlNodePtr cur; - xmlEntityPtr ent; - - /* - * Allocate a new node and fill the fields. - */ - cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlNewReference : malloc failed\n"); - return(NULL); - } - memset(cur, 0, sizeof(xmlNode)); - cur->type = XML_ENTITY_REF_NODE; - - cur->doc = doc; - if (name[0] == '&') { - int len; - name++; - len = xmlStrlen(name); - if (name[len - 1] == ';') - cur->name = xmlStrndup(name, len - 1); - else - cur->name = xmlStrndup(name, len); - } else - cur->name = xmlStrdup(name); - - ent = xmlGetDocEntity(doc, cur->name); - if (ent != NULL) { - cur->content = ent->content; - /* - * The parent pointer in entity is a DTD pointer and thus is NOT - * updated. Not sure if this is 100% correct. - * -George - */ - cur->children = (xmlNodePtr) ent; - cur->last = (xmlNodePtr) ent; - } - return(cur); -} - -/** - * xmlNewDocText: - * @doc: the document - * @content: the text content - * - * Creation of a new text node within a document. - * Returns a pointer to the new node object. - */ -xmlNodePtr -xmlNewDocText(xmlDocPtr doc, const xmlChar *content) { - xmlNodePtr cur; - - cur = xmlNewText(content); - if (cur != NULL) cur->doc = doc; - return(cur); -} - -/** - * xmlNewTextLen: - * @content: the text content - * @len: the text len. - * - * Creation of a new text node with an extra parameter for the content's length - * Returns a pointer to the new node object. - */ -xmlNodePtr -xmlNewTextLen(const xmlChar *content, int len) { - xmlNodePtr cur; - - /* - * Allocate a new node and fill the fields. - */ - cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlNewTextLen : malloc failed\n"); - return(NULL); - } - memset(cur, 0, sizeof(xmlNode)); - cur->type = XML_TEXT_NODE; - - cur->name = xmlStringText; - if (content != NULL) { - cur->content = xmlStrndup(content, len); - } - return(cur); -} - -/** - * xmlNewDocTextLen: - * @doc: the document - * @content: the text content - * @len: the text len. - * - * Creation of a new text node with an extra content length parameter. The - * text node pertain to a given document. - * Returns a pointer to the new node object. - */ -xmlNodePtr -xmlNewDocTextLen(xmlDocPtr doc, const xmlChar *content, int len) { - xmlNodePtr cur; - - cur = xmlNewTextLen(content, len); - if (cur != NULL) cur->doc = doc; - return(cur); -} - -/** - * xmlNewComment: - * @content: the comment content - * - * Creation of a new node containing a comment. - * Returns a pointer to the new node object. - */ -xmlNodePtr -xmlNewComment(const xmlChar *content) { - xmlNodePtr cur; - - /* - * Allocate a new node and fill the fields. - */ - cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlNewComment : malloc failed\n"); - return(NULL); - } - memset(cur, 0, sizeof(xmlNode)); - cur->type = XML_COMMENT_NODE; - - cur->name = xmlStringComment; - if (content != NULL) { - cur->content = xmlStrdup(content); - } - return(cur); -} - -/** - * xmlNewCDataBlock: - * @doc: the document - * @content: the CDATA block content content - * @len: the length of the block - * - * Creation of a new node containing a CDATA block. - * Returns a pointer to the new node object. - */ -xmlNodePtr -xmlNewCDataBlock(xmlDocPtr doc, const xmlChar *content, int len) { - xmlNodePtr cur; - - /* - * Allocate a new node and fill the fields. - */ - cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (cur == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlNewCDataBlock : malloc failed\n"); - return(NULL); - } - memset(cur, 0, sizeof(xmlNode)); - cur->type = XML_CDATA_SECTION_NODE; - cur->doc = doc; - - if (content != NULL) { - cur->content = xmlStrndup(content, len); - } - return(cur); -} - -/** - * xmlNewDocComment: - * @doc: the document - * @content: the comment content - * - * Creation of a new node containing a comment within a document. - * Returns a pointer to the new node object. - */ -xmlNodePtr -xmlNewDocComment(xmlDocPtr doc, const xmlChar *content) { - xmlNodePtr cur; - - cur = xmlNewComment(content); - if (cur != NULL) cur->doc = doc; - return(cur); -} - -/** - * xmlSetTreeDoc: - * @tree: the top element - * @doc: the document - * - * update all nodes under the tree to point to the right document - */ -void -xmlSetTreeDoc(xmlNodePtr tree, xmlDocPtr doc) { - xmlAttrPtr prop; - - if (tree == NULL) - return; - if (tree->doc != doc) { - if(tree->type == XML_ELEMENT_NODE) { - prop = tree->properties; - while (prop != NULL) { - prop->doc = doc; - xmlSetListDoc(prop->children, doc); - prop = prop->next; - } - } - if (tree->children != NULL) - xmlSetListDoc(tree->children, doc); - tree->doc = doc; - } -} - -/** - * xmlSetListDoc: - * @list: the first element - * @doc: the document - * - * update all nodes in the list to point to the right document - */ -void -xmlSetListDoc(xmlNodePtr list, xmlDocPtr doc) { - xmlNodePtr cur; - - if (list == NULL) - return; - cur = list; - while (cur != NULL) { - if (cur->doc != doc) - xmlSetTreeDoc(cur, doc); - cur = cur->next; - } -} - - -/** - * xmlNewChild: - * @parent: the parent node - * @ns: a namespace if any - * @name: the name of the child - * @content: the XML content of the child if any. - * - * Creation of a new child element, added at the end of @parent children list. - * @ns and @content parameters are optional (NULL). If content is non NULL, - * a child list containing the TEXTs and ENTITY_REFs node will be created. - * NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities - * references, but XML special chars need to be escaped first by using - * xmlEncodeEntitiesReentrant(). Use xmlNewTextChild() if entities - * support is not needed. - * - * Returns a pointer to the new node object. - */ -xmlNodePtr -xmlNewChild(xmlNodePtr parent, xmlNsPtr ns, - const xmlChar *name, const xmlChar *content) { - xmlNodePtr cur, prev; - - if (parent == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewChild : parent == NULL\n"); -#endif - return(NULL); - } - - if (name == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewChild : name == NULL\n"); -#endif - return(NULL); - } - - /* - * Allocate a new node - */ - if (parent->type == XML_ELEMENT_NODE) { - if (ns == NULL) - cur = xmlNewDocNode(parent->doc, parent->ns, name, content); - else - cur = xmlNewDocNode(parent->doc, ns, name, content); - } else if ((parent->type == XML_DOCUMENT_NODE) || - (parent->type == XML_HTML_DOCUMENT_NODE)) { - if (ns == NULL) - cur = xmlNewDocNode((xmlDocPtr) parent, NULL, name, content); - else - cur = xmlNewDocNode((xmlDocPtr) parent, ns, name, content); - } else if (parent->type == XML_DOCUMENT_FRAG_NODE) { - cur = xmlNewDocNode( parent->doc, ns, name, content); - } else { - return(NULL); - } - if (cur == NULL) return(NULL); - - /* - * add the new element at the end of the children list. - */ - cur->type = XML_ELEMENT_NODE; - cur->parent = parent; - cur->doc = parent->doc; - if (parent->children == NULL) { - parent->children = cur; - parent->last = cur; - } else { - prev = parent->last; - prev->next = cur; - cur->prev = prev; - parent->last = cur; - } - - return(cur); -} - -/** - * xmlAddNextSibling: - * @cur: the child node - * @elem: the new node - * - * Add a new node @elem as the next sibling of @cur - * If the new node was already inserted in a document it is - * first unlinked from its existing context. - * As a result of text merging @elem may be freed. - * If the new node is ATTRIBUTE, it is added into properties instead of children. - * If there is an attribute with equal name, it is first destroyed. - * - * Returns the new node or NULL in case of error. - */ -xmlNodePtr -xmlAddNextSibling(xmlNodePtr cur, xmlNodePtr elem) { - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAddNextSibling : cur == NULL\n"); -#endif - return(NULL); - } - if (elem == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAddNextSibling : elem == NULL\n"); -#endif - return(NULL); - } - - xmlUnlinkNode(elem); - - if (elem->type == XML_TEXT_NODE) { - if (cur->type == XML_TEXT_NODE) { - xmlNodeAddContent(cur, elem->content); - xmlFreeNode(elem); - return(cur); - } - if ((cur->next != NULL) && (cur->next->type == XML_TEXT_NODE) && - (cur->name == cur->next->name)) { - xmlChar *tmp; - - tmp = xmlStrdup(elem->content); - tmp = xmlStrcat(tmp, cur->next->content); - xmlNodeSetContent(cur->next, tmp); - xmlFree(tmp); - xmlFreeNode(elem); - return(cur->next); - } - } else if (elem->type == XML_ATTRIBUTE_NODE) { - /* check if an attribute with the same name exists */ - xmlAttrPtr attr; - - if (elem->ns == NULL) - attr = xmlHasProp(cur->parent, elem->name); - else - attr = xmlHasNsProp(cur->parent, elem->name, elem->ns->href); - if ((attr != NULL) && (attr != (xmlAttrPtr) elem)) { - /* different instance, destroy it (attributes must be unique) */ - xmlFreeProp(attr); - } - } - - if (elem->doc != cur->doc) { - xmlSetTreeDoc(elem, cur->doc); - } - elem->parent = cur->parent; - elem->prev = cur; - elem->next = cur->next; - cur->next = elem; - if (elem->next != NULL) - elem->next->prev = elem; - if ((elem->parent != NULL) && (elem->parent->last == cur) && (elem->type != XML_ATTRIBUTE_NODE)) - elem->parent->last = elem; - return(elem); -} - -/** - * xmlAddPrevSibling: - * @cur: the child node - * @elem: the new node - * - * Add a new node @elem as the previous sibling of @cur - * merging adjacent TEXT nodes (@elem may be freed) - * If the new node was already inserted in a document it is - * first unlinked from its existing context. - * If the new node is ATTRIBUTE, it is added into properties instead of children. - * If there is an attribute with equal name, it is first destroyed. - * - * Returns the new node or NULL in case of error. - */ -xmlNodePtr -xmlAddPrevSibling(xmlNodePtr cur, xmlNodePtr elem) { - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAddPrevSibling : cur == NULL\n"); -#endif - return(NULL); - } - if (elem == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAddPrevSibling : elem == NULL\n"); -#endif - return(NULL); - } - - xmlUnlinkNode(elem); - - if (elem->type == XML_TEXT_NODE) { - if (cur->type == XML_TEXT_NODE) { - xmlChar *tmp; - - tmp = xmlStrdup(elem->content); - tmp = xmlStrcat(tmp, cur->content); - xmlNodeSetContent(cur, tmp); - xmlFree(tmp); - xmlFreeNode(elem); - return(cur); - } - if ((cur->prev != NULL) && (cur->prev->type == XML_TEXT_NODE) && - (cur->name == cur->prev->name)) { - xmlNodeAddContent(cur->prev, elem->content); - xmlFreeNode(elem); - return(cur->prev); - } - } else if (elem->type == XML_ATTRIBUTE_NODE) { - /* check if an attribute with the same name exists */ - xmlAttrPtr attr; - - if (elem->ns == NULL) - attr = xmlHasProp(cur->parent, elem->name); - else - attr = xmlHasNsProp(cur->parent, elem->name, elem->ns->href); - if ((attr != NULL) && (attr != (xmlAttrPtr) elem)) { - /* different instance, destroy it (attributes must be unique) */ - xmlFreeProp(attr); - } - } - - if (elem->doc != cur->doc) { - xmlSetTreeDoc(elem, cur->doc); - } - elem->parent = cur->parent; - elem->next = cur; - elem->prev = cur->prev; - cur->prev = elem; - if (elem->prev != NULL) - elem->prev->next = elem; - if (elem->parent != NULL) { - if (elem->type == XML_ATTRIBUTE_NODE) { - if (elem->parent->properties == (xmlAttrPtr) cur) { - elem->parent->properties = (xmlAttrPtr) elem; - } - } else { - if (elem->parent->children == cur) { - elem->parent->children = elem; - } - } - } - return(elem); -} - -/** - * xmlAddSibling: - * @cur: the child node - * @elem: the new node - * - * Add a new element @elem to the list of siblings of @cur - * merging adjacent TEXT nodes (@elem may be freed) - * If the new element was already inserted in a document it is - * first unlinked from its existing context. - * - * Returns the new element or NULL in case of error. - */ -xmlNodePtr -xmlAddSibling(xmlNodePtr cur, xmlNodePtr elem) { - xmlNodePtr parent; - - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAddSibling : cur == NULL\n"); -#endif - return(NULL); - } - - if (elem == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAddSibling : elem == NULL\n"); -#endif - return(NULL); - } - - /* - * Constant time is we can rely on the ->parent->last to find - * the last sibling. - */ - if ((cur->parent != NULL) && - (cur->parent->children != NULL) && - (cur->parent->last != NULL) && - (cur->parent->last->next == NULL)) { - cur = cur->parent->last; - } else { - while (cur->next != NULL) cur = cur->next; - } - - xmlUnlinkNode(elem); - - if ((cur->type == XML_TEXT_NODE) && (elem->type == XML_TEXT_NODE)) { - xmlNodeAddContent(cur, elem->content); - xmlFreeNode(elem); - return(cur); - } - - if (elem->doc != cur->doc) { - xmlSetTreeDoc(elem, cur->doc); - } - parent = cur->parent; - elem->prev = cur; - elem->next = NULL; - elem->parent = parent; - cur->next = elem; - if (parent != NULL) - parent->last = elem; - - return(elem); -} - -/** - * xmlAddChildList: - * @parent: the parent node - * @cur: the first node in the list - * - * Add a list of node at the end of the child list of the parent - * merging adjacent TEXT nodes (@cur may be freed) - * - * Returns the last child or NULL in case of error. - */ -xmlNodePtr -xmlAddChildList(xmlNodePtr parent, xmlNodePtr cur) { - xmlNodePtr prev; - - if (parent == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAddChildList : parent == NULL\n"); -#endif - return(NULL); - } - - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAddChildList : child == NULL\n"); -#endif - return(NULL); - } - - if ((cur->doc != NULL) && (parent->doc != NULL) && - (cur->doc != parent->doc)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "Elements moved to a different document\n"); -#endif - } - - /* - * add the first element at the end of the children list. - */ - if (parent->children == NULL) { - parent->children = cur; - } else { - /* - * If cur and parent->last both are TEXT nodes, then merge them. - */ - if ((cur->type == XML_TEXT_NODE) && - (parent->last->type == XML_TEXT_NODE) && - (cur->name == parent->last->name)) { - xmlNodeAddContent(parent->last, cur->content); - /* - * if it's the only child, nothing more to be done. - */ - if (cur->next == NULL) { - xmlFreeNode(cur); - return(parent->last); - } - prev = cur; - cur = cur->next; - xmlFreeNode(prev); - } - prev = parent->last; - prev->next = cur; - cur->prev = prev; - } - while (cur->next != NULL) { - cur->parent = parent; - if (cur->doc != parent->doc) { - xmlSetTreeDoc(cur, parent->doc); - } - cur = cur->next; - } - cur->parent = parent; - cur->doc = parent->doc; /* the parent may not be linked to a doc ! */ - parent->last = cur; - - return(cur); -} - -/** - * xmlAddChild: - * @parent: the parent node - * @cur: the child node - * - * Add a new node to @parent, at the end of the child (or property) list - * merging adjacent TEXT nodes (in which case @cur is freed) - * If the new node was already inserted in a document it is - * first unlinked from its existing context. - * If the new node is ATTRIBUTE, it is added into properties instead of children. - * If there is an attribute with equal name, it is first destroyed. - * - * Returns the child or NULL in case of error. - */ -xmlNodePtr -xmlAddChild(xmlNodePtr parent, xmlNodePtr cur) { - xmlNodePtr prev; - - if (parent == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAddChild : parent == NULL\n"); -#endif - return(NULL); - } - - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAddChild : child == NULL\n"); -#endif - return(NULL); - } - - /* - * If cur is a TEXT node, merge its content with adjacent TEXT nodes - * cur is then freed. - */ - if (cur->type == XML_TEXT_NODE) { - if ((parent->type == XML_TEXT_NODE) && - (parent->content != NULL)) { - xmlNodeAddContent(parent, cur->content); - xmlFreeNode(cur); - return(parent); - } - if ((parent->last != NULL) && (parent->last->type == XML_TEXT_NODE) && - (parent->last->name == cur->name)) { - xmlNodeAddContent(parent->last, cur->content); - xmlFreeNode(cur); - return(parent->last); - } - } - - /* - * add the new element at the end of the children list. - */ - cur->parent = parent; - if (cur->doc != parent->doc) { - xmlSetTreeDoc(cur, parent->doc); - } - - /* - * Coalescing - */ - if ((parent->type == XML_TEXT_NODE) && - (parent->content != NULL)) { - xmlNodeAddContent(parent, cur->content); - xmlFreeNode(cur); - return(parent); - } - if (cur->type == XML_ATTRIBUTE_NODE) { - if (parent->properties == NULL) { - parent->properties = (xmlAttrPtr) cur; - } else { - /* check if an attribute with the same name exists */ - xmlAttrPtr lastattr; - - if (cur->ns == NULL) - lastattr = xmlHasProp(parent, cur->name); - else - lastattr = xmlHasNsProp(parent, cur->name, cur->ns->href); - if ((lastattr != NULL) && (lastattr != (xmlAttrPtr) cur)) { - /* different instance, destroy it (attributes must be unique) */ - xmlFreeProp(lastattr); - } - /* find the end */ - lastattr = parent->properties; - while (lastattr->next != NULL) { - lastattr = lastattr->next; - } - lastattr->next = (xmlAttrPtr) cur; - ((xmlAttrPtr) cur)->prev = lastattr; - } - } else { - if (parent->children == NULL) { - parent->children = cur; - parent->last = cur; - } else { - prev = parent->last; - prev->next = cur; - cur->prev = prev; - parent->last = cur; - } - } - return(cur); -} - -/** - * xmlGetLastChild: - * @parent: the parent node - * - * Search the last child of a node. - * Returns the last child or NULL if none. - */ -xmlNodePtr -xmlGetLastChild(xmlNodePtr parent) { - if (parent == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlGetLastChild : parent == NULL\n"); -#endif - return(NULL); - } - return(parent->last); -} - -/** - * xmlFreeNodeList: - * @cur: the first node in the list - * - * Free a node and all its siblings, this is a recursive behaviour, all - * the children are freed too. - */ -void -xmlFreeNodeList(xmlNodePtr cur) { - xmlNodePtr next; - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlFreeNodeList : node == NULL\n"); -#endif - return; - } - if (cur->type == XML_NAMESPACE_DECL) { - xmlFreeNsList((xmlNsPtr) cur); - return; - } - while (cur != NULL) { - next = cur->next; - /* unroll to speed up freeing the document */ - if (cur->type != XML_DTD_NODE) { - if ((cur->children != NULL) && - (cur->type != XML_ENTITY_REF_NODE)) - xmlFreeNodeList(cur->children); - if (((cur->type == XML_ELEMENT_NODE) || - (cur->type == XML_XINCLUDE_START) || - (cur->type == XML_XINCLUDE_END)) && - (cur->properties != NULL)) - xmlFreePropList(cur->properties); - if ((cur->type != XML_ELEMENT_NODE) && - (cur->type != XML_XINCLUDE_START) && - (cur->type != XML_XINCLUDE_END) && - (cur->type != XML_ENTITY_REF_NODE)) { - if (cur->content != NULL) xmlFree(cur->content); - } - if (((cur->type == XML_ELEMENT_NODE) || - (cur->type == XML_XINCLUDE_START) || - (cur->type == XML_XINCLUDE_END)) && - (cur->nsDef != NULL)) - xmlFreeNsList(cur->nsDef); - - /* - * When a node is a text node or a comment, it uses a global static - * variable for the name of the node. - * - * The xmlStrEqual comparisons need to be done when (happened with - * XML::libXML and XML::libXSLT) the library is included twice - * statically in the binary and a tree allocated by one occurrence - * of the lib gets freed by the other occurrence, in this case - * the string addresses compare are not sufficient. - */ - if ((cur->name != NULL) && - (cur->name != xmlStringText) && - (cur->name != xmlStringTextNoenc) && - (cur->name != xmlStringComment)) { - if (cur->type == XML_TEXT_NODE) { - if ((!xmlStrEqual(cur->name, xmlStringText)) && - (!xmlStrEqual(cur->name, xmlStringTextNoenc))) - xmlFree((char *) cur->name); - } else if (cur->type == XML_COMMENT_NODE) { - if (!xmlStrEqual(cur->name, xmlStringComment)) - xmlFree((char *) cur->name); - } else - xmlFree((char *) cur->name); - } - /* TODO : derecursivate this function */ - xmlFree(cur); - } - cur = next; - } -} - -/** - * xmlFreeNode: - * @cur: the node - * - * Free a node, this is a recursive behaviour, all the children are freed too. - * This doesn't unlink the child from the list, use xmlUnlinkNode() first. - */ -void -xmlFreeNode(xmlNodePtr cur) { - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlFreeNode : node == NULL\n"); -#endif - return; - } - /* use xmlFreeDtd for DTD nodes */ - if (cur->type == XML_DTD_NODE) { - xmlFreeDtd((xmlDtdPtr) cur); - return; - } - if (cur->type == XML_NAMESPACE_DECL) { - xmlFreeNs((xmlNsPtr) cur); - return; - } - if (cur->type == XML_ATTRIBUTE_NODE) { - xmlFreeProp((xmlAttrPtr) cur); - return; - } - if ((cur->children != NULL) && - (cur->type != XML_ENTITY_REF_NODE)) - xmlFreeNodeList(cur->children); - if (((cur->type == XML_ELEMENT_NODE) || - (cur->type == XML_XINCLUDE_START) || - (cur->type == XML_XINCLUDE_END)) && - (cur->properties != NULL)) - xmlFreePropList(cur->properties); - if ((cur->type != XML_ELEMENT_NODE) && - (cur->content != NULL) && - (cur->type != XML_ENTITY_REF_NODE) && - (cur->type != XML_XINCLUDE_END) && - (cur->type != XML_XINCLUDE_START)) { - xmlFree(cur->content); - } - - /* - * When a node is a text node or a comment, it uses a global static - * variable for the name of the node. - * - * The xmlStrEqual comparisons need to be done when (happened with - * XML::libXML and XML::libXSLT) the library is included twice statically - * in the binary and a tree allocated by one occurence of the lib gets - * freed by the other occurrence, in this case the string addresses compare - * are not sufficient. - */ - if ((cur->name != NULL) && - (cur->name != xmlStringText) && - (cur->name != xmlStringTextNoenc) && - (cur->name != xmlStringComment)) { - if (cur->type == XML_TEXT_NODE) { - if ((!xmlStrEqual(cur->name, xmlStringText)) && - (!xmlStrEqual(cur->name, xmlStringTextNoenc))) - xmlFree((char *) cur->name); - } else if (cur->type == XML_COMMENT_NODE) { - if (!xmlStrEqual(cur->name, xmlStringComment)) - xmlFree((char *) cur->name); - } else - xmlFree((char *) cur->name); - } - - if (((cur->type == XML_ELEMENT_NODE) || - (cur->type == XML_XINCLUDE_START) || - (cur->type == XML_XINCLUDE_END)) && - (cur->nsDef != NULL)) - xmlFreeNsList(cur->nsDef); - xmlFree(cur); -} - -/** - * xmlUnlinkNode: - * @cur: the node - * - * Unlink a node from it's current context, the node is not freed - */ -void -xmlUnlinkNode(xmlNodePtr cur) { - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlUnlinkNode : node == NULL\n"); -#endif - return; - } - if (cur->type == XML_DTD_NODE) { - xmlDocPtr doc; - doc = cur->doc; - if (doc->intSubset == (xmlDtdPtr) cur) - doc->intSubset = NULL; - if (doc->extSubset == (xmlDtdPtr) cur) - doc->extSubset = NULL; - } - if (cur->parent != NULL) { - xmlNodePtr parent; - parent = cur->parent; - if (cur->type == XML_ATTRIBUTE_NODE) { - if (parent->properties == (xmlAttrPtr) cur) - parent->properties = ((xmlAttrPtr) cur)->next; - } else { - if (parent->children == cur) - parent->children = cur->next; - if (parent->last == cur) - parent->last = cur->prev; - } - cur->parent = NULL; - } - if (cur->next != NULL) - cur->next->prev = cur->prev; - if (cur->prev != NULL) - cur->prev->next = cur->next; - cur->next = cur->prev = NULL; -} - -/** - * xmlReplaceNode: - * @old: the old node - * @cur: the node - * - * Unlink the old node from it's current context, prune the new one - * at the same place. If @cur was already inserted in a document it is - * first unlinked from its existing context. - * - * Returns the @old node - */ -xmlNodePtr -xmlReplaceNode(xmlNodePtr old, xmlNodePtr cur) { - if (old == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlReplaceNode : old == NULL\n"); -#endif - return(NULL); - } - if (cur == NULL) { - xmlUnlinkNode(old); - return(old); - } - if (cur == old) { - return(old); - } - if ((old->type==XML_ATTRIBUTE_NODE) && (cur->type!=XML_ATTRIBUTE_NODE)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlReplaceNode : Trying to replace attribute node with other node type\n"); -#endif - return(old); - } - if ((cur->type==XML_ATTRIBUTE_NODE) && (old->type!=XML_ATTRIBUTE_NODE)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlReplaceNode : Trying to replace a non-attribute node with attribute node\n"); -#endif - return(old); - } - if ((old->type==XML_ATTRIBUTE_NODE) && (cur->type!=XML_ATTRIBUTE_NODE)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlReplaceNode : Trying to replace attribute node with other node type\n"); -#endif - return(old); - } - if ((cur->type==XML_ATTRIBUTE_NODE) && (old->type!=XML_ATTRIBUTE_NODE)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlReplaceNode : Trying to replace a non-attribute node with attribute node\n"); -#endif - return(old); - } - xmlUnlinkNode(cur); - cur->doc = old->doc; - cur->parent = old->parent; - cur->next = old->next; - if (cur->next != NULL) - cur->next->prev = cur; - cur->prev = old->prev; - if (cur->prev != NULL) - cur->prev->next = cur; - if (cur->parent != NULL) { - if (cur->type == XML_ATTRIBUTE_NODE) { - if (cur->parent->properties == (xmlAttrPtr)old) - cur->parent->properties = ((xmlAttrPtr) cur); - } else { - if (cur->parent->children == old) - cur->parent->children = cur; - if (cur->parent->last == old) - cur->parent->last = cur; - } - } - old->next = old->prev = NULL; - old->parent = NULL; - return(old); -} - -/************************************************************************ - * * - * Copy operations * - * * - ************************************************************************/ - -/** - * xmlCopyNamespace: - * @cur: the namespace - * - * Do a copy of the namespace. - * - * Returns: a new #xmlNsPtr, or NULL in case of error. - */ -xmlNsPtr -xmlCopyNamespace(xmlNsPtr cur) { - xmlNsPtr ret; - - if (cur == NULL) return(NULL); - switch (cur->type) { - case XML_LOCAL_NAMESPACE: - ret = xmlNewNs(NULL, cur->href, cur->prefix); - break; - default: -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlCopyNamespace: invalid type %d\n", cur->type); -#endif - return(NULL); - } - return(ret); -} - -/** - * xmlCopyNamespaceList: - * @cur: the first namespace - * - * Do a copy of an namespace list. - * - * Returns: a new #xmlNsPtr, or NULL in case of error. - */ -xmlNsPtr -xmlCopyNamespaceList(xmlNsPtr cur) { - xmlNsPtr ret = NULL; - xmlNsPtr p = NULL,q; - - while (cur != NULL) { - q = xmlCopyNamespace(cur); - if (p == NULL) { - ret = p = q; - } else { - p->next = q; - p = q; - } - cur = cur->next; - } - return(ret); -} - -static xmlNodePtr -xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent); -/** - * xmlCopyProp: - * @target: the element where the attribute will be grafted - * @cur: the attribute - * - * Do a copy of the attribute. - * - * Returns: a new #xmlAttrPtr, or NULL in case of error. - */ -xmlAttrPtr -xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) { - xmlAttrPtr ret; - - if (cur == NULL) return(NULL); - if (target != NULL) - ret = xmlNewDocProp(target->doc, cur->name, NULL); - else if (cur->parent != NULL) - ret = xmlNewDocProp(cur->parent->doc, cur->name, NULL); - else if (cur->children != NULL) - ret = xmlNewDocProp(cur->children->doc, cur->name, NULL); - else - ret = xmlNewDocProp(NULL, cur->name, NULL); - if (ret == NULL) return(NULL); - ret->parent = target; - - if ((cur->ns != NULL) && (target != NULL)) { - xmlNsPtr ns; -/* - * if (target->doc) - * ns = xmlSearchNs(target->doc, target, cur->ns->prefix); - * else if (cur->doc) / * target may not yet have a doc : KPI * / - * ns = xmlSearchNs(cur->doc, target, cur->ns->prefix); - * else - * ns = NULL; - * ret->ns = ns; - */ - ns = xmlSearchNs(target->doc, target, cur->ns->prefix); - if (ns == NULL) { - /* - * Humm, we are copying an element whose namespace is defined - * out of the new tree scope. Search it in the original tree - * and add it at the top of the new tree - */ - ns = xmlSearchNs(cur->doc, cur->parent, cur->ns->prefix); - if (ns != NULL) { - xmlNodePtr root = target; - xmlNodePtr pred = NULL; - - while (root->parent != NULL) { - pred = root; - root = root->parent; - } - if (root == (xmlNodePtr) target->doc) { - /* correct possibly cycling above the document elt */ - root = pred; - } - ret->ns = xmlNewNs(root, ns->href, ns->prefix); - } - } else { - /* - * we have to find something appropriate here since - * we cant be sure, that the namespce we found is identified - * by the prefix - */ - if (xmlStrEqual(ns->href, cur->ns->href)) { - /* this is the nice case */ - ret->ns = ns; - } else { - /* - * we are in trouble: we need a new reconcilied namespace. - * This is expensive - */ - ret->ns = xmlNewReconciliedNs(target->doc, target, cur->ns); - } - } - - } else - ret->ns = NULL; - - if (cur->children != NULL) { - xmlNodePtr tmp; - - ret->children = xmlStaticCopyNodeList(cur->children, ret->doc, (xmlNodePtr) ret); - ret->last = NULL; - tmp = ret->children; - while (tmp != NULL) { - /* tmp->parent = (xmlNodePtr)ret; */ - if (tmp->next == NULL) - ret->last = tmp; - tmp = tmp->next; - } - } - /* - * Try to handle IDs - */ - if ((target!= NULL) && (cur!= NULL) && - (target->doc != NULL) && (cur->doc != NULL) && - (cur->doc->ids != NULL) && (cur->parent != NULL)) { - if (xmlIsID(cur->doc, cur->parent, cur)) { - xmlChar *id; - - id = xmlNodeListGetString(cur->doc, cur->children, 1); - if (id != NULL) { - xmlAddID(NULL, target->doc, id, ret); - xmlFree(id); - } - } - } - return(ret); -} - -/** - * xmlCopyPropList: - * @target: the element where the attributes will be grafted - * @cur: the first attribute - * - * Do a copy of an attribute list. - * - * Returns: a new #xmlAttrPtr, or NULL in case of error. - */ -xmlAttrPtr -xmlCopyPropList(xmlNodePtr target, xmlAttrPtr cur) { - xmlAttrPtr ret = NULL; - xmlAttrPtr p = NULL,q; - - while (cur != NULL) { - q = xmlCopyProp(target, cur); - if (p == NULL) { - ret = p = q; - } else { - p->next = q; - q->prev = p; - p = q; - } - cur = cur->next; - } - return(ret); -} - -/* - * NOTE about the CopyNode operations ! - * - * They are split into external and internal parts for one - * tricky reason: namespaces. Doing a direct copy of a node - * say RPM:Copyright without changing the namespace pointer to - * something else can produce stale links. One way to do it is - * to keep a reference counter but this doesn't work as soon - * as one move the element or the subtree out of the scope of - * the existing namespace. The actual solution seems to add - * a copy of the namespace at the top of the copied tree if - * not available in the subtree. - * Hence two functions, the public front-end call the inner ones - */ - -static xmlNodePtr -xmlStaticCopyNode(const xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent, - int recursive) { - xmlNodePtr ret; - - if (node == NULL) return(NULL); - switch (node->type) { - case XML_TEXT_NODE: - case XML_CDATA_SECTION_NODE: - case XML_ELEMENT_NODE: - case XML_DOCUMENT_FRAG_NODE: - case XML_ENTITY_REF_NODE: - case XML_ENTITY_NODE: - case XML_PI_NODE: - case XML_COMMENT_NODE: - case XML_XINCLUDE_START: - case XML_XINCLUDE_END: - break; - case XML_ATTRIBUTE_NODE: - return((xmlNodePtr) xmlCopyProp(parent, (xmlAttrPtr) node)); - case XML_NAMESPACE_DECL: - return((xmlNodePtr) xmlCopyNamespaceList((xmlNsPtr) node)); - - case XML_DOCUMENT_NODE: - case XML_HTML_DOCUMENT_NODE: -#ifdef LIBXML_DOCB_ENABLED - case XML_DOCB_DOCUMENT_NODE: -#endif - return((xmlNodePtr) xmlCopyDoc((xmlDocPtr) node, recursive)); - case XML_DOCUMENT_TYPE_NODE: - case XML_NOTATION_NODE: - case XML_DTD_NODE: - case XML_ELEMENT_DECL: - case XML_ATTRIBUTE_DECL: - case XML_ENTITY_DECL: - return(NULL); - } - - /* - * Allocate a new node and fill the fields. - */ - ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); - if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlStaticCopyNode : malloc failed\n"); - return(NULL); - } - memset(ret, 0, sizeof(xmlNode)); - ret->type = node->type; - - ret->doc = doc; - ret->parent = parent; - if (node->name == xmlStringText) - ret->name = xmlStringText; - else if (node->name == xmlStringTextNoenc) - ret->name = xmlStringTextNoenc; - else if (node->name == xmlStringComment) - ret->name = xmlStringComment; - else if (node->name != NULL) - ret->name = xmlStrdup(node->name); - if ((node->type != XML_ELEMENT_NODE) && - (node->content != NULL) && - (node->type != XML_ENTITY_REF_NODE) && - (node->type != XML_XINCLUDE_END) && - (node->type != XML_XINCLUDE_START)) { - ret->content = xmlStrdup(node->content); - }else{ - if (node->type == XML_ELEMENT_NODE) - ret->content = (void*)(long) node->content; - } - if (parent != NULL) { - xmlNodePtr tmp; - - tmp = xmlAddChild(parent, ret); - /* node could have coalesced */ - if (tmp != ret) - return(tmp); - } - - if (!recursive) return(ret); - if (node->nsDef != NULL) - ret->nsDef = xmlCopyNamespaceList(node->nsDef); - - if (node->ns != NULL) { - xmlNsPtr ns; - - ns = xmlSearchNs(doc, ret, node->ns->prefix); - if (ns == NULL) { - /* - * Humm, we are copying an element whose namespace is defined - * out of the new tree scope. Search it in the original tree - * and add it at the top of the new tree - */ - ns = xmlSearchNs(node->doc, node, node->ns->prefix); - if (ns != NULL) { - xmlNodePtr root = ret; - - while (root->parent != NULL) root = root->parent; - ret->ns = xmlNewNs(root, ns->href, ns->prefix); - } - } else { - /* - * reference the existing namespace definition in our own tree. - */ - ret->ns = ns; - } - } - if (node->properties != NULL) - ret->properties = xmlCopyPropList(ret, node->properties); - if (node->type == XML_ENTITY_REF_NODE) { - if ((doc == NULL) || (node->doc != doc)) { - /* - * The copied node will go into a separate document, so - * to avoid dangling references to the ENTITY_DECL node - * we cannot keep the reference. Try to find it in the - * target document. - */ - ret->children = (xmlNodePtr) xmlGetDocEntity(doc, ret->name); - } else { - ret->children = node->children; - } - ret->last = ret->children; - } else if (node->children != NULL) { - ret->children = xmlStaticCopyNodeList(node->children, doc, ret); - UPDATE_LAST_CHILD_AND_PARENT(ret) - } - return(ret); -} - -static xmlNodePtr -xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) { - xmlNodePtr ret = NULL; - xmlNodePtr p = NULL,q; - - while (node != NULL) { - if (node->type == XML_DTD_NODE ) { - if (doc == NULL) { - node = node->next; - continue; - } - if (doc->intSubset == NULL) { - q = (xmlNodePtr) xmlCopyDtd( (xmlDtdPtr) node ); - q->doc = doc; - q->parent = parent; - doc->intSubset = (xmlDtdPtr) q; - xmlAddChild(parent, q); - } else { - q = (xmlNodePtr) doc->intSubset; - xmlAddChild(parent, q); - } - } else - q = xmlStaticCopyNode(node, doc, parent, 1); - if (ret == NULL) { - q->prev = NULL; - ret = p = q; - } else if (p != q) { - /* the test is required if xmlStaticCopyNode coalesced 2 text nodes */ - p->next = q; - q->prev = p; - p = q; - } - node = node->next; - } - return(ret); -} - -/** - * xmlCopyNode: - * @node: the node - * @recursive: if 1 do a recursive copy. - * - * Do a copy of the node. - * - * Returns: a new #xmlNodePtr, or NULL in case of error. - */ -xmlNodePtr -xmlCopyNode(const xmlNodePtr node, int recursive) { - xmlNodePtr ret; - - ret = xmlStaticCopyNode(node, NULL, NULL, recursive); - return(ret); -} - -/** - * xmlDocCopyNode: - * @node: the node - * @doc: the document - * @recursive: if 1 do a recursive copy. - * - * Do a copy of the node to a given document. - * - * Returns: a new #xmlNodePtr, or NULL in case of error. - */ -xmlNodePtr -xmlDocCopyNode(const xmlNodePtr node, xmlDocPtr doc, int recursive) { - xmlNodePtr ret; - - ret = xmlStaticCopyNode(node, doc, NULL, recursive); - return(ret); -} - -/** - * xmlCopyNodeList: - * @node: the first node in the list. - * - * Do a recursive copy of the node list. - * - * Returns: a new #xmlNodePtr, or NULL in case of error. - */ -xmlNodePtr xmlCopyNodeList(const xmlNodePtr node) { - xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL); - return(ret); -} - -/** - * xmlCopyDtd: - * @dtd: the dtd - * - * Do a copy of the dtd. - * - * Returns: a new #xmlDtdPtr, or NULL in case of error. - */ -xmlDtdPtr -xmlCopyDtd(xmlDtdPtr dtd) { - xmlDtdPtr ret; - xmlNodePtr cur, p = NULL, q; - - if (dtd == NULL) return(NULL); - ret = xmlNewDtd(NULL, dtd->name, dtd->ExternalID, dtd->SystemID); - if (ret == NULL) return(NULL); - if (dtd->entities != NULL) - ret->entities = (void *) xmlCopyEntitiesTable( - (xmlEntitiesTablePtr) dtd->entities); - if (dtd->notations != NULL) - ret->notations = (void *) xmlCopyNotationTable( - (xmlNotationTablePtr) dtd->notations); - if (dtd->elements != NULL) - ret->elements = (void *) xmlCopyElementTable( - (xmlElementTablePtr) dtd->elements); - if (dtd->attributes != NULL) - ret->attributes = (void *) xmlCopyAttributeTable( - (xmlAttributeTablePtr) dtd->attributes); - if (dtd->pentities != NULL) - ret->pentities = (void *) xmlCopyEntitiesTable( - (xmlEntitiesTablePtr) dtd->pentities); - - cur = dtd->children; - while (cur != NULL) { - q = NULL; - - if (cur->type == XML_ENTITY_DECL) { - xmlEntityPtr tmp = (xmlEntityPtr) cur; - switch (tmp->etype) { - case XML_INTERNAL_GENERAL_ENTITY: - case XML_EXTERNAL_GENERAL_PARSED_ENTITY: - case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY: - q = (xmlNodePtr) xmlGetEntityFromDtd(ret, tmp->name); - break; - case XML_INTERNAL_PARAMETER_ENTITY: - case XML_EXTERNAL_PARAMETER_ENTITY: - q = (xmlNodePtr) - xmlGetParameterEntityFromDtd(ret, tmp->name); - break; - case XML_INTERNAL_PREDEFINED_ENTITY: - break; - } - } else if (cur->type == XML_ELEMENT_DECL) { - xmlElementPtr tmp = (xmlElementPtr) cur; - q = (xmlNodePtr) - xmlGetDtdQElementDesc(ret, tmp->name, tmp->prefix); - } else if (cur->type == XML_ATTRIBUTE_DECL) { - xmlAttributePtr tmp = (xmlAttributePtr) cur; - q = (xmlNodePtr) - xmlGetDtdQAttrDesc(ret, tmp->elem, tmp->name, tmp->prefix); - } else if (cur->type == XML_COMMENT_NODE) { - q = xmlCopyNode(cur, 0); - } - - if (q == NULL) { - cur = cur->next; - continue; - } - - if (p == NULL) - ret->children = q; - else - p->next = q; - - q->prev = p; - q->parent = (xmlNodePtr) ret; - q->next = NULL; - ret->last = q; - p = q; - cur = cur->next; - } - - return(ret); -} - -/** - * xmlCopyDoc: - * @doc: the document - * @recursive: if 1 do a recursive copy. - * - * Do a copy of the document info. If recursive, the content tree will - * be copied too as well as DTD, namespaces and entities. - * - * Returns: a new #xmlDocPtr, or NULL in case of error. - */ -xmlDocPtr -xmlCopyDoc(xmlDocPtr doc, int recursive) { - xmlDocPtr ret; - - if (doc == NULL) return(NULL); - ret = xmlNewDoc(doc->version); - if (ret == NULL) return(NULL); - if (doc->name != NULL) - ret->name = xmlMemStrdup(doc->name); - if (doc->encoding != NULL) - ret->encoding = xmlStrdup(doc->encoding); - ret->charset = doc->charset; - ret->compression = doc->compression; - ret->standalone = doc->standalone; - if (!recursive) return(ret); - - ret->last = NULL; - ret->children = NULL; - if (doc->intSubset != NULL) { - ret->intSubset = xmlCopyDtd(doc->intSubset); - xmlSetTreeDoc((xmlNodePtr)ret->intSubset, ret); - ret->intSubset->parent = ret; - } - if (doc->oldNs != NULL) - ret->oldNs = xmlCopyNamespaceList(doc->oldNs); - if (doc->children != NULL) { - xmlNodePtr tmp; - - ret->children = xmlStaticCopyNodeList(doc->children, ret, - (xmlNodePtr)ret); - ret->last = NULL; - tmp = ret->children; - while (tmp != NULL) { - if (tmp->next == NULL) - ret->last = tmp; - tmp = tmp->next; - } - } - return(ret); -} - -/************************************************************************ - * * - * Content access functions * - * * - ************************************************************************/ - -/** - * xmlGetLineNo: - * @node: valid node - * - * Get line number of node. this requires activation of this option - * before invoking the parser by calling xmlLineNumbersDefault(1) - * - * Returns the line number if successful, -1 otherwise - */ -long -xmlGetLineNo(xmlNodePtr node) -{ - long result = -1; - - if (!node) - return result; - if (node->type == XML_ELEMENT_NODE) - result = (long) node->content; - else if ((node->prev != NULL) && - ((node->prev->type == XML_ELEMENT_NODE) || - (node->prev->type == XML_TEXT_NODE))) - result = xmlGetLineNo(node->prev); - else if ((node->parent != NULL) && - ((node->parent->type == XML_ELEMENT_NODE) || - (node->parent->type == XML_TEXT_NODE))) - result = xmlGetLineNo(node->parent); - - return result; -} - -/** - * xmlGetNodePath: - * @node: a node - * - * Build a structure based Path for the given node - * - * Returns the new path or NULL in case of error. The caller must free - * the returned string - */ -xmlChar * -xmlGetNodePath(xmlNodePtr node) -{ - xmlNodePtr cur, tmp, next; - xmlChar *buffer = NULL, *temp; - size_t buf_len; - xmlChar *buf; - const char *sep; - const char *name; - char nametemp[100]; - int occur = 0; - - if (node == NULL) - return (NULL); - - buf_len = 500; - buffer = (xmlChar *) xmlMalloc(buf_len * sizeof(xmlChar)); - if (buffer == NULL) - return (NULL); - buf = (xmlChar *) xmlMalloc(buf_len * sizeof(xmlChar)); - if (buf == NULL) { - xmlFree(buffer); - return (NULL); - } - - buffer[0] = 0; - cur = node; - do { - name = ""; - sep = "?"; - occur = 0; - if ((cur->type == XML_DOCUMENT_NODE) || - (cur->type == XML_HTML_DOCUMENT_NODE)) { - if (buffer[0] == '/') - break; - sep = "/"; - next = NULL; - } else if (cur->type == XML_ELEMENT_NODE) { - sep = "/"; - name = (const char *) cur->name; - if (cur->ns) { - snprintf(nametemp, sizeof(nametemp) - 1, - "%s:%s", cur->ns->prefix, cur->name); - nametemp[sizeof(nametemp) - 1] = 0; - name = nametemp; - } - next = cur->parent; - - /* - * Thumbler index computation - */ - tmp = cur->prev; - while (tmp != NULL) { - if ((tmp->type == XML_ELEMENT_NODE) && - (xmlStrEqual(cur->name, tmp->name))) - occur++; - tmp = tmp->prev; - } - if (occur == 0) { - tmp = cur->next; - while (tmp != NULL && occur == 0) { - if ((tmp->type == XML_ELEMENT_NODE) && - (xmlStrEqual(cur->name, tmp->name))) - occur++; - tmp = tmp->next; - } - if (occur != 0) - occur = 1; - } else - occur++; - } else if (cur->type == XML_COMMENT_NODE) { - sep = "/"; - name = "comment()"; - next = cur->parent; - - /* - * Thumbler index computation - */ - tmp = cur->prev; - while (tmp != NULL) { - if (tmp->type == XML_COMMENT_NODE) - occur++; - tmp = tmp->prev; - } - if (occur == 0) { - tmp = cur->next; - while (tmp != NULL && occur == 0) { - if (tmp->type == XML_COMMENT_NODE) - occur++; - tmp = tmp->next; - } - if (occur != 0) - occur = 1; - } else - occur++; - } else if ((cur->type == XML_TEXT_NODE) || - (cur->type == XML_CDATA_SECTION_NODE)) { - sep = "/"; - name = "text()"; - next = cur->parent; - - /* - * Thumbler index computation - */ - tmp = cur->prev; - while (tmp != NULL) { - if ((cur->type == XML_TEXT_NODE) || - (cur->type == XML_CDATA_SECTION_NODE)) - occur++; - tmp = tmp->prev; - } - if (occur == 0) { - tmp = cur->next; - while (tmp != NULL && occur == 0) { - if ((cur->type == XML_TEXT_NODE) || - (cur->type == XML_CDATA_SECTION_NODE)) - occur++; - tmp = tmp->next; - } - if (occur != 0) - occur = 1; - } else - occur++; - } else if (cur->type == XML_PI_NODE) { - sep = "/"; - snprintf(nametemp, sizeof(nametemp) - 1, - "processing-instruction('%s')", cur->name); - nametemp[sizeof(nametemp) - 1] = 0; - name = nametemp; - - next = cur->parent; - - /* - * Thumbler index computation - */ - tmp = cur->prev; - while (tmp != NULL) { - if ((tmp->type == XML_PI_NODE) && - (xmlStrEqual(cur->name, tmp->name))) - occur++; - tmp = tmp->prev; - } - if (occur == 0) { - tmp = cur->next; - while (tmp != NULL && occur == 0) { - if ((tmp->type == XML_PI_NODE) && - (xmlStrEqual(cur->name, tmp->name))) - occur++; - tmp = tmp->next; - } - if (occur != 0) - occur = 1; - } else - occur++; - - } else if (cur->type == XML_ATTRIBUTE_NODE) { - sep = "/@"; - name = (const char *) (((xmlAttrPtr) cur)->name); - next = ((xmlAttrPtr) cur)->parent; - } else { - next = cur->parent; - } - - /* - * Make sure there is enough room - */ - if (xmlStrlen(buffer) + sizeof(nametemp) + 20 > buf_len) { - buf_len = - 2 * buf_len + xmlStrlen(buffer) + sizeof(nametemp) + 20; - temp = (xmlChar *) xmlRealloc(buffer, buf_len); - if (temp == NULL) { - xmlFree(buf); - xmlFree(buffer); - return (NULL); - } - buffer = temp; - temp = (xmlChar *) xmlRealloc(buf, buf_len); - if (temp == NULL) { - xmlFree(buf); - xmlFree(buffer); - return (NULL); - } - buf = temp; - } - if (occur == 0) - snprintf((char *) buf, buf_len, "%s%s%s", - sep, name, (char *) buffer); - else - snprintf((char *) buf, buf_len, "%s%s[%d]%s", - sep, name, occur, (char *) buffer); - snprintf((char *) buffer, buf_len, "%s", buf); - cur = next; - } while (cur != NULL); - xmlFree(buf); - return (buffer); -} - -/** - * xmlDocGetRootElement: - * @doc: the document - * - * Get the root element of the document (doc->children is a list - * containing possibly comments, PIs, etc ...). - * - * Returns the #xmlNodePtr for the root or NULL - */ -xmlNodePtr -xmlDocGetRootElement(xmlDocPtr doc) { - xmlNodePtr ret; - - if (doc == NULL) return(NULL); - ret = doc->children; - while (ret != NULL) { - if (ret->type == XML_ELEMENT_NODE) - return(ret); - ret = ret->next; - } - return(ret); -} - -/** - * xmlDocSetRootElement: - * @doc: the document - * @root: the new document root element - * - * Set the root element of the document (doc->children is a list - * containing possibly comments, PIs, etc ...). - * - * Returns the old root element if any was found - */ -xmlNodePtr -xmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) { - xmlNodePtr old = NULL; - - if (doc == NULL) return(NULL); - if (root == NULL) - return(NULL); - xmlUnlinkNode(root); - root->doc = doc; - root->parent = (xmlNodePtr) doc; - old = doc->children; - while (old != NULL) { - if (old->type == XML_ELEMENT_NODE) - break; - old = old->next; - } - if (old == NULL) { - if (doc->children == NULL) { - doc->children = root; - doc->last = root; - } else { - xmlAddSibling(doc->children, root); - } - } else { - xmlReplaceNode(old, root); - } - return(old); -} - -/** - * xmlNodeSetLang: - * @cur: the node being changed - * @lang: the language description - * - * Set the language of a node, i.e. the values of the xml:lang - * attribute. - */ -void -xmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) { - xmlNsPtr ns; - - if (cur == NULL) return; - switch(cur->type) { - case XML_TEXT_NODE: - case XML_CDATA_SECTION_NODE: - case XML_COMMENT_NODE: - case XML_DOCUMENT_NODE: - case XML_DOCUMENT_TYPE_NODE: - case XML_DOCUMENT_FRAG_NODE: - case XML_NOTATION_NODE: - case XML_HTML_DOCUMENT_NODE: - case XML_DTD_NODE: - case XML_ELEMENT_DECL: - case XML_ATTRIBUTE_DECL: - case XML_ENTITY_DECL: - case XML_PI_NODE: - case XML_ENTITY_REF_NODE: - case XML_ENTITY_NODE: - case XML_NAMESPACE_DECL: -#ifdef LIBXML_DOCB_ENABLED - case XML_DOCB_DOCUMENT_NODE: -#endif - case XML_XINCLUDE_START: - case XML_XINCLUDE_END: - return; - case XML_ELEMENT_NODE: - case XML_ATTRIBUTE_NODE: - break; - } - ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE); - if (ns == NULL) - return; - xmlSetNsProp(cur, ns, BAD_CAST "lang", lang); -} - -/** - * xmlNodeGetLang: - * @cur: the node being checked - * - * Searches the language of a node, i.e. the values of the xml:lang - * attribute or the one carried by the nearest ancestor. - * - * Returns a pointer to the lang value, or NULL if not found - * It's up to the caller to free the memory with xmlFree(). - */ -xmlChar * -xmlNodeGetLang(xmlNodePtr cur) { - xmlChar *lang; - - while (cur != NULL) { - lang = xmlGetNsProp(cur, BAD_CAST "lang", XML_XML_NAMESPACE); - if (lang != NULL) - return(lang); - cur = cur->parent; - } - return(NULL); -} - - -/** - * xmlNodeSetSpacePreserve: - * @cur: the node being changed - * @val: the xml:space value ("0": default, 1: "preserve") - * - * Set (or reset) the space preserving behaviour of a node, i.e. the - * value of the xml:space attribute. - */ -void -xmlNodeSetSpacePreserve(xmlNodePtr cur, int val) { - xmlNsPtr ns; - - if (cur == NULL) return; - switch(cur->type) { - case XML_TEXT_NODE: - case XML_CDATA_SECTION_NODE: - case XML_COMMENT_NODE: - case XML_DOCUMENT_NODE: - case XML_DOCUMENT_TYPE_NODE: - case XML_DOCUMENT_FRAG_NODE: - case XML_NOTATION_NODE: - case XML_HTML_DOCUMENT_NODE: - case XML_DTD_NODE: - case XML_ELEMENT_DECL: - case XML_ATTRIBUTE_DECL: - case XML_ENTITY_DECL: - case XML_PI_NODE: - case XML_ENTITY_REF_NODE: - case XML_ENTITY_NODE: - case XML_NAMESPACE_DECL: - case XML_XINCLUDE_START: - case XML_XINCLUDE_END: -#ifdef LIBXML_DOCB_ENABLED - case XML_DOCB_DOCUMENT_NODE: -#endif - return; - case XML_ELEMENT_NODE: - case XML_ATTRIBUTE_NODE: - break; - } - ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE); - if (ns == NULL) - return; - switch (val) { - case 0: - xmlSetNsProp(cur, ns, BAD_CAST "space", BAD_CAST "default"); - break; - case 1: - xmlSetNsProp(cur, ns, BAD_CAST "space", BAD_CAST "preserve"); - break; - } -} - -/** - * xmlNodeGetSpacePreserve: - * @cur: the node being checked - * - * Searches the space preserving behaviour of a node, i.e. the values - * of the xml:space attribute or the one carried by the nearest - * ancestor. - * - * Returns -1 if xml:space is not inherited, 0 if "default", 1 if "preserve" - */ -int -xmlNodeGetSpacePreserve(xmlNodePtr cur) { - xmlChar *space; - - while (cur != NULL) { - space = xmlGetNsProp(cur, BAD_CAST "space", XML_XML_NAMESPACE); - if (space != NULL) { - if (xmlStrEqual(space, BAD_CAST "preserve")) { - xmlFree(space); - return(1); - } - if (xmlStrEqual(space, BAD_CAST "default")) { - xmlFree(space); - return(0); - } - xmlFree(space); - } - cur = cur->parent; - } - return(-1); -} - -/** - * xmlNodeSetName: - * @cur: the node being changed - * @name: the new tag name - * - * Set (or reset) the name of a node. - */ -void -xmlNodeSetName(xmlNodePtr cur, const xmlChar *name) { - if (cur == NULL) return; - if (name == NULL) return; - switch(cur->type) { - case XML_TEXT_NODE: - case XML_CDATA_SECTION_NODE: - case XML_COMMENT_NODE: - case XML_DOCUMENT_TYPE_NODE: - case XML_DOCUMENT_FRAG_NODE: - case XML_NOTATION_NODE: - case XML_HTML_DOCUMENT_NODE: - case XML_NAMESPACE_DECL: - case XML_XINCLUDE_START: - case XML_XINCLUDE_END: -#ifdef LIBXML_DOCB_ENABLED - case XML_DOCB_DOCUMENT_NODE: -#endif - return; - case XML_ELEMENT_NODE: - case XML_ATTRIBUTE_NODE: - case XML_PI_NODE: - case XML_ENTITY_REF_NODE: - case XML_ENTITY_NODE: - case XML_DTD_NODE: - case XML_DOCUMENT_NODE: - case XML_ELEMENT_DECL: - case XML_ATTRIBUTE_DECL: - case XML_ENTITY_DECL: - break; - } - if (cur->name != NULL) xmlFree((xmlChar *) cur->name); - cur->name = xmlStrdup(name); -} - -/** - * xmlNodeSetBase: - * @cur: the node being changed - * @uri: the new base URI - * - * Set (or reset) the base URI of a node, i.e. the value of the - * xml:base attribute. - */ -void -xmlNodeSetBase(xmlNodePtr cur, xmlChar* uri) { - xmlNsPtr ns; - - if (cur == NULL) return; - switch(cur->type) { - case XML_TEXT_NODE: - case XML_CDATA_SECTION_NODE: - case XML_COMMENT_NODE: - case XML_DOCUMENT_TYPE_NODE: - case XML_DOCUMENT_FRAG_NODE: - case XML_NOTATION_NODE: - case XML_DTD_NODE: - case XML_ELEMENT_DECL: - case XML_ATTRIBUTE_DECL: - case XML_ENTITY_DECL: - case XML_PI_NODE: - case XML_ENTITY_REF_NODE: - case XML_ENTITY_NODE: - case XML_NAMESPACE_DECL: - case XML_XINCLUDE_START: - case XML_XINCLUDE_END: - return; - case XML_ELEMENT_NODE: - case XML_ATTRIBUTE_NODE: - break; - case XML_DOCUMENT_NODE: -#ifdef LIBXML_DOCB_ENABLED - case XML_DOCB_DOCUMENT_NODE: -#endif - case XML_HTML_DOCUMENT_NODE: { - xmlDocPtr doc = (xmlDocPtr) cur; - - if (doc->URL != NULL) - xmlFree((xmlChar *) doc->URL); - if (uri == NULL) - doc->URL = NULL; - else - doc->URL = xmlStrdup(uri); - return; - } - } - - ns = xmlSearchNsByHref(cur->doc, cur, XML_XML_NAMESPACE); - if (ns == NULL) - return; - xmlSetNsProp(cur, ns, BAD_CAST "base", uri); -} - -/** - * xmlNodeGetBase: - * @doc: the document the node pertains to - * @cur: the node being checked - * - * Searches for the BASE URL. The code should work on both XML - * and HTML document even if base mechanisms are completely different. - * It returns the base as defined in RFC 2396 sections - * 5.1.1. Base URI within Document Content - * and - * 5.1.2. Base URI from the Encapsulating Entity - * However it does not return the document base (5.1.3), use - * xmlDocumentGetBase() for this - * - * Returns a pointer to the base URL, or NULL if not found - * It's up to the caller to free the memory with xmlFree(). - */ -xmlChar * -xmlNodeGetBase(xmlDocPtr doc, xmlNodePtr cur) { - xmlChar *oldbase = NULL; - xmlChar *base, *newbase; - - if ((cur == NULL) && (doc == NULL)) - return(NULL); - if (doc == NULL) doc = cur->doc; - if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) { - cur = doc->children; - while ((cur != NULL) && (cur->name != NULL)) { - if (cur->type != XML_ELEMENT_NODE) { - cur = cur->next; - continue; - } - if (!xmlStrcasecmp(cur->name, BAD_CAST "html")) { - cur = cur->children; - continue; - } - if (!xmlStrcasecmp(cur->name, BAD_CAST "head")) { - cur = cur->children; - continue; - } - if (!xmlStrcasecmp(cur->name, BAD_CAST "base")) { - return(xmlGetProp(cur, BAD_CAST "href")); - } - cur = cur->next; - } - return(NULL); - } - while (cur != NULL) { - if (cur->type == XML_ENTITY_DECL) { - xmlEntityPtr ent = (xmlEntityPtr) cur; - return(xmlStrdup(ent->URI)); - } - if (cur->type == XML_ELEMENT_NODE) { - base = xmlGetNsProp(cur, BAD_CAST "base", XML_XML_NAMESPACE); - if (base != NULL) { - if (oldbase != NULL) { - newbase = xmlBuildURI(oldbase, base); - if (newbase != NULL) { - xmlFree(oldbase); - xmlFree(base); - oldbase = newbase; - } else { - xmlFree(oldbase); - xmlFree(base); - return(NULL); - } - } else { - oldbase = base; - } - if ((!xmlStrncmp(oldbase, BAD_CAST "http://", 7)) || - (!xmlStrncmp(oldbase, BAD_CAST "ftp://", 6)) || - (!xmlStrncmp(oldbase, BAD_CAST "urn:", 4))) - return(oldbase); - } - } - cur = cur->parent; - } - if ((doc != NULL) && (doc->URL != NULL)) { - if (oldbase == NULL) - return(xmlStrdup(doc->URL)); - newbase = xmlBuildURI(oldbase, doc->URL); - xmlFree(oldbase); - return(newbase); - } - return(oldbase); -} - -/** - * xmlNodeGetContent: - * @cur: the node being read - * - * Read the value of a node, this can be either the text carried - * directly by this node if it's a TEXT node or the aggregate string - * of the values carried by this node child's (TEXT and ENTITY_REF). - * Entity references are substituted. - * Returns a new #xmlChar * or NULL if no content is available. - * It's up to the caller to free the memory with xmlFree(). - */ -xmlChar * -xmlNodeGetContent(xmlNodePtr cur) -{ - if (cur == NULL) - return (NULL); - switch (cur->type) { - case XML_DOCUMENT_FRAG_NODE: - case XML_ELEMENT_NODE:{ - xmlNodePtr tmp = cur; - xmlBufferPtr buffer; - xmlChar *ret; - - buffer = xmlBufferCreate(); - if (buffer == NULL) - return (NULL); - while (tmp != NULL) { - switch (tmp->type) { - case XML_CDATA_SECTION_NODE: - case XML_TEXT_NODE: - if (tmp->content != NULL) - xmlBufferCat(buffer, tmp->content); - break; - case XML_ENTITY_REF_NODE:{ - /* recursive substitution of entity references */ - xmlChar *cont = xmlNodeGetContent(tmp); - - if (cont) { - xmlBufferCat(buffer, - (const xmlChar *) cont); - xmlFree(cont); - } - break; - } - default: - break; - } - /* - * Skip to next node - */ - if (tmp->children != NULL) { - if (tmp->children->type != XML_ENTITY_DECL) { - tmp = tmp->children; - continue; - } - } - if (tmp == cur) - break; - - if (tmp->next != NULL) { - tmp = tmp->next; - continue; - } - - do { - tmp = tmp->parent; - if (tmp == NULL) - break; - if (tmp == cur) { - tmp = NULL; - break; - } - if (tmp->next != NULL) { - tmp = tmp->next; - break; - } - } while (tmp != NULL); - } - ret = buffer->content; - buffer->content = NULL; - xmlBufferFree(buffer); - return (ret); - } - case XML_ATTRIBUTE_NODE:{ - xmlAttrPtr attr = (xmlAttrPtr) cur; - - if (attr->parent != NULL) - return (xmlNodeListGetString - (attr->parent->doc, attr->children, 1)); - else - return (xmlNodeListGetString(NULL, attr->children, 1)); - break; - } - case XML_COMMENT_NODE: - case XML_PI_NODE: - if (cur->content != NULL) - return (xmlStrdup(cur->content)); - return (NULL); - case XML_ENTITY_REF_NODE:{ - xmlEntityPtr ent; - xmlNodePtr tmp; - xmlBufferPtr buffer; - xmlChar *ret; - - /* lookup entity declaration */ - ent = xmlGetDocEntity(cur->doc, cur->name); - if (ent == NULL) - return (NULL); - - buffer = xmlBufferCreate(); - if (buffer == NULL) - return (NULL); - - /* 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 - * -> we iterate through child nodes and recursive call - * xmlNodeGetContent() which handles all possible node types */ - tmp = ent->children; - while (tmp) { - xmlChar *cont = xmlNodeGetContent(tmp); - - if (cont) { - xmlBufferCat(buffer, (const xmlChar *) cont); - xmlFree(cont); - } - tmp = tmp->next; - } - - ret = buffer->content; - buffer->content = NULL; - xmlBufferFree(buffer); - return (ret); - } - case XML_ENTITY_NODE: - case XML_DOCUMENT_NODE: - case XML_HTML_DOCUMENT_NODE: - case XML_DOCUMENT_TYPE_NODE: - case XML_NOTATION_NODE: - case XML_DTD_NODE: - case XML_XINCLUDE_START: - case XML_XINCLUDE_END: -#ifdef LIBXML_DOCB_ENABLED - case XML_DOCB_DOCUMENT_NODE: -#endif - return (NULL); - case XML_NAMESPACE_DECL: { - xmlChar *tmp; - - tmp = xmlStrdup(((xmlNsPtr) cur)->href); - return (tmp); - } - case XML_ELEMENT_DECL: - /* TODO !!! */ - return (NULL); - case XML_ATTRIBUTE_DECL: - /* TODO !!! */ - return (NULL); - case XML_ENTITY_DECL: - /* TODO !!! */ - return (NULL); - case XML_CDATA_SECTION_NODE: - case XML_TEXT_NODE: - if (cur->content != NULL) - return (xmlStrdup(cur->content)); - return (NULL); - } - return (NULL); -} -/** - * xmlNodeSetContent: - * @cur: the node being modified - * @content: the new value of the content - * - * Replace the content of a node. - */ -void -xmlNodeSetContent(xmlNodePtr cur, const xmlChar *content) { - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNodeSetContent : node == NULL\n"); -#endif - return; - } - switch (cur->type) { - case XML_DOCUMENT_FRAG_NODE: - case XML_ELEMENT_NODE: - case XML_ATTRIBUTE_NODE: - if (cur->children != NULL) xmlFreeNodeList(cur->children); - cur->children = xmlStringGetNodeList(cur->doc, content); - UPDATE_LAST_CHILD_AND_PARENT(cur) - break; - case XML_TEXT_NODE: - case XML_CDATA_SECTION_NODE: - case XML_ENTITY_REF_NODE: - case XML_ENTITY_NODE: - case XML_PI_NODE: - case XML_COMMENT_NODE: - if (cur->content != NULL) { - xmlFree(cur->content); - } - if (cur->children != NULL) xmlFreeNodeList(cur->children); - cur->last = cur->children = NULL; - if (content != NULL) { - cur->content = xmlStrdup(content); - } else - cur->content = NULL; - break; - case XML_DOCUMENT_NODE: - case XML_HTML_DOCUMENT_NODE: - case XML_DOCUMENT_TYPE_NODE: - case XML_XINCLUDE_START: - case XML_XINCLUDE_END: -#ifdef LIBXML_DOCB_ENABLED - case XML_DOCB_DOCUMENT_NODE: -#endif - break; - case XML_NOTATION_NODE: - break; - case XML_DTD_NODE: - break; - case XML_NAMESPACE_DECL: - break; - case XML_ELEMENT_DECL: - /* TODO !!! */ - break; - case XML_ATTRIBUTE_DECL: - /* TODO !!! */ - break; - case XML_ENTITY_DECL: - /* TODO !!! */ - break; - } -} - -/** - * xmlNodeSetContentLen: - * @cur: the node being modified - * @content: the new value of the content - * @len: the size of @content - * - * Replace the content of a node. - */ -void -xmlNodeSetContentLen(xmlNodePtr cur, const xmlChar *content, int len) { - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNodeSetContentLen : node == NULL\n"); -#endif - return; - } - switch (cur->type) { - case XML_DOCUMENT_FRAG_NODE: - case XML_ELEMENT_NODE: - case XML_ATTRIBUTE_NODE: - if (cur->children != NULL) xmlFreeNodeList(cur->children); - cur->children = xmlStringLenGetNodeList(cur->doc, content, len); - UPDATE_LAST_CHILD_AND_PARENT(cur) - break; - case XML_TEXT_NODE: - case XML_CDATA_SECTION_NODE: - case XML_ENTITY_REF_NODE: - case XML_ENTITY_NODE: - case XML_PI_NODE: - case XML_COMMENT_NODE: - case XML_NOTATION_NODE: - if (cur->content != NULL) { - xmlFree(cur->content); - } - if (cur->children != NULL) xmlFreeNodeList(cur->children); - cur->children = cur->last = NULL; - if (content != NULL) { - cur->content = xmlStrndup(content, len); - } else - cur->content = NULL; - break; - case XML_DOCUMENT_NODE: - case XML_DTD_NODE: - case XML_HTML_DOCUMENT_NODE: - case XML_DOCUMENT_TYPE_NODE: - case XML_NAMESPACE_DECL: - case XML_XINCLUDE_START: - case XML_XINCLUDE_END: -#ifdef LIBXML_DOCB_ENABLED - case XML_DOCB_DOCUMENT_NODE: -#endif - break; - case XML_ELEMENT_DECL: - /* TODO !!! */ - break; - case XML_ATTRIBUTE_DECL: - /* TODO !!! */ - break; - case XML_ENTITY_DECL: - /* TODO !!! */ - break; - } -} - -/** - * xmlNodeAddContentLen: - * @cur: the node being modified - * @content: extra content - * @len: the size of @content - * - * Append the extra substring to the node content. - */ -void -xmlNodeAddContentLen(xmlNodePtr cur, const xmlChar *content, int len) { - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNodeAddContentLen : node == NULL\n"); -#endif - return; - } - if (len <= 0) return; - switch (cur->type) { - case XML_DOCUMENT_FRAG_NODE: - case XML_ELEMENT_NODE: { - xmlNodePtr last, newNode, tmp; - - last = cur->last; - newNode = xmlNewTextLen(content, len); - if (newNode != NULL) { - tmp = xmlAddChild(cur, newNode); - if (tmp != newNode) - return; - if ((last != NULL) && (last->next == newNode)) { - xmlTextMerge(last, newNode); - } - } - break; - } - case XML_ATTRIBUTE_NODE: - break; - case XML_TEXT_NODE: - case XML_CDATA_SECTION_NODE: - case XML_ENTITY_REF_NODE: - case XML_ENTITY_NODE: - case XML_PI_NODE: - case XML_COMMENT_NODE: - case XML_NOTATION_NODE: - if (content != NULL) { - cur->content = xmlStrncat(cur->content, content, len); - } - case XML_DOCUMENT_NODE: - case XML_DTD_NODE: - case XML_HTML_DOCUMENT_NODE: - case XML_DOCUMENT_TYPE_NODE: - case XML_NAMESPACE_DECL: - case XML_XINCLUDE_START: - case XML_XINCLUDE_END: -#ifdef LIBXML_DOCB_ENABLED - case XML_DOCB_DOCUMENT_NODE: -#endif - break; - case XML_ELEMENT_DECL: - case XML_ATTRIBUTE_DECL: - case XML_ENTITY_DECL: - break; - } -} - -/** - * xmlNodeAddContent: - * @cur: the node being modified - * @content: extra content - * - * Append the extra substring to the node content. - */ -void -xmlNodeAddContent(xmlNodePtr cur, const xmlChar *content) { - int len; - - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNodeAddContent : node == NULL\n"); -#endif - return; - } - if (content == NULL) return; - len = xmlStrlen(content); - xmlNodeAddContentLen(cur, content, len); -} - -/** - * xmlTextMerge: - * @first: the first text node - * @second: the second text node being merged - * - * Merge two text nodes into one - * Returns the first text node augmented - */ -xmlNodePtr -xmlTextMerge(xmlNodePtr first, xmlNodePtr second) { - if (first == NULL) return(second); - if (second == NULL) return(first); - if (first->type != XML_TEXT_NODE) return(first); - if (second->type != XML_TEXT_NODE) return(first); - if (second->name != first->name) - return(first); - xmlNodeAddContent(first, second->content); - xmlUnlinkNode(second); - xmlFreeNode(second); - return(first); -} - -/** - * xmlGetNsList: - * @doc: the document - * @node: the current node - * - * Search all the namespace applying to a given element. - * Returns an NULL terminated array of all the #xmlNsPtr found - * that need to be freed by the caller or NULL if no - * namespace if defined - */ -xmlNsPtr * -xmlGetNsList(xmlDocPtr doc ATTRIBUTE_UNUSED, xmlNodePtr node) -{ - xmlNsPtr cur; - xmlNsPtr *ret = NULL; - int nbns = 0; - int maxns = 10; - int i; - - while (node != NULL) { - if (node->type == XML_ELEMENT_NODE) { - cur = node->nsDef; - while (cur != NULL) { - if (ret == NULL) { - ret = - (xmlNsPtr *) xmlMalloc((maxns + 1) * - sizeof(xmlNsPtr)); - if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlGetNsList : out of memory!\n"); - return (NULL); - } - ret[nbns] = NULL; - } - for (i = 0; i < nbns; i++) { - if ((cur->prefix == ret[i]->prefix) || - (xmlStrEqual(cur->prefix, ret[i]->prefix))) - break; - } - if (i >= nbns) { - if (nbns >= maxns) { - maxns *= 2; - ret = (xmlNsPtr *) xmlRealloc(ret, - (maxns + - 1) * - sizeof(xmlNsPtr)); - if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlGetNsList : realloc failed!\n"); - return (NULL); - } - } - ret[nbns++] = cur; - ret[nbns] = NULL; - } - - cur = cur->next; - } - } - node = node->parent; - } - return (ret); -} - -/** - * xmlSearchNs: - * @doc: the document - * @node: the current node - * @nameSpace: the namespace prefix - * - * Search a Ns registered under a given name space for a document. - * recurse on the parents until it finds the defined namespace - * or return NULL otherwise. - * @nameSpace can be NULL, this is a search for the default namespace. - * We don't allow to cross entities boundaries. If you don't declare - * the namespace within those you will be in troubles !!! A warning - * is generated to cover this case. - * - * Returns the namespace pointer or NULL. - */ -xmlNsPtr -xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace) { - xmlNsPtr cur; - - if (node == NULL) return(NULL); - if ((nameSpace != NULL) && - (xmlStrEqual(nameSpace, (const xmlChar *)"xml"))) { - if ((doc == NULL) && (node->type == XML_ELEMENT_NODE)) { - /* - * The XML-1.0 namespace is normally held on the root - * element. In this case exceptionally create it on the - * node element. - */ - cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); - if (cur == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSearchNs : malloc failed\n"); - return(NULL); - } - memset(cur, 0, sizeof(xmlNs)); - cur->type = XML_LOCAL_NAMESPACE; - cur->href = xmlStrdup(XML_XML_NAMESPACE); - cur->prefix = xmlStrdup((const xmlChar *)"xml"); - cur->next = node->nsDef; - node->nsDef = cur; - return(cur); - } - if (doc->oldNs == NULL) { - /* - * Allocate a new Namespace and fill the fields. - */ - doc->oldNs = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); - if (doc->oldNs == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSearchNs : malloc failed\n"); - return(NULL); - } - memset(doc->oldNs, 0, sizeof(xmlNs)); - doc->oldNs->type = XML_LOCAL_NAMESPACE; - - doc->oldNs->href = xmlStrdup(XML_XML_NAMESPACE); - doc->oldNs->prefix = xmlStrdup((const xmlChar *)"xml"); - } - return(doc->oldNs); - } - while (node != NULL) { - if ((node->type == XML_ENTITY_REF_NODE) || - (node->type == XML_ENTITY_NODE) || - (node->type == XML_ENTITY_DECL)) - return(NULL); - if (node->type == XML_ELEMENT_NODE) { - cur = node->nsDef; - while (cur != NULL) { - if ((cur->prefix == NULL) && (nameSpace == NULL) && - (cur->href != NULL)) - return(cur); - if ((cur->prefix != NULL) && (nameSpace != NULL) && - (cur->href != NULL) && - (xmlStrEqual(cur->prefix, nameSpace))) - return(cur); - cur = cur->next; - } - } - node = node->parent; - } - return(NULL); -} - -/** - * xmlSearchNsByHref: - * @doc: the document - * @node: the current node - * @href: the namespace value - * - * Search a Ns aliasing a given URI. Recurse on the parents until it finds - * the defined namespace or return NULL otherwise. - * Returns the namespace pointer or NULL. - */ -xmlNsPtr -xmlSearchNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar *href) { - xmlNsPtr cur; - xmlNodePtr orig = node; - - if ((node == NULL) || (href == NULL)) return(NULL); - if (xmlStrEqual(href, XML_XML_NAMESPACE)) { - /* - * Only the document can hold the XML spec namespace. - */ - if ((doc == NULL) && (node->type == XML_ELEMENT_NODE)) { - /* - * The XML-1.0 namespace is normally held on the root - * element. In this case exceptionally create it on the - * node element. - */ - cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); - if (cur == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSearchNs : malloc failed\n"); - return(NULL); - } - memset(cur, 0, sizeof(xmlNs)); - cur->type = XML_LOCAL_NAMESPACE; - cur->href = xmlStrdup(XML_XML_NAMESPACE); - cur->prefix = xmlStrdup((const xmlChar *)"xml"); - cur->next = node->nsDef; - node->nsDef = cur; - return(cur); - } - if (doc->oldNs == NULL) { - /* - * Allocate a new Namespace and fill the fields. - */ - doc->oldNs = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); - if (doc->oldNs == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSearchNsByHref : malloc failed\n"); - return(NULL); - } - memset(doc->oldNs, 0, sizeof(xmlNs)); - doc->oldNs->type = XML_LOCAL_NAMESPACE; - - doc->oldNs->href = xmlStrdup(XML_XML_NAMESPACE); - doc->oldNs->prefix = xmlStrdup((const xmlChar *)"xml"); - } - return(doc->oldNs); - } - while (node != NULL) { - cur = node->nsDef; - while (cur != NULL) { - if ((cur->href != NULL) && (href != NULL) && - (xmlStrEqual(cur->href, href))) { - /* - * Check that the prefix is not shadowed between orig and node - */ - xmlNodePtr check = orig; - xmlNsPtr tst; - - while (check != node) { - tst = check->nsDef; - while (tst != NULL) { - if ((tst->prefix == NULL) && (cur->prefix == NULL)) - goto shadowed; - if ((tst->prefix != NULL) && (cur->prefix != NULL) && - (xmlStrEqual(tst->prefix, cur->prefix))) - goto shadowed; - tst = tst->next; - } - check = check->parent; - } - return(cur); - } -shadowed: - cur = cur->next; - } - node = node->parent; - } - return(NULL); -} - -/** - * xmlNewReconciliedNs: - * @doc: the document - * @tree: a node expected to hold the new namespace - * @ns: the original namespace - * - * This function tries to locate a namespace definition in a tree - * ancestors, or create a new namespace definition node similar to - * @ns trying to reuse the same prefix. However if the given prefix is - * null (default namespace) or reused within the subtree defined by - * @tree or on one of its ancestors then a new prefix is generated. - * Returns the (new) namespace definition or NULL in case of error - */ -xmlNsPtr -xmlNewReconciliedNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) { - xmlNsPtr def; - xmlChar prefix[50]; - int counter = 1; - - if (tree == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewReconciliedNs : tree == NULL\n"); -#endif - return(NULL); - } - if (ns == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNewReconciliedNs : ns == NULL\n"); -#endif - return(NULL); - } - /* - * Search an existing namespace definition inherited. - */ - def = xmlSearchNsByHref(doc, tree, ns->href); - if (def != NULL) - return(def); - - /* - * Find a close prefix which is not already in use. - * Let's strip namespace prefixes longer than 20 chars ! - */ - if (ns->prefix == NULL) - snprintf((char *) prefix, sizeof(prefix), "default"); - else - snprintf((char *) prefix, sizeof(prefix), "%.20s", ns->prefix); - - def = xmlSearchNs(doc, tree, prefix); - while (def != NULL) { - if (counter > 1000) return(NULL); - if (ns->prefix == NULL) - snprintf((char *) prefix, sizeof(prefix), "default%d", counter++); - else - snprintf((char *) prefix, sizeof(prefix), "%.20s%d", ns->prefix, counter++); - def = xmlSearchNs(doc, tree, prefix); - } - - /* - * OK, now we are ready to create a new one. - */ - def = xmlNewNs(tree, ns->href, prefix); - return(def); -} - -/** - * xmlReconciliateNs: - * @doc: the document - * @tree: a node defining the subtree to reconciliate - * - * This function checks that all the namespaces declared within the given - * tree are properly declared. This is needed for example after Copy or Cut - * and then paste operations. The subtree may still hold pointers to - * namespace declarations outside the subtree or invalid/masked. As much - * as possible the function try to reuse the existing namespaces found in - * the new environment. If not possible the new namespaces are redeclared - * on @tree at the top of the given subtree. - * Returns the number of namespace declarations created or -1 in case of error. - */ -int -xmlReconciliateNs(xmlDocPtr doc, xmlNodePtr tree) { - xmlNsPtr *oldNs = NULL; - xmlNsPtr *newNs = NULL; - int sizeCache = 0; - int nbCache = 0; - - xmlNsPtr n; - xmlNodePtr node = tree; - xmlAttrPtr attr; - int ret = 0, i; - - while (node != NULL) { - /* - * Reconciliate the node namespace - */ - if (node->ns != NULL) { - /* - * initialize the cache if needed - */ - if (sizeCache == 0) { - sizeCache = 10; - oldNs = (xmlNsPtr *) xmlMalloc(sizeCache * - sizeof(xmlNsPtr)); - if (oldNs == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlReconciliateNs : memory pbm\n"); - return(-1); - } - newNs = (xmlNsPtr *) xmlMalloc(sizeCache * - sizeof(xmlNsPtr)); - if (newNs == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlReconciliateNs : memory pbm\n"); - xmlFree(oldNs); - return(-1); - } - } - for (i = 0;i < nbCache;i++) { - if (oldNs[i] == node->ns) { - node->ns = newNs[i]; - break; - } - } - if (i == nbCache) { - /* - * OK we need to recreate a new namespace definition - */ - n = xmlNewReconciliedNs(doc, tree, node->ns); - if (n != NULL) { /* :-( what if else ??? */ - /* - * check if we need to grow the cache buffers. - */ - if (sizeCache <= nbCache) { - sizeCache *= 2; - oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache * - sizeof(xmlNsPtr)); - if (oldNs == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlReconciliateNs : memory pbm\n"); - xmlFree(newNs); - return(-1); - } - newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache * - sizeof(xmlNsPtr)); - if (newNs == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlReconciliateNs : memory pbm\n"); - xmlFree(oldNs); - return(-1); - } - } - newNs[nbCache] = n; - oldNs[nbCache++] = node->ns; - node->ns = n; - } - } - } - /* - * now check for namespace hold by attributes on the node. - */ - attr = node->properties; - while (attr != NULL) { - if (attr->ns != NULL) { - /* - * initialize the cache if needed - */ - if (sizeCache == 0) { - sizeCache = 10; - oldNs = (xmlNsPtr *) xmlMalloc(sizeCache * - sizeof(xmlNsPtr)); - if (oldNs == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlReconciliateNs : memory pbm\n"); - return(-1); - } - newNs = (xmlNsPtr *) xmlMalloc(sizeCache * - sizeof(xmlNsPtr)); - if (newNs == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlReconciliateNs : memory pbm\n"); - xmlFree(oldNs); - return(-1); - } - } - for (i = 0;i < nbCache;i++) { - if (oldNs[i] == attr->ns) { - attr->ns = newNs[i]; - break; - } - } - if (i == nbCache) { - /* - * OK we need to recreate a new namespace definition - */ - n = xmlNewReconciliedNs(doc, tree, attr->ns); - if (n != NULL) { /* :-( what if else ??? */ - /* - * check if we need to grow the cache buffers. - */ - if (sizeCache <= nbCache) { - sizeCache *= 2; - oldNs = (xmlNsPtr *) xmlRealloc(oldNs, sizeCache * - sizeof(xmlNsPtr)); - if (oldNs == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlReconciliateNs : memory pbm\n"); - xmlFree(newNs); - return(-1); - } - newNs = (xmlNsPtr *) xmlRealloc(newNs, sizeCache * - sizeof(xmlNsPtr)); - if (newNs == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlReconciliateNs : memory pbm\n"); - xmlFree(oldNs); - return(-1); - } - } - newNs[nbCache] = n; - oldNs[nbCache++] = attr->ns; - attr->ns = n; - } - } - } - attr = attr->next; - } - - /* - * Browse the full subtree, deep first - */ - if (node->children != NULL) { - /* deep first */ - node = node->children; - } else if ((node != tree) && (node->next != NULL)) { - /* then siblings */ - node = node->next; - } else if (node != tree) { - /* go up to parents->next if needed */ - while (node != tree) { - if (node->parent != NULL) - node = node->parent; - if ((node != tree) && (node->next != NULL)) { - node = node->next; - break; - } - if (node->parent == NULL) { - node = NULL; - break; - } - } - /* exit condition */ - if (node == tree) - node = NULL; - } else - break; - } - if (oldNs != NULL) - xmlFree(oldNs); - if (newNs != NULL) - xmlFree(newNs); - return(ret); -} - -/** - * xmlHasProp: - * @node: the node - * @name: the attribute name - * - * Search an attribute associated to a node - * This function also looks in DTD attribute declaration for #FIXED or - * default declaration values unless DTD use has been turned off. - * - * Returns the attribute or the attribute declaration or NULL if - * neither was found. - */ -xmlAttrPtr -xmlHasProp(xmlNodePtr node, const xmlChar *name) { - xmlAttrPtr prop; - xmlDocPtr doc; - - if ((node == NULL) || (name == NULL)) return(NULL); - /* - * Check on the properties attached to the node - */ - prop = node->properties; - while (prop != NULL) { - if (xmlStrEqual(prop->name, name)) { - return(prop); - } - prop = prop->next; - } - if (!xmlCheckDTD) return(NULL); - - /* - * Check if there is a default declaration in the internal - * or external subsets - */ - doc = node->doc; - if (doc != NULL) { - xmlAttributePtr attrDecl; - if (doc->intSubset != NULL) { - attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name); - if ((attrDecl == NULL) && (doc->extSubset != NULL)) - attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name); - if (attrDecl != NULL) - return((xmlAttrPtr) attrDecl); - } - } - return(NULL); -} - -/** - * xmlHasNsProp: - * @node: the node - * @name: the attribute name - * @nameSpace: the URI of the namespace - * - * Search for an attribute associated to a node - * This attribute has to be anchored in the namespace specified. - * This does the entity substitution. - * This function looks in DTD attribute declaration for #FIXED or - * default declaration values unless DTD use has been turned off. - * - * Returns the attribute or the attribute declaration or NULL - * if neither was found. - */ -xmlAttrPtr -xmlHasNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *nameSpace) { - xmlAttrPtr prop; - xmlDocPtr doc; - - if (node == NULL) - return(NULL); - - prop = node->properties; - if (nameSpace == NULL) - return(xmlHasProp(node, name)); - while (prop != NULL) { - /* - * One need to have - * - same attribute names - * - and the attribute carrying that namespace - */ - if ((xmlStrEqual(prop->name, name)) && - ((prop->ns != NULL) && (xmlStrEqual(prop->ns->href, nameSpace)))) { - return(prop); - } - prop = prop->next; - } - if (!xmlCheckDTD) return(NULL); - - /* - * Check if there is a default declaration in the internal - * or external subsets - */ - doc = node->doc; - if (doc != NULL) { - if (doc->intSubset != NULL) { - xmlAttributePtr attrDecl = NULL; - xmlNsPtr *nsList, *cur; - xmlChar *ename; - - nsList = xmlGetNsList(node->doc, node); - if (nsList == NULL) - return(NULL); - if ((node->ns != NULL) && (node->ns->prefix != NULL)) { - ename = xmlStrdup(node->ns->prefix); - ename = xmlStrcat(ename, BAD_CAST ":"); - ename = xmlStrcat(ename, node->name); - } else { - ename = xmlStrdup(node->name); - } - if (ename == NULL) { - xmlFree(nsList); - return(NULL); - } - - cur = nsList; - while (*cur != NULL) { - if (xmlStrEqual((*cur)->href, nameSpace)) { - attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, ename, - name, (*cur)->prefix); - if ((attrDecl == NULL) && (doc->extSubset != NULL)) - attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, ename, - name, (*cur)->prefix); - } - cur++; - } - xmlFree(nsList); - xmlFree(ename); - return((xmlAttrPtr) attrDecl); - } - } - return(NULL); -} - -/** - * xmlGetProp: - * @node: the node - * @name: the attribute name - * - * Search and get the value of an attribute associated to a node - * This does the entity substitution. - * This function looks in DTD attribute declaration for #FIXED or - * default declaration values unless DTD use has been turned off. - * - * Returns the attribute value or NULL if not found. - * It's up to the caller to free the memory with xmlFree(). - */ -xmlChar * -xmlGetProp(xmlNodePtr node, const xmlChar *name) { - xmlAttrPtr prop; - xmlDocPtr doc; - - if ((node == NULL) || (name == NULL)) return(NULL); - /* - * Check on the properties attached to the node - */ - prop = node->properties; - while (prop != NULL) { - if (xmlStrEqual(prop->name, name)) { - xmlChar *ret; - - ret = xmlNodeListGetString(node->doc, prop->children, 1); - if (ret == NULL) return(xmlStrdup((xmlChar *)"")); - return(ret); - } - prop = prop->next; - } - if (!xmlCheckDTD) return(NULL); - - /* - * Check if there is a default declaration in the internal - * or external subsets - */ - doc = node->doc; - if (doc != NULL) { - xmlAttributePtr attrDecl; - if (doc->intSubset != NULL) { - attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name); - if ((attrDecl == NULL) && (doc->extSubset != NULL)) - attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name); - if (attrDecl != NULL) - return(xmlStrdup(attrDecl->defaultValue)); - } - } - return(NULL); -} - -/** - * xmlGetNsProp: - * @node: the node - * @name: the attribute name - * @nameSpace: the URI of the namespace - * - * Search and get the value of an attribute associated to a node - * This attribute has to be anchored in the namespace specified. - * This does the entity substitution. - * This function looks in DTD attribute declaration for #FIXED or - * default declaration values unless DTD use has been turned off. - * - * Returns the attribute value or NULL if not found. - * It's up to the caller to free the memory with xmlFree(). - */ -xmlChar * -xmlGetNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *nameSpace) { - xmlAttrPtr prop; - xmlDocPtr doc; - xmlNsPtr ns; - - if (node == NULL) - return(NULL); - - prop = node->properties; - if (nameSpace == NULL) - return(xmlGetProp(node, name)); - while (prop != NULL) { - /* - * One need to have - * - same attribute names - * - and the attribute carrying that namespace - */ - if ((xmlStrEqual(prop->name, name)) && - ((prop->ns != NULL) && - (xmlStrEqual(prop->ns->href, nameSpace)))) { - xmlChar *ret; - - ret = xmlNodeListGetString(node->doc, prop->children, 1); - if (ret == NULL) return(xmlStrdup((xmlChar *)"")); - return(ret); - } - prop = prop->next; - } - if (!xmlCheckDTD) return(NULL); - - /* - * Check if there is a default declaration in the internal - * or external subsets - */ - doc = node->doc; - if (doc != NULL) { - if (doc->intSubset != NULL) { - xmlAttributePtr attrDecl; - - attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name); - if ((attrDecl == NULL) && (doc->extSubset != NULL)) - attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name); - - if ((attrDecl != NULL) && (attrDecl->prefix != NULL)) { - /* - * The DTD declaration only allows a prefix search - */ - ns = xmlSearchNs(doc, node, attrDecl->prefix); - if ((ns != NULL) && (xmlStrEqual(ns->href, nameSpace))) - return(xmlStrdup(attrDecl->defaultValue)); - } - } - } - return(NULL); -} - -/** - * xmlSetProp: - * @node: the node - * @name: the attribute name - * @value: the attribute value - * - * Set (or reset) an attribute carried by a node. - * Returns the attribute pointer. - */ -xmlAttrPtr -xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) { - xmlAttrPtr prop; - xmlDocPtr doc; - - if ((node == NULL) || (name == NULL)) - return(NULL); - doc = node->doc; - prop = node->properties; - while (prop != NULL) { - if ((xmlStrEqual(prop->name, name)) && - (prop->ns == NULL)){ - xmlNodePtr oldprop = prop->children; - - prop->children = NULL; - prop->last = NULL; - if (value != NULL) { - xmlChar *buffer; - xmlNodePtr tmp; - - buffer = xmlEncodeEntitiesReentrant(node->doc, value); - prop->children = xmlStringGetNodeList(node->doc, buffer); - prop->last = NULL; - prop->doc = doc; - tmp = prop->children; - while (tmp != NULL) { - tmp->parent = (xmlNodePtr) prop; - tmp->doc = doc; - if (tmp->next == NULL) - prop->last = tmp; - tmp = tmp->next; - } - xmlFree(buffer); - } - if (oldprop != NULL) - xmlFreeNodeList(oldprop); - return(prop); - } - prop = prop->next; - } - prop = xmlNewProp(node, name, value); - return(prop); -} - -/** - * xmlUnsetProp: - * @node: the node - * @name: the attribute name - * - * Remove an attribute carried by a node. - * Returns 0 if successful, -1 if not found - */ -int -xmlUnsetProp(xmlNodePtr node, const xmlChar *name) { - xmlAttrPtr prop = node->properties, prev = NULL;; - - if ((node == NULL) || (name == NULL)) - return(-1); - while (prop != NULL) { - if ((xmlStrEqual(prop->name, name)) && - (prop->ns == NULL)) { - if (prev == NULL) - node->properties = prop->next; - else - prev->next = prop->next; - xmlFreeProp(prop); - return(0); - } - prev = prop; - prop = prop->next; - } - return(-1); -} - -/** - * xmlSetNsProp: - * @node: the node - * @ns: the namespace definition - * @name: the attribute name - * @value: the attribute value - * - * Set (or reset) an attribute carried by a node. - * The ns structure must be in scope, this is not checked. - * - * Returns the attribute pointer. - */ -xmlAttrPtr -xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name, - const xmlChar *value) { - xmlAttrPtr prop; - - if ((node == NULL) || (name == NULL)) - return(NULL); - - if (ns == NULL) - return(xmlSetProp(node, name, value)); - if (ns->href == NULL) - return(NULL); - prop = node->properties; - - while (prop != NULL) { - /* - * One need to have - * - same attribute names - * - and the attribute carrying that namespace - */ - if ((xmlStrEqual(prop->name, name)) && - (prop->ns != NULL) && (xmlStrEqual(prop->ns->href, ns->href))) { - if (prop->children != NULL) - xmlFreeNodeList(prop->children); - prop->children = NULL; - prop->last = NULL; - prop->ns = ns; - if (value != NULL) { - xmlChar *buffer; - xmlNodePtr tmp; - - buffer = xmlEncodeEntitiesReentrant(node->doc, value); - prop->children = xmlStringGetNodeList(node->doc, buffer); - prop->last = NULL; - tmp = prop->children; - while (tmp != NULL) { - tmp->parent = (xmlNodePtr) prop; - if (tmp->next == NULL) - prop->last = tmp; - tmp = tmp->next; - } - xmlFree(buffer); - } - return(prop); - } - prop = prop->next; - } - prop = xmlNewNsProp(node, ns, name, value); - return(prop); -} - -/** - * xmlUnsetNsProp: - * @node: the node - * @ns: the namespace definition - * @name: the attribute name - * - * Remove an attribute carried by a node. - * Returns 0 if successful, -1 if not found - */ -int -xmlUnsetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name) { - xmlAttrPtr prop = node->properties, prev = NULL;; - - if ((node == NULL) || (name == NULL)) - return(-1); - if (ns == NULL) - return(xmlUnsetProp(node, name)); - if (ns->href == NULL) - return(-1); - while (prop != NULL) { - if ((xmlStrEqual(prop->name, name)) && - (prop->ns != NULL) && (xmlStrEqual(prop->ns->href, ns->href))) { - if (prev == NULL) - node->properties = prop->next; - else - prev->next = prop->next; - xmlFreeProp(prop); - return(0); - } - prev = prop; - prop = prop->next; - } - return(-1); -} - -/** - * xmlNodeIsText: - * @node: the node - * - * Is this node a Text node ? - * Returns 1 yes, 0 no - */ -int -xmlNodeIsText(xmlNodePtr node) { - if (node == NULL) return(0); - - if (node->type == XML_TEXT_NODE) return(1); - return(0); -} - -/** - * xmlIsBlankNode: - * @node: the node - * - * Checks whether this node is an empty or whitespace only - * (and possibly ignorable) text-node. - * - * Returns 1 yes, 0 no - */ -int -xmlIsBlankNode(xmlNodePtr node) { - const xmlChar *cur; - if (node == NULL) return(0); - - if ((node->type != XML_TEXT_NODE) && - (node->type != XML_CDATA_SECTION_NODE)) - return(0); - if (node->content == NULL) return(1); - cur = node->content; - while (*cur != 0) { - if (!IS_BLANK(*cur)) return(0); - cur++; - } - - return(1); -} - -/** - * xmlTextConcat: - * @node: the node - * @content: the content - * @len: @content length - * - * Concat the given string at the end of the existing node content - */ - -void -xmlTextConcat(xmlNodePtr node, const xmlChar *content, int len) { - if (node == NULL) return; - - if ((node->type != XML_TEXT_NODE) && - (node->type != XML_CDATA_SECTION_NODE)) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlTextConcat: node is not text nor CDATA\n"); -#endif - return; - } - node->content = xmlStrncat(node->content, content, len); -} - -/************************************************************************ - * * - * Output : to a FILE or in memory * - * * - ************************************************************************/ - -/** - * xmlBufferCreate: - * - * routine to create an XML buffer. - * returns the new structure. - */ -xmlBufferPtr -xmlBufferCreate(void) { - xmlBufferPtr ret; - - ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer)); - if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlBufferCreate : out of memory!\n"); - return(NULL); - } - ret->use = 0; - ret->size = xmlDefaultBufferSize; - ret->alloc = xmlBufferAllocScheme; - ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar)); - if (ret->content == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlBufferCreate : out of memory!\n"); - xmlFree(ret); - return(NULL); - } - ret->content[0] = 0; - return(ret); -} - -/** - * xmlBufferCreateSize: - * @size: initial size of buffer - * - * routine to create an XML buffer. - * returns the new structure. - */ -xmlBufferPtr -xmlBufferCreateSize(size_t size) { - xmlBufferPtr ret; - - ret = (xmlBufferPtr) xmlMalloc(sizeof(xmlBuffer)); - if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlBufferCreate : out of memory!\n"); - return(NULL); - } - ret->use = 0; - ret->alloc = xmlBufferAllocScheme; - ret->size = (size ? size+2 : 0); /* +1 for ending null */ - if (ret->size){ - ret->content = (xmlChar *) xmlMalloc(ret->size * sizeof(xmlChar)); - if (ret->content == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlBufferCreate : out of memory!\n"); - xmlFree(ret); - return(NULL); - } - ret->content[0] = 0; - } else - ret->content = NULL; - return(ret); -} - -/** - * xmlBufferSetAllocationScheme: - * @buf: the buffer to tune - * @scheme: allocation scheme to use - * - * Sets the allocation scheme for this buffer - */ -void -xmlBufferSetAllocationScheme(xmlBufferPtr buf, - xmlBufferAllocationScheme scheme) { - if (buf == NULL) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufferSetAllocationScheme: buf == NULL\n"); -#endif - return; - } - - buf->alloc = scheme; -} - -/** - * xmlBufferFree: - * @buf: the buffer to free - * - * Frees an XML buffer. It frees both the content and the structure which - * encapsulate it. - */ -void -xmlBufferFree(xmlBufferPtr buf) { - if (buf == NULL) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufferFree: buf == NULL\n"); -#endif - return; - } - if (buf->content != NULL) { - xmlFree(buf->content); - } - xmlFree(buf); -} - -/** - * xmlBufferEmpty: - * @buf: the buffer - * - * empty a buffer. - */ -void -xmlBufferEmpty(xmlBufferPtr buf) { - if (buf->content == NULL) return; - buf->use = 0; - memset(buf->content, 0, buf->size); -} - -/** - * xmlBufferShrink: - * @buf: the buffer to dump - * @len: the number of xmlChar to remove - * - * Remove the beginning of an XML buffer. - * - * Returns the number of #xmlChar removed, or -1 in case of failure. - */ -int -xmlBufferShrink(xmlBufferPtr buf, unsigned int len) { - if (len == 0) return(0); - if (len > buf->use) return(-1); - - buf->use -= len; - memmove(buf->content, &buf->content[len], buf->use * sizeof(xmlChar)); - - buf->content[buf->use] = 0; - return(len); -} - -/** - * xmlBufferGrow: - * @buf: the buffer - * @len: the minimum free size to allocate - * - * Grow the available space of an XML buffer. - * - * Returns the new available space or -1 in case of error - */ -int -xmlBufferGrow(xmlBufferPtr buf, unsigned int len) { - int size; - xmlChar *newbuf; - - if (len + buf->use < buf->size) return(0); - - size = buf->use + len + 100; - - newbuf = (xmlChar *) xmlRealloc(buf->content, size); - if (newbuf == NULL) return(-1); - buf->content = newbuf; - buf->size = size; - return(buf->size - buf->use); -} - -/** - * xmlBufferDump: - * @file: the file output - * @buf: the buffer to dump - * - * Dumps an XML buffer to a FILE *. - * Returns the number of #xmlChar written - */ -int -xmlBufferDump(FILE *file, xmlBufferPtr buf) { - int ret; - - if (buf == NULL) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufferDump: buf == NULL\n"); -#endif - return(0); - } - if (buf->content == NULL) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufferDump: buf->content == NULL\n"); -#endif - return(0); - } - if (file == NULL) - file = stdout; - ret = fwrite(buf->content, sizeof(xmlChar), buf->use, file); - return(ret); -} - -/** - * xmlBufferContent: - * @buf: the buffer - * - * Function to extract the content of a buffer - * - * Returns the internal content - */ - -const xmlChar * -xmlBufferContent(const xmlBufferPtr buf) -{ - if(!buf) - return NULL; - - return buf->content; -} - -/** - * xmlBufferLength: - * @buf: the buffer - * - * Function to get the length of a buffer - * - * Returns the length of data in the internal content - */ - -int -xmlBufferLength(const xmlBufferPtr buf) -{ - if(!buf) - return 0; - - return buf->use; -} - -/** - * xmlBufferResize: - * @buf: the buffer to resize - * @size: the desired size - * - * Resize a buffer to accommodate minimum size of @size. - * - * Returns 0 in case of problems, 1 otherwise - */ -int -xmlBufferResize(xmlBufferPtr buf, unsigned int size) -{ - unsigned int newSize; - xmlChar* rebuf = NULL; - - /*take care of empty case*/ - newSize = (buf->size ? buf->size*2 : size); - - /* Don't resize if we don't have to */ - if (size < buf->size) - return 1; - - /* figure out new size */ - switch (buf->alloc){ - case XML_BUFFER_ALLOC_DOUBLEIT: - while (size > newSize) newSize *= 2; - break; - case XML_BUFFER_ALLOC_EXACT: - newSize = size+10; - break; - default: - newSize = size+10; - break; - } - - if (buf->content == NULL) - rebuf = (xmlChar *) xmlMalloc(newSize * sizeof(xmlChar)); - else - rebuf = (xmlChar *) xmlRealloc(buf->content, - newSize * sizeof(xmlChar)); - if (rebuf == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlBufferResize : out of memory!\n"); - return 0; - } - buf->content = rebuf; - buf->size = newSize; - - return 1; -} - -/** - * xmlBufferAdd: - * @buf: the buffer to dump - * @str: the #xmlChar string - * @len: the number of #xmlChar to add - * - * Add a string range to an XML buffer. if len == -1, the length of - * str is recomputed. - */ -void -xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) { - unsigned int needSize; - - if (str == NULL) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufferAdd: str == NULL\n"); -#endif - return; - } - if (len < -1) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufferAdd: len < 0\n"); -#endif - return; - } - if (len == 0) return; - - if (len < 0) - len = xmlStrlen(str); - - if (len <= 0) return; - - needSize = buf->use + len + 2; - if (needSize > buf->size){ - if (!xmlBufferResize(buf, needSize)){ - xmlGenericError(xmlGenericErrorContext, - "xmlBufferAdd : out of memory!\n"); - return; - } - } - - memmove(&buf->content[buf->use], str, len*sizeof(xmlChar)); - buf->use += len; - buf->content[buf->use] = 0; -} - -/** - * xmlBufferAddHead: - * @buf: the buffer - * @str: the #xmlChar string - * @len: the number of #xmlChar to add - * - * Add a string range to the beginning of an XML buffer. - * if len == -1, the length of @str is recomputed. - */ -void -xmlBufferAddHead(xmlBufferPtr buf, const xmlChar *str, int len) { - unsigned int needSize; - - if (str == NULL) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufferAddHead: str == NULL\n"); -#endif - return; - } - if (len < -1) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufferAddHead: len < 0\n"); -#endif - return; - } - if (len == 0) return; - - if (len < 0) - len = xmlStrlen(str); - - if (len <= 0) return; - - needSize = buf->use + len + 2; - if (needSize > buf->size){ - if (!xmlBufferResize(buf, needSize)){ - xmlGenericError(xmlGenericErrorContext, - "xmlBufferAddHead : out of memory!\n"); - return; - } - } - - memmove(&buf->content[len], &buf->content[0], buf->use * sizeof(xmlChar)); - memmove(&buf->content[0], str, len * sizeof(xmlChar)); - buf->use += len; - buf->content[buf->use] = 0; -} - -/** - * xmlBufferCat: - * @buf: the buffer to dump - * @str: the #xmlChar string - * - * Append a zero terminated string to an XML buffer. - */ -void -xmlBufferCat(xmlBufferPtr buf, const xmlChar *str) { - if (str != NULL) - xmlBufferAdd(buf, str, -1); -} - -/** - * xmlBufferCCat: - * @buf: the buffer to dump - * @str: the C char string - * - * Append a zero terminated C string to an XML buffer. - */ -void -xmlBufferCCat(xmlBufferPtr buf, const char *str) { - const char *cur; - - if (str == NULL) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufferCCat: str == NULL\n"); -#endif - return; - } - for (cur = str;*cur != 0;cur++) { - if (buf->use + 10 >= buf->size) { - if (!xmlBufferResize(buf, buf->use+10)){ - xmlGenericError(xmlGenericErrorContext, - "xmlBufferCCat : out of memory!\n"); - return; - } - } - buf->content[buf->use++] = *cur; - } - buf->content[buf->use] = 0; -} - -/** - * xmlBufferWriteCHAR: - * @buf: the XML buffer - * @string: the string to add - * - * routine which manages and grows an output buffer. This one adds - * xmlChars at the end of the buffer. - */ -void -xmlBufferWriteCHAR -(xmlBufferPtr buf, const xmlChar *string) { - xmlBufferCat(buf, string); -} - -/** - * xmlBufferWriteChar: - * @buf: the XML buffer output - * @string: the string to add - * - * routine which manage and grows an output buffer. This one add - * C chars at the end of the array. - */ -void -xmlBufferWriteChar(xmlBufferPtr buf, const char *string) { - xmlBufferCCat(buf, string); -} - - -/** - * xmlBufferWriteQuotedString: - * @buf: the XML buffer output - * @string: the string to add - * - * routine which manage and grows an output buffer. This one writes - * a quoted or double quoted #xmlChar string, checking first if it holds - * quote or double-quotes internally - */ -void -xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) { - if (xmlStrchr(string, '"')) { - if (xmlStrchr(string, '\'')) { -#ifdef DEBUG_BUFFER - xmlGenericError(xmlGenericErrorContext, - "xmlBufferWriteQuotedString: string contains quote and double-quotes !\n"); -#endif - } - xmlBufferCCat(buf, "'"); - xmlBufferCat(buf, string); - xmlBufferCCat(buf, "'"); - } else { - xmlBufferCCat(buf, "\""); - xmlBufferCat(buf, string); - xmlBufferCCat(buf, "\""); - } -} - - -/************************************************************************ - * * - * Dumping XML tree content to a simple buffer * - * * - ************************************************************************/ - -/** - * xmlAttrSerializeContent: - * @buf: the XML buffer output - * @doc: the document - * @attr: the attribute pointer - * - * Serialize the attribute in the buffer - */ -static void -xmlAttrSerializeContent(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr attr) -{ - const xmlChar *cur, *base; - xmlNodePtr children; - - children = attr->children; - while (children != NULL) { - switch (children->type) { - case XML_TEXT_NODE: - base = cur = children->content; - while (*cur != 0) { - if (*cur == '\n') { - if (base != cur) - xmlBufferAdd(buf, base, cur - base); - xmlBufferAdd(buf, BAD_CAST " ", 5); - cur++; - base = cur; -#if 0 - } else if (*cur == '\'') { - if (base != cur) - xmlBufferAdd(buf, base, cur - base); - xmlBufferAdd(buf, BAD_CAST "'", 6); - cur++; - base = cur; -#endif - } else if (*cur == '"') { - if (base != cur) - xmlBufferAdd(buf, base, cur - base); - xmlBufferAdd(buf, BAD_CAST """, 6); - cur++; - base = cur; - } else if (*cur == '<') { - if (base != cur) - xmlBufferAdd(buf, base, cur - base); - xmlBufferAdd(buf, BAD_CAST "<", 4); - cur++; - base = cur; - } else if (*cur == '>') { - if (base != cur) - xmlBufferAdd(buf, base, cur - base); - xmlBufferAdd(buf, BAD_CAST ">", 4); - cur++; - base = cur; - } else if (*cur == '&') { - if (base != cur) - xmlBufferAdd(buf, base, cur - base); - xmlBufferAdd(buf, BAD_CAST "&", 5); - cur++; - base = cur; - } else if ((*cur >= 0x80) && ((doc == NULL) || - (doc->encoding == - NULL))) { - /* - * We assume we have UTF-8 content. - */ - char tmp[10]; - int val = 0, l = 1; - - if (base != cur) - xmlBufferAdd(buf, base, cur - base); - if (*cur < 0xC0) { - xmlGenericError(xmlGenericErrorContext, - "xmlAttrSerializeContent : input not UTF-8\n"); - if (doc != NULL) - doc->encoding = - xmlStrdup(BAD_CAST "ISO-8859-1"); - snprintf(tmp, sizeof(tmp), "&#%d;", *cur); - tmp[sizeof(tmp) - 1] = 0; - xmlBufferAdd(buf, (xmlChar *) tmp, -1); - cur++; - base = cur; - continue; - } else if (*cur < 0xE0) { - val = (cur[0]) & 0x1F; - val <<= 6; - val |= (cur[1]) & 0x3F; - l = 2; - } else if (*cur < 0xF0) { - val = (cur[0]) & 0x0F; - val <<= 6; - val |= (cur[1]) & 0x3F; - val <<= 6; - val |= (cur[2]) & 0x3F; - l = 3; - } else if (*cur < 0xF8) { - val = (cur[0]) & 0x07; - val <<= 6; - val |= (cur[1]) & 0x3F; - val <<= 6; - val |= (cur[2]) & 0x3F; - val <<= 6; - val |= (cur[3]) & 0x3F; - l = 4; - } - if ((l == 1) || (!IS_CHAR(val))) { - xmlGenericError(xmlGenericErrorContext, - "xmlAttrSerializeContent : char out of range\n"); - if (doc != NULL) - doc->encoding = - xmlStrdup(BAD_CAST "ISO-8859-1"); - snprintf(tmp, sizeof(tmp), "&#%d;", *cur); - tmp[sizeof(tmp) - 1] = 0; - xmlBufferAdd(buf, (xmlChar *) tmp, -1); - cur++; - base = cur; - continue; - } - /* - * We could do multiple things here. Just save - * as a char ref - */ - snprintf(tmp, sizeof(tmp), "&#x%X;", val); - tmp[sizeof(tmp) - 1] = 0; - xmlBufferAdd(buf, (xmlChar *) tmp, -1); - cur += l; - base = cur; - } else { - cur++; - } - } - if (base != cur) - xmlBufferAdd(buf, base, cur - base); - break; - case XML_ENTITY_REF_NODE: - xmlBufferAdd(buf, BAD_CAST "&", 1); - xmlBufferAdd(buf, children->name, - xmlStrlen(children->name)); - xmlBufferAdd(buf, BAD_CAST ";", 1); - break; - default: - /* should not happen unless we have a badly built tree */ - break; - } - children = children->next; - } -} - -/** - * xmlNodeDump: - * @buf: the XML buffer output - * @doc: the document - * @cur: the current node - * @level: the imbrication level for indenting - * @format: is formatting allowed - * - * Dump an XML node, recursive behaviour,children are printed too. - * Note that format = 1 provide node indenting only if xmlIndentTreeOutput = 1 - * or xmlKeepBlanksDefault(0) was called - * - * Returns the number of bytes written to the buffer or -1 in case of error - */ -int -xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level, - int format) -{ - unsigned int use; - int ret; - xmlOutputBufferPtr outbuf; - - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNodeDump : node == NULL\n"); -#endif - return (-1); - } - if (buf == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNodeDump : buf == NULL\n"); -#endif - return (-1); - } - outbuf = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer)); - if (outbuf == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlNodeDump: out of memory!\n"); - return (-1); - } - memset(outbuf, 0, (size_t) sizeof(xmlOutputBuffer)); - outbuf->buffer = buf; - outbuf->encoder = NULL; - outbuf->writecallback = NULL; - outbuf->closecallback = NULL; - outbuf->context = NULL; - outbuf->written = 0; - - use = buf->use; - xmlNodeDumpOutput(outbuf, doc, cur, level, format, NULL); - xmlFree(outbuf); - ret = buf->use - use; - return (ret); -} - -/** - * xmlElemDump: - * @f: the FILE * for the output - * @doc: the document - * @cur: the current node - * - * Dump an XML/HTML node, recursive behaviour, children are printed too. - */ -void -xmlElemDump(FILE * f, xmlDocPtr doc, xmlNodePtr cur) -{ - xmlOutputBufferPtr outbuf; - - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlElemDump : cur == NULL\n"); -#endif - return; - } -#ifdef DEBUG_TREE - if (doc == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlElemDump : doc == NULL\n"); - } -#endif - - outbuf = xmlOutputBufferCreateFile(f, NULL); - if (outbuf == NULL) - return; - if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) { -#ifdef LIBXML_HTML_ENABLED - htmlNodeDumpOutput(outbuf, doc, cur, NULL); -#else - xmlGenericError(xmlGenericErrorContext, - "HTML support not compiled in\n"); -#endif /* LIBXML_HTML_ENABLED */ - } else - xmlNodeDumpOutput(outbuf, doc, cur, 0, 1, NULL); - xmlOutputBufferClose(outbuf); -} - -/************************************************************************ - * * - * Dumping XML tree content to an I/O output buffer * - * * - ************************************************************************/ - -static void -xhtmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, - int level, int format, const char *encoding); -static void -xmlNodeListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, - int level, int format, const char *encoding); -static void -xmlNodeDumpOutputInternal(xmlOutputBufferPtr buf, xmlDocPtr doc, - xmlNodePtr cur, int level, int format, const char *encoding); - -/** - * xmlNsDumpOutput: - * @buf: the XML buffer output - * @cur: a namespace - * - * Dump a local Namespace definition. - * Should be called in the context of attributes dumps. - */ -static void -xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) { - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNsDumpOutput : Ns == NULL\n"); -#endif - return; - } - if ((cur->type == XML_LOCAL_NAMESPACE) && (cur->href != NULL)) { - if (xmlStrEqual(cur->prefix, BAD_CAST "xml")) - return; - - /* Within the context of an element attributes */ - if (cur->prefix != NULL) { - xmlOutputBufferWriteString(buf, " xmlns:"); - xmlOutputBufferWriteString(buf, (const char *)cur->prefix); - } else - xmlOutputBufferWriteString(buf, " xmlns"); - xmlOutputBufferWriteString(buf, "="); - xmlBufferWriteQuotedString(buf->buffer, cur->href); - } -} - -/** - * xmlNsListDumpOutput: - * @buf: the XML buffer output - * @cur: the first namespace - * - * Dump a list of local Namespace definitions. - * Should be called in the context of attributes dumps. - */ -static void -xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) { - while (cur != NULL) { - xmlNsDumpOutput(buf, cur); - cur = cur->next; - } -} - -/** - * xmlDtdDumpOutput: - * @buf: the XML buffer output - * @doc: the document - * @encoding: an optional encoding string - * - * Dump the XML document DTD, if any. - */ -static void -xmlDtdDumpOutput(xmlOutputBufferPtr buf, xmlDtdPtr dtd, const char *encoding) { - if (dtd == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlDtdDumpOutput : no internal subset\n"); -#endif - return; - } - xmlOutputBufferWriteString(buf, "<!DOCTYPE "); - xmlOutputBufferWriteString(buf, (const char *)dtd->name); - if (dtd->ExternalID != NULL) { - xmlOutputBufferWriteString(buf, " PUBLIC "); - xmlBufferWriteQuotedString(buf->buffer, dtd->ExternalID); - xmlOutputBufferWriteString(buf, " "); - xmlBufferWriteQuotedString(buf->buffer, dtd->SystemID); - } else if (dtd->SystemID != NULL) { - xmlOutputBufferWriteString(buf, " SYSTEM "); - xmlBufferWriteQuotedString(buf->buffer, dtd->SystemID); - } - if ((dtd->entities == NULL) && (dtd->elements == NULL) && - (dtd->attributes == NULL) && (dtd->notations == NULL)) { - xmlOutputBufferWriteString(buf, ">"); - return; - } - xmlOutputBufferWriteString(buf, " [\n"); - xmlNodeListDumpOutput(buf, dtd->doc, dtd->children, -1, 0, encoding); - xmlOutputBufferWriteString(buf, "]>"); -} - -/** - * xmlAttrDumpOutput: - * @buf: the XML buffer output - * @doc: the document - * @cur: the attribute pointer - * @encoding: an optional encoding string - * - * Dump an XML attribute - */ -static void -xmlAttrDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur, - const char *encoding ATTRIBUTE_UNUSED) { - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAttrDumpOutput : property == NULL\n"); -#endif - return; - } - xmlOutputBufferWriteString(buf, " "); - if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { - xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix); - xmlOutputBufferWriteString(buf, ":"); - } - xmlOutputBufferWriteString(buf, (const char *)cur->name); - xmlOutputBufferWriteString(buf, "=\""); - xmlAttrSerializeContent(buf->buffer, doc, cur); - xmlOutputBufferWriteString(buf, "\""); -} - -/** - * xmlAttrListDumpOutput: - * @buf: the XML buffer output - * @doc: the document - * @cur: the first attribute pointer - * @encoding: an optional encoding string - * - * Dump a list of XML attributes - */ -static void -xmlAttrListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, - xmlAttrPtr cur, const char *encoding) { - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAttrListDumpOutput : property == NULL\n"); -#endif - return; - } - while (cur != NULL) { - xmlAttrDumpOutput(buf, doc, cur, encoding); - cur = cur->next; - } -} - - - -/** - * xmlNodeListDumpOutput: - * @buf: the XML buffer output - * @doc: the document - * @cur: the first node - * @level: the imbrication level for indenting - * @format: is formatting allowed - * @encoding: an optional encoding string - * - * Dump an XML node list, recursive behaviour, children are printed too. - * Note that format = 1 provide node indenting only if xmlIndentTreeOutput = 1 - * or xmlKeepBlanksDefault(0) was called - */ -static void -xmlNodeListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, - xmlNodePtr cur, int level, int format, const char *encoding) { - int i; - - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNodeListDumpOutput : node == NULL\n"); -#endif - return; - } - while (cur != NULL) { - if ((format) && (xmlIndentTreeOutput) && - (cur->type == XML_ELEMENT_NODE)) - for (i = 0;i < level;i++) - xmlOutputBufferWriteString(buf, xmlTreeIndentString); - xmlNodeDumpOutputInternal(buf, doc, cur, level, format, encoding); - if (format) { - xmlOutputBufferWriteString(buf, "\n"); - } - cur = cur->next; - } -} - -/** - * xmlNodeDumpOutputInternal: - * @buf: the XML buffer output - * @doc: the document - * @cur: the current node - * @level: the imbrication level for indenting - * @format: is formatting allowed - * @encoding: an optional encoding string - * - * Dump an XML node, recursive behaviour, children are printed too. - * Note that format = 1 provide node indenting only if xmlIndentTreeOutput = 1 - * or xmlKeepBlanksDefault(0) was called - */ -static void -xmlNodeDumpOutputInternal(xmlOutputBufferPtr buf, xmlDocPtr doc, - xmlNodePtr cur, int level, int format, const char *encoding) { - int i; - xmlNodePtr tmp; - - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNodeDumpOutput : node == NULL\n"); -#endif - return; - } - if (cur->type == XML_XINCLUDE_START) - return; - if (cur->type == XML_XINCLUDE_END) - return; - if (cur->type == XML_DTD_NODE) { - xmlDtdDumpOutput(buf, (xmlDtdPtr) cur, encoding); - return; - } - if (cur->type == XML_ELEMENT_DECL) { - xmlDumpElementDecl(buf->buffer, (xmlElementPtr) cur); - return; - } - if (cur->type == XML_ATTRIBUTE_DECL) { - xmlDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur); - return; - } - if (cur->type == XML_ENTITY_DECL) { - xmlDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur); - return; - } - if (cur->type == XML_TEXT_NODE) { - if (cur->content != NULL) { - if ((cur->name == xmlStringText) || - (cur->name != xmlStringTextNoenc)) { - xmlChar *buffer; - - if (encoding == NULL) - buffer = xmlEncodeEntitiesReentrant(doc, cur->content); - else - buffer = xmlEncodeSpecialChars(doc, cur->content); - if (buffer != NULL) { - xmlOutputBufferWriteString(buf, (const char *)buffer); - xmlFree(buffer); - } - } else { - /* - * Disable escaping, needed for XSLT - */ - xmlOutputBufferWriteString(buf, (const char *) cur->content); - } - } - - return; - } - if (cur->type == XML_PI_NODE) { - if (cur->content != NULL) { - xmlOutputBufferWriteString(buf, "<?"); - xmlOutputBufferWriteString(buf, (const char *)cur->name); - if (cur->content != NULL) { - xmlOutputBufferWriteString(buf, " "); - xmlOutputBufferWriteString(buf, (const char *)cur->content); - } - xmlOutputBufferWriteString(buf, "?>"); - } else { - xmlOutputBufferWriteString(buf, "<?"); - xmlOutputBufferWriteString(buf, (const char *)cur->name); - xmlOutputBufferWriteString(buf, "?>"); - } - return; - } - if (cur->type == XML_COMMENT_NODE) { - if (cur->content != NULL) { - xmlOutputBufferWriteString(buf, "<!--"); - xmlOutputBufferWriteString(buf, (const char *)cur->content); - xmlOutputBufferWriteString(buf, "-->"); - } - return; - } - if (cur->type == XML_ENTITY_REF_NODE) { - xmlOutputBufferWriteString(buf, "&"); - xmlOutputBufferWriteString(buf, (const char *)cur->name); - xmlOutputBufferWriteString(buf, ";"); - return; - } - if (cur->type == XML_CDATA_SECTION_NODE) { - xmlOutputBufferWriteString(buf, "<![CDATA["); - if (cur->content != NULL) - xmlOutputBufferWriteString(buf, (const char *)cur->content); - xmlOutputBufferWriteString(buf, "]]>"); - return; - } - - if (format == 1) { - tmp = cur->children; - while (tmp != NULL) { - if ((tmp->type == XML_TEXT_NODE) || - (tmp->type == XML_ENTITY_REF_NODE)) { - format = 0; - break; - } - tmp = tmp->next; - } - } - xmlOutputBufferWriteString(buf, "<"); - if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { - xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix); - xmlOutputBufferWriteString(buf, ":"); - } - - xmlOutputBufferWriteString(buf, (const char *)cur->name); - if (cur->nsDef) - xmlNsListDumpOutput(buf, cur->nsDef); - if (cur->properties != NULL) - xmlAttrListDumpOutput(buf, doc, cur->properties, encoding); - - if (((cur->type == XML_ELEMENT_NODE) || (cur->content == NULL)) && - (cur->children == NULL) && (!xmlSaveNoEmptyTags)) { - xmlOutputBufferWriteString(buf, "/>"); - return; - } - xmlOutputBufferWriteString(buf, ">"); - if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) { - xmlChar *buffer; - - if (encoding == NULL) - buffer = xmlEncodeEntitiesReentrant(doc, cur->content); - else - buffer = xmlEncodeSpecialChars(doc, cur->content); - if (buffer != NULL) { - xmlOutputBufferWriteString(buf, (const char *)buffer); - xmlFree(buffer); - } - } - if (cur->children != NULL) { - if (format) xmlOutputBufferWriteString(buf, "\n"); - xmlNodeListDumpOutput(buf, doc, cur->children, - (level >= 0?level+1:-1), format, encoding); - if ((xmlIndentTreeOutput) && (format)) - for (i = 0;i < level;i++) - xmlOutputBufferWriteString(buf, xmlTreeIndentString); - } - xmlOutputBufferWriteString(buf, "</"); - if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { - xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix); - xmlOutputBufferWriteString(buf, ":"); - } - - xmlOutputBufferWriteString(buf, (const char *)cur->name); - xmlOutputBufferWriteString(buf, ">"); -} - -/** - * xmlNodeDumpOutput: - * @buf: the XML buffer output - * @doc: the document - * @cur: the current node - * @level: the imbrication level for indenting - * @format: is formatting allowed - * @encoding: an optional encoding string - * - * Dump an XML node, recursive behaviour, children are printed too. - * Note that format = 1 provide node indenting only if xmlIndentTreeOutput = 1 - * or xmlKeepBlanksDefault(0) was called - */ -void -xmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, - int level, int format, const char *encoding) -{ -#ifdef LIBXML_HTML_ENABLED - xmlDtdPtr dtd; - int is_xhtml = 0; - - dtd = xmlGetIntSubset(doc); - if (dtd != NULL) { - is_xhtml = xmlIsXHTML(dtd->SystemID, dtd->ExternalID); - if (is_xhtml < 0) - is_xhtml = 0; - if ((is_xhtml) && (cur->parent == (xmlNodePtr) doc) && - (cur->type == XML_ELEMENT_NODE) && - (xmlStrEqual(cur->name, BAD_CAST "html"))) { - if (encoding != NULL) - htmlSetMetaEncoding((htmlDocPtr) cur, - (const xmlChar *) encoding); - else - htmlSetMetaEncoding((htmlDocPtr) cur, BAD_CAST "UTF-8"); - } - } - - if (is_xhtml) - xhtmlNodeDumpOutput(buf, doc, cur, level, format, encoding); - else -#endif - xmlNodeDumpOutputInternal(buf, doc, cur, level, format, encoding); -} - -/** - * xmlDocContentDumpOutput: - * @buf: the XML buffer output - * @cur: the document - * @encoding: an optional encoding string - * @format: should formatting spaces been added - * - * Dump an XML document. - * Note that format = 1 provide node indenting only if xmlIndentTreeOutput = 1 - * or xmlKeepBlanksDefault(0) was called - */ -static void -xmlDocContentDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr cur, - const char *encoding, int format) { -#ifdef LIBXML_HTML_ENABLED - xmlDtdPtr dtd; - int is_xhtml = 0; -#endif - - xmlOutputBufferWriteString(buf, "<?xml version="); - if (cur->version != NULL) - xmlBufferWriteQuotedString(buf->buffer, cur->version); - else - xmlOutputBufferWriteString(buf, "\"1.0\""); - if (encoding == NULL) { - if (cur->encoding != NULL) - encoding = (const char *) cur->encoding; - else if (cur->charset != XML_CHAR_ENCODING_UTF8) - encoding = xmlGetCharEncodingName((xmlCharEncoding) cur->charset); - } - if (encoding != NULL) { - xmlOutputBufferWriteString(buf, " encoding="); - xmlBufferWriteQuotedString(buf->buffer, (xmlChar *) encoding); - } - switch (cur->standalone) { - case 0: - xmlOutputBufferWriteString(buf, " standalone=\"no\""); - break; - case 1: - xmlOutputBufferWriteString(buf, " standalone=\"yes\""); - break; - } - xmlOutputBufferWriteString(buf, "?>\n"); - -#ifdef LIBXML_HTML_ENABLED - dtd = xmlGetIntSubset(cur); - if (dtd != NULL) { - is_xhtml = xmlIsXHTML(dtd->SystemID, dtd->ExternalID); - if (is_xhtml < 0) is_xhtml = 0; - } - if (is_xhtml) { - if (encoding != NULL) - htmlSetMetaEncoding(cur, (const xmlChar *) encoding); - else - htmlSetMetaEncoding(cur, BAD_CAST "UTF-8"); - } -#endif - if (cur->children != NULL) { - xmlNodePtr child = cur->children; - - while (child != NULL) { -#ifdef LIBXML_HTML_ENABLED - if (is_xhtml) - xhtmlNodeDumpOutput(buf, cur, child, 0, format, encoding); - else -#endif - xmlNodeDumpOutputInternal(buf, cur, child, 0, format, encoding); - xmlOutputBufferWriteString(buf, "\n"); - child = child->next; - } - } -} - -#ifdef LIBXML_HTML_ENABLED -/************************************************************************ - * * - * Functions specific to XHTML serialization * - * * - ************************************************************************/ - -#define XHTML_STRICT_PUBLIC_ID BAD_CAST \ - "-//W3C//DTD XHTML 1.0 Strict//EN" -#define XHTML_STRICT_SYSTEM_ID BAD_CAST \ - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" -#define XHTML_FRAME_PUBLIC_ID BAD_CAST \ - "-//W3C//DTD XHTML 1.0 Frameset//EN" -#define XHTML_FRAME_SYSTEM_ID BAD_CAST \ - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd" -#define XHTML_TRANS_PUBLIC_ID BAD_CAST \ - "-//W3C//DTD XHTML 1.0 Transitional//EN" -#define XHTML_TRANS_SYSTEM_ID BAD_CAST \ - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" - -#define XHTML_NS_NAME BAD_CAST "http://www.w3.org/1999/xhtml" -/** - * xmlIsXHTML: - * @systemID: the system identifier - * @publicID: the public identifier - * - * Try to find if the document correspond to an XHTML DTD - * - * Returns 1 if true, 0 if not and -1 in case of error - */ -int -xmlIsXHTML(const xmlChar *systemID, const xmlChar *publicID) { - if ((systemID == NULL) && (publicID == NULL)) - return(-1); - if (publicID != NULL) { - if (xmlStrEqual(publicID, XHTML_STRICT_PUBLIC_ID)) return(1); - if (xmlStrEqual(publicID, XHTML_FRAME_PUBLIC_ID)) return(1); - if (xmlStrEqual(publicID, XHTML_TRANS_PUBLIC_ID)) return(1); - } - if (systemID != NULL) { - if (xmlStrEqual(systemID, XHTML_STRICT_SYSTEM_ID)) return(1); - if (xmlStrEqual(systemID, XHTML_FRAME_SYSTEM_ID)) return(1); - if (xmlStrEqual(systemID, XHTML_TRANS_SYSTEM_ID)) return(1); - } - return(0); -} - -/** - * xhtmlIsEmpty: - * @node: the node - * - * Check if a node is an empty xhtml node - * - * Returns 1 if the node is an empty node, 0 if not and -1 in case of error - */ -static int -xhtmlIsEmpty(xmlNodePtr node) { - if (node == NULL) - return(-1); - if (node->type != XML_ELEMENT_NODE) - return(0); - if ((node->ns != NULL) && (!xmlStrEqual(node->ns->href, XHTML_NS_NAME))) - return(0); - if (node->children != NULL) - return(0); - switch (node->name[0]) { - case 'a': - if (xmlStrEqual(node->name, BAD_CAST "area")) - return(1); - return(0); - case 'b': - if (xmlStrEqual(node->name, BAD_CAST "br")) - return(1); - if (xmlStrEqual(node->name, BAD_CAST "base")) - return(1); - if (xmlStrEqual(node->name, BAD_CAST "basefont")) - return(1); - return(0); - case 'c': - if (xmlStrEqual(node->name, BAD_CAST "col")) - return(1); - return(0); - case 'f': - if (xmlStrEqual(node->name, BAD_CAST "frame")) - return(1); - return(0); - case 'h': - if (xmlStrEqual(node->name, BAD_CAST "hr")) - return(1); - return(0); - case 'i': - if (xmlStrEqual(node->name, BAD_CAST "img")) - return(1); - if (xmlStrEqual(node->name, BAD_CAST "input")) - return(1); - if (xmlStrEqual(node->name, BAD_CAST "isindex")) - return(1); - return(0); - case 'l': - if (xmlStrEqual(node->name, BAD_CAST "link")) - return(1); - return(0); - case 'm': - if (xmlStrEqual(node->name, BAD_CAST "meta")) - return(1); - return(0); - case 'p': - if (xmlStrEqual(node->name, BAD_CAST "param")) - return(1); - return(0); - } - return(0); -} - -/** - * xhtmlAttrListDumpOutput: - * @buf: the XML buffer output - * @doc: the document - * @cur: the first attribute pointer - * @encoding: an optional encoding string - * - * Dump a list of XML attributes - */ -static void -xhtmlAttrListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, - xmlAttrPtr cur, const char *encoding) { - xmlAttrPtr xml_lang = NULL; - xmlAttrPtr lang = NULL; - xmlAttrPtr name = NULL; - xmlAttrPtr id = NULL; - - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlAttrListDumpOutput : property == NULL\n"); -#endif - return; - } - while (cur != NULL) { - if ((cur->ns == NULL) && (xmlStrEqual(cur->name, BAD_CAST "id"))) - id = cur; - else - if ((cur->ns == NULL) && (xmlStrEqual(cur->name, BAD_CAST "name"))) - name = cur; - else - if ((cur->ns == NULL) && (xmlStrEqual(cur->name, BAD_CAST "lang"))) - lang = cur; - else - if ((cur->ns != NULL) && (xmlStrEqual(cur->name, BAD_CAST "lang")) && - (xmlStrEqual(cur->ns->prefix, BAD_CAST "xml"))) - xml_lang = cur; - else if ((cur->ns == NULL) && - ((cur->children == NULL) || - (cur->children->content == NULL) || - (cur->children->content[0] == 0)) && - (htmlIsBooleanAttr(cur->name))) { - if (cur->children != NULL) - xmlFreeNode(cur->children); - cur->children = xmlNewText(cur->name); - if (cur->children != NULL) - cur->children->parent = (xmlNodePtr) cur; - } - xmlAttrDumpOutput(buf, doc, cur, encoding); - cur = cur->next; - } - /* - * C.8 - */ - if ((name != NULL) && (id == NULL)) { - xmlOutputBufferWriteString(buf, " id=\""); - xmlAttrSerializeContent(buf->buffer, doc, name); - xmlOutputBufferWriteString(buf, "\""); - } - /* - * C.7. - */ - if ((lang != NULL) && (xml_lang == NULL)) { - xmlOutputBufferWriteString(buf, " xml:lang=\""); - xmlAttrSerializeContent(buf->buffer, doc, lang); - xmlOutputBufferWriteString(buf, "\""); - } else - if ((xml_lang != NULL) && (lang == NULL)) { - xmlOutputBufferWriteString(buf, " lang=\""); - xmlAttrSerializeContent(buf->buffer, doc, xml_lang); - xmlOutputBufferWriteString(buf, "\""); - } -} - -/** - * xhtmlNodeListDumpOutput: - * @buf: the XML buffer output - * @doc: the XHTML document - * @cur: the first node - * @level: the imbrication level for indenting - * @format: is formatting allowed - * @encoding: an optional encoding string - * - * Dump an XML node list, recursive behaviour, children are printed too. - * Note that format = 1 provide node indenting only if xmlIndentTreeOutput = 1 - * or xmlKeepBlanksDefault(0) was called - */ -static void -xhtmlNodeListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, - xmlNodePtr cur, int level, int format, const char *encoding) { - int i; - - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xhtmlNodeListDumpOutput : node == NULL\n"); -#endif - return; - } - while (cur != NULL) { - if ((format) && (xmlIndentTreeOutput) && - (cur->type == XML_ELEMENT_NODE)) - for (i = 0;i < level;i++) - xmlOutputBufferWriteString(buf, xmlTreeIndentString); - xhtmlNodeDumpOutput(buf, doc, cur, level, format, encoding); - if (format) { - xmlOutputBufferWriteString(buf, "\n"); - } - cur = cur->next; - } -} - -/** - * xhtmlNodeDumpOutput: - * @buf: the XML buffer output - * @doc: the XHTML document - * @cur: the current node - * @level: the imbrication level for indenting - * @format: is formatting allowed - * @encoding: an optional encoding string - * - * Dump an XHTML node, recursive behaviour, children are printed too. - * Note that format = 1 provide node indenting only if xmlIndentTreeOutput = 1 - * or xmlKeepBlanksDefault(0) was called - */ -static void -xhtmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, - int level, int format, const char *encoding) { - int i; - xmlNodePtr tmp; - - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlNodeDumpOutput : node == NULL\n"); -#endif - return; - } - if (cur->type == XML_XINCLUDE_START) - return; - if (cur->type == XML_XINCLUDE_END) - return; - if (cur->type == XML_DTD_NODE) { - xmlDtdDumpOutput(buf, (xmlDtdPtr) cur, encoding); - return; - } - if (cur->type == XML_ELEMENT_DECL) { - xmlDumpElementDecl(buf->buffer, (xmlElementPtr) cur); - return; - } - if (cur->type == XML_ATTRIBUTE_DECL) { - xmlDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur); - return; - } - if (cur->type == XML_ENTITY_DECL) { - xmlDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur); - return; - } - if (cur->type == XML_TEXT_NODE) { - if (cur->content != NULL) { - if ((cur->name == xmlStringText) || - (cur->name != xmlStringTextNoenc)) { - xmlChar *buffer; - - if (encoding == NULL) - buffer = xmlEncodeEntitiesReentrant(doc, cur->content); - else - buffer = xmlEncodeSpecialChars(doc, cur->content); - if (buffer != NULL) { - xmlOutputBufferWriteString(buf, (const char *)buffer); - xmlFree(buffer); - } - } else { - /* - * Disable escaping, needed for XSLT - */ - xmlOutputBufferWriteString(buf, (const char *) cur->content); - } - } - - return; - } - if (cur->type == XML_PI_NODE) { - if (cur->content != NULL) { - xmlOutputBufferWriteString(buf, "<?"); - xmlOutputBufferWriteString(buf, (const char *)cur->name); - if (cur->content != NULL) { - xmlOutputBufferWriteString(buf, " "); - xmlOutputBufferWriteString(buf, (const char *)cur->content); - } - xmlOutputBufferWriteString(buf, "?>"); - } else { - xmlOutputBufferWriteString(buf, "<?"); - xmlOutputBufferWriteString(buf, (const char *)cur->name); - xmlOutputBufferWriteString(buf, "?>"); - } - return; - } - if (cur->type == XML_COMMENT_NODE) { - if (cur->content != NULL) { - xmlOutputBufferWriteString(buf, "<!--"); - xmlOutputBufferWriteString(buf, (const char *)cur->content); - xmlOutputBufferWriteString(buf, "-->"); - } - return; - } - if (cur->type == XML_ENTITY_REF_NODE) { - xmlOutputBufferWriteString(buf, "&"); - xmlOutputBufferWriteString(buf, (const char *)cur->name); - xmlOutputBufferWriteString(buf, ";"); - return; - } - if (cur->type == XML_CDATA_SECTION_NODE) { - xmlOutputBufferWriteString(buf, "<![CDATA["); - if (cur->content != NULL) - xmlOutputBufferWriteString(buf, (const char *)cur->content); - xmlOutputBufferWriteString(buf, "]]>"); - return; - } - - if (format == 1) { - tmp = cur->children; - while (tmp != NULL) { - if ((tmp->type == XML_TEXT_NODE) || - (tmp->type == XML_ENTITY_REF_NODE)) { - format = 0; - break; - } - tmp = tmp->next; - } - } - xmlOutputBufferWriteString(buf, "<"); - if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { - xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix); - xmlOutputBufferWriteString(buf, ":"); - } - - xmlOutputBufferWriteString(buf, (const char *)cur->name); - if (cur->nsDef) - xmlNsListDumpOutput(buf, cur->nsDef); - if ((xmlStrEqual(cur->name, BAD_CAST "html") && - (cur->ns == NULL) && (cur->nsDef == NULL))) { - /* - * 3.1.1. Strictly Conforming Documents A.3.1.1 3/ - */ - xmlOutputBufferWriteString(buf, - " xmlns=\"http://www.w3.org/1999/xhtml\""); - } - if (cur->properties != NULL) - xhtmlAttrListDumpOutput(buf, doc, cur->properties, encoding); - - if ((cur->type == XML_ELEMENT_NODE) && (cur->children == NULL)) { - if (((cur->ns == NULL) || (cur->ns->prefix == NULL)) && - (xhtmlIsEmpty(cur) == 1)) { - /* - * C.2. Empty Elements - */ - xmlOutputBufferWriteString(buf, " />"); - } else { - /* - * C.3. Element Minimization and Empty Element Content - */ - xmlOutputBufferWriteString(buf, "></"); - if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { - xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix); - xmlOutputBufferWriteString(buf, ":"); - } - xmlOutputBufferWriteString(buf, (const char *)cur->name); - xmlOutputBufferWriteString(buf, ">"); - } - return; - } - xmlOutputBufferWriteString(buf, ">"); - if ((cur->type != XML_ELEMENT_NODE) && (cur->content != NULL)) { - xmlChar *buffer; - - if (encoding == NULL) - buffer = xmlEncodeEntitiesReentrant(doc, cur->content); - else - buffer = xmlEncodeSpecialChars(doc, cur->content); - if (buffer != NULL) { - xmlOutputBufferWriteString(buf, (const char *)buffer); - xmlFree(buffer); - } - } - - /* - * 4.8. Script and Style elements - */ - if ((cur->type == XML_ELEMENT_NODE) && - ((xmlStrEqual(cur->name, BAD_CAST "script")) || - (xmlStrEqual(cur->name, BAD_CAST "style"))) && - ((cur->ns == NULL) || - (xmlStrEqual(cur->ns->href, XHTML_NS_NAME)))) { - xmlNodePtr child = cur->children; - - while (child != NULL) { - if ((child->type == XML_TEXT_NODE) || - (child->type == XML_CDATA_SECTION_NODE)) { - /* - * Apparently CDATA escaping for style just break on IE, - * mozilla and galeon, so ... - */ - if (xmlStrEqual(cur->name, BAD_CAST "style") && - (xmlStrchr(child->content, '<') == NULL) && - (xmlStrchr(child->content, '>') == NULL) && - (xmlStrchr(child->content, '&') == NULL)) { - xhtmlNodeDumpOutput(buf, doc, child, 0, 0, encoding); - } else { - xmlOutputBufferWriteString(buf, "<![CDATA["); - if (child->content != NULL) - xmlOutputBufferWriteString(buf, - (const char *)child->content); - xmlOutputBufferWriteString(buf, "]]>"); - } - } else { - xhtmlNodeDumpOutput(buf, doc, child, 0, 0, encoding); - } - child = child->next; - } - } else if (cur->children != NULL) { - if (format) xmlOutputBufferWriteString(buf, "\n"); - xhtmlNodeListDumpOutput(buf, doc, cur->children, - (level >= 0?level+1:-1), format, encoding); - if ((xmlIndentTreeOutput) && (format)) - for (i = 0;i < level;i++) - xmlOutputBufferWriteString(buf, xmlTreeIndentString); - } - xmlOutputBufferWriteString(buf, "</"); - if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) { - xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix); - xmlOutputBufferWriteString(buf, ":"); - } - - xmlOutputBufferWriteString(buf, (const char *)cur->name); - xmlOutputBufferWriteString(buf, ">"); -} -#endif - -/************************************************************************ - * * - * Saving functions front-ends * - * * - ************************************************************************/ - -/** - * xmlDocDumpFormatMemoryEnc: - * @out_doc: Document to generate XML text from - * @doc_txt_ptr: Memory pointer for allocated XML text - * @doc_txt_len: Length of the generated XML text - * @txt_encoding: Character encoding to use when generating XML text - * @format: should formatting spaces been added - * - * Dump the current DOM tree into memory using the character encoding specified - * by the caller. Note it is up to the caller of this function to free the - * allocated memory with xmlFree(). - * Note that format = 1 provide node indenting only if xmlIndentTreeOutput = 1 - * or xmlKeepBlanksDefault(0) was called - */ - -void -xmlDocDumpFormatMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr, - int * doc_txt_len, const char * txt_encoding, - int format) { - int dummy = 0; - - xmlCharEncoding doc_charset; - xmlOutputBufferPtr out_buff = NULL; - xmlCharEncodingHandlerPtr conv_hdlr = NULL; - - if (doc_txt_len == NULL) { - doc_txt_len = &dummy; /* Continue, caller just won't get length */ - } - - if (doc_txt_ptr == NULL) { - *doc_txt_len = 0; - xmlGenericError(xmlGenericErrorContext, - "xmlDocDumpFormatMemoryEnc: Null return buffer pointer."); - return; - } - - *doc_txt_ptr = NULL; - *doc_txt_len = 0; - - if (out_doc == NULL) { - /* No document, no output */ - xmlGenericError(xmlGenericErrorContext, - "xmlDocDumpFormatMemoryEnc: Null DOM tree document pointer.\n"); - return; - } - - /* - * Validate the encoding value, if provided. - * This logic is copied from xmlSaveFileEnc. - */ - - if (txt_encoding == NULL) - txt_encoding = (const char *) out_doc->encoding; - if (txt_encoding != NULL) { - doc_charset = xmlParseCharEncoding(txt_encoding); - - if (out_doc->charset != XML_CHAR_ENCODING_UTF8) { - xmlGenericError(xmlGenericErrorContext, - "xmlDocDumpFormatMemoryEnc: Source document not in UTF8\n"); - return; - - } else if (doc_charset != XML_CHAR_ENCODING_UTF8) { - conv_hdlr = xmlFindCharEncodingHandler(txt_encoding); - if ( conv_hdlr == NULL ) { - xmlGenericError(xmlGenericErrorContext, - "%s: %s %s '%s'\n", - "xmlDocDumpFormatMemoryEnc", - "Failed to identify encoding handler for", - "character set", - txt_encoding); - return; - } - } - } - - if ((out_buff = xmlAllocOutputBuffer(conv_hdlr)) == NULL ) { - xmlGenericError(xmlGenericErrorContext, - "xmlDocDumpFormatMemoryEnc: Failed to allocate output buffer.\n"); - return; - } - - xmlDocContentDumpOutput(out_buff, out_doc, txt_encoding, format); - xmlOutputBufferFlush(out_buff); - if (out_buff->conv != NULL) { - *doc_txt_len = out_buff->conv->use; - *doc_txt_ptr = xmlStrndup(out_buff->conv->content, *doc_txt_len); - } else { - *doc_txt_len = out_buff->buffer->use; - *doc_txt_ptr = xmlStrndup(out_buff->buffer->content, *doc_txt_len); - } - (void)xmlOutputBufferClose(out_buff); - - if ((*doc_txt_ptr == NULL) && (*doc_txt_len > 0)) { - *doc_txt_len = 0; - xmlGenericError(xmlGenericErrorContext, - "xmlDocDumpFormatMemoryEnc: %s\n", - "Failed to allocate memory for document text representation."); - } - - return; -} - -/** - * xmlDocDumpMemory: - * @cur: the document - * @mem: OUT: the memory pointer - * @size: OUT: the memory length - * - * Dump an XML document in memory and return the #xmlChar * and it's size. - * It's up to the caller to free the memory with xmlFree(). - */ -void -xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) { - xmlDocDumpFormatMemoryEnc(cur, mem, size, NULL, 0); -} - -/** - * xmlDocDumpFormatMemory: - * @cur: the document - * @mem: OUT: the memory pointer - * @size: OUT: the memory length - * @format: should formatting spaces been added - * - * - * Dump an XML document in memory and return the #xmlChar * and it's size. - * It's up to the caller to free the memory with xmlFree(). - * Note that format = 1 provide node indenting only if xmlIndentTreeOutput = 1 - * or xmlKeepBlanksDefault(0) was called - */ -void -xmlDocDumpFormatMemory(xmlDocPtr cur, xmlChar**mem, int *size, int format) { - xmlDocDumpFormatMemoryEnc(cur, mem, size, NULL, format); -} - -/** - * xmlDocDumpMemoryEnc: - * @out_doc: Document to generate XML text from - * @doc_txt_ptr: Memory pointer for allocated XML text - * @doc_txt_len: Length of the generated XML text - * @txt_encoding: Character encoding to use when generating XML text - * - * Dump the current DOM tree into memory using the character encoding specified - * by the caller. Note it is up to the caller of this function to free the - * allocated memory with xmlFree(). - */ - -void -xmlDocDumpMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr, - int * doc_txt_len, const char * txt_encoding) { - xmlDocDumpFormatMemoryEnc(out_doc, doc_txt_ptr, doc_txt_len, - txt_encoding, 0); -} - -/** - * xmlGetDocCompressMode: - * @doc: the document - * - * get the compression ratio for a document, ZLIB based - * Returns 0 (uncompressed) to 9 (max compression) - */ -int -xmlGetDocCompressMode (xmlDocPtr doc) { - if (doc == NULL) return(-1); - return(doc->compression); -} - -/** - * xmlSetDocCompressMode: - * @doc: the document - * @mode: the compression ratio - * - * set the compression ratio for a document, ZLIB based - * Correct values: 0 (uncompressed) to 9 (max compression) - */ -void -xmlSetDocCompressMode (xmlDocPtr doc, int mode) { - if (doc == NULL) return; - if (mode < 0) doc->compression = 0; - else if (mode > 9) doc->compression = 9; - else doc->compression = mode; -} - -/** - * xmlGetCompressMode: - * - * get the default compression mode used, ZLIB based. - * Returns 0 (uncompressed) to 9 (max compression) - */ -int -xmlGetCompressMode(void) -{ - return (xmlCompressMode); -} - -/** - * xmlSetCompressMode: - * @mode: the compression ratio - * - * set the default compression mode used, ZLIB based - * Correct values: 0 (uncompressed) to 9 (max compression) - */ -void -xmlSetCompressMode(int mode) { - if (mode < 0) xmlCompressMode = 0; - else if (mode > 9) xmlCompressMode = 9; - else xmlCompressMode = mode; -} - -/** - * xmlDocFormatDump: - * @f: the FILE* - * @cur: the document - * @format: should formatting spaces been added - * - * Dump an XML document to an open FILE. - * - * returns: the number of bytes written or -1 in case of failure. - */ -int -xmlDocFormatDump(FILE *f, xmlDocPtr cur, int format) { - xmlOutputBufferPtr buf; - const char * encoding; - xmlCharEncodingHandlerPtr handler = NULL; - int ret; - - if (cur == NULL) { -#ifdef DEBUG_TREE - xmlGenericError(xmlGenericErrorContext, - "xmlDocDump : document == NULL\n"); -#endif - return(-1); - } - encoding = (const char *) cur->encoding; - - if (encoding != NULL) { - xmlCharEncoding enc; - - enc = xmlParseCharEncoding(encoding); - - if (cur->charset != XML_CHAR_ENCODING_UTF8) { - xmlGenericError(xmlGenericErrorContext, - "xmlDocDump: document not in UTF8\n"); - return(-1); - } - if (enc != XML_CHAR_ENCODING_UTF8) { - handler = xmlFindCharEncodingHandler(encoding); - if (handler == NULL) { - xmlFree((char *) cur->encoding); - cur->encoding = NULL; - } - } - } - buf = xmlOutputBufferCreateFile(f, handler); - if (buf == NULL) return(-1); - xmlDocContentDumpOutput(buf, cur, NULL, format); - - ret = xmlOutputBufferClose(buf); - return(ret); -} - -/** - * xmlDocDump: - * @f: the FILE* - * @cur: the document - * - * Dump an XML document to an open FILE. - * - * returns: the number of bytes written or -1 in case of failure. - */ -int -xmlDocDump(FILE *f, xmlDocPtr cur) { - return(xmlDocFormatDump (f, cur, 0)); -} - -/** - * xmlSaveFileTo: - * @buf: an output I/O buffer - * @cur: the document - * @encoding: the encoding if any assuming the I/O layer handles the trancoding - * - * Dump an XML document to an I/O buffer. - * - * returns: the number of bytes written or -1 in case of failure. - */ -int -xmlSaveFileTo(xmlOutputBufferPtr buf, xmlDocPtr cur, const char *encoding) { - int ret; - - if (buf == NULL) return(0); - xmlDocContentDumpOutput(buf, cur, encoding, 0); - ret = xmlOutputBufferClose(buf); - return(ret); -} - -/** - * xmlSaveFormatFileTo: - * @buf: an output I/O buffer - * @cur: the document - * @encoding: the encoding if any assuming the I/O layer handles the trancoding - * @format: should formatting spaces been added - * - * Dump an XML document to an I/O buffer. - * - * returns: the number of bytes written or -1 in case of failure. - */ -int -xmlSaveFormatFileTo(xmlOutputBufferPtr buf, xmlDocPtr cur, const char *encoding, int format) { - int ret; - - if (buf == NULL) return(0); - xmlDocContentDumpOutput(buf, cur, encoding, format); - ret = xmlOutputBufferClose(buf); - return(ret); -} - -/** - * xmlSaveFormatFileEnc: - * @filename: the filename or URL to output - * @cur: the document being saved - * @encoding: the name of the encoding to use or NULL. - * @format: should formatting spaces be added. - * - * Dump an XML document to a file or an URL. - * - * Returns the number of bytes written or -1 in case of error. - */ -int -xmlSaveFormatFileEnc( const char * filename, xmlDocPtr cur, - const char * encoding, int format ) { - xmlOutputBufferPtr buf; - xmlCharEncodingHandlerPtr handler = NULL; - xmlCharEncoding enc; - int ret; - - if (encoding == NULL) - encoding = (const char *) cur->encoding; - - if (encoding != NULL) { - - enc = xmlParseCharEncoding(encoding); - if (cur->charset != XML_CHAR_ENCODING_UTF8) { - xmlGenericError(xmlGenericErrorContext, - "xmlSaveFormatFileEnc: document not in UTF8\n"); - return(-1); - } - if (enc != XML_CHAR_ENCODING_UTF8) { - handler = xmlFindCharEncodingHandler(encoding); - if (handler == NULL) - return(-1); - } - } - -#ifdef HAVE_ZLIB_H - if (cur->compression < 0) cur->compression = xmlCompressMode; -#endif - /* - * save the content to a temp buffer. - */ - buf = xmlOutputBufferCreateFilename(filename, handler, cur->compression); - if (buf == NULL) return(-1); - - xmlDocContentDumpOutput(buf, cur, encoding, format); - - ret = xmlOutputBufferClose(buf); - return(ret); -} - - -/** - * xmlSaveFileEnc: - * @filename: the filename (or URL) - * @cur: the document - * @encoding: the name of an encoding (or NULL) - * - * Dump an XML document, converting it to the given encoding - * - * returns: the number of bytes written or -1 in case of failure. - */ -int -xmlSaveFileEnc(const char *filename, xmlDocPtr cur, const char *encoding) { - return ( xmlSaveFormatFileEnc( filename, cur, encoding, 0 ) ); -} - -/** - * xmlSaveFormatFile: - * @filename: the filename (or URL) - * @cur: the document - * @format: should formatting spaces been added - * - * Dump an XML document to a file. Will use compression if - * compiled in and enabled. If @filename is "-" the stdout file is - * used. If @format is set then the document will be indented on output. - * - * returns: the number of bytes written or -1 in case of failure. - */ -int -xmlSaveFormatFile(const char *filename, xmlDocPtr cur, int format) { - return ( xmlSaveFormatFileEnc( filename, cur, NULL, format ) ); -} - -/** - * xmlSaveFile: - * @filename: the filename (or URL) - * @cur: the document - * - * Dump an XML document to a file. Will use compression if - * compiled in and enabled. If @filename is "-" the stdout file is - * used. - * returns: the number of bytes written or -1 in case of failure. - */ -int -xmlSaveFile(const char *filename, xmlDocPtr cur) { - return(xmlSaveFormatFileEnc(filename, cur, NULL, 0)); -} - |