📄 tree.c
字号:
/* * tree.c : implemetation of access function for an XML tree. * * See Copyright for the status of this software. * * Daniel.Veillard@w3.org */#include "global.h"#ifdef WIN32#include "win32config.h"#else#include "config.h"#endif#include <stdio.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/entities.h>#include <libxml/valid.h>static xmlChar xmlStringText[] = { 't', 'e', 'x', 't', 0 };static xmlChar xmlStringComment[] = { 'c', 'o', 'm', 'm', 'e', 'n', 't', 0 };int oldXMLWDcompatibility = 0;int xmlIndentTreeOutput = 0;xmlBufferAllocationScheme xmlBufferAllocScheme = XML_BUFFER_ALLOC_EXACT;static int xmlCompressMode = 0;static int xmlCheckDTD = 1;int xmlSaveNoEmptyTags = 0;#define IS_BLANK(c) \ (((c) == '\n') || ((c) == '\r') || ((c) == '\t') || ((c) == ' '))#define UPDATE_LAST_CHILD(n) if ((n) != NULL) { \ xmlNodePtr ulccur = (n)->children; \ if (ulccur == NULL) { \ (n)->last = NULL; \ } else { \ while (ulccur->next != NULL) ulccur = ulccur->next; \ (n)->last = ulccur; \}}/* #define DEBUG_BUFFER *//* #define DEBUG_TREE *//************************************************************************ * * * 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 */voidxmlSetBufferAllocationScheme(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 */xmlBufferAllocationSchemexmlGetBufferAllocationScheme() { return xmlBufferAllocScheme;}/** * xmlUpgradeOldNs: * @doc: a document pointer * * Upgrade old style Namespaces (PI) and move them to the root of the document. */voidxmlUpgradeOldNs(xmlDocPtr doc) { xmlNsPtr cur; if ((doc == NULL) || (doc->oldNs == NULL)) return; if (doc->children == NULL) {#ifdef DEBUG_TREE fprintf(stderr, "xmlUpgradeOldNs: failed no root !\n");#endif return; } cur = doc->oldNs; while (cur->next != NULL) { cur->type = XML_LOCAL_NAMESPACE; cur = cur->next; } cur->type = XML_LOCAL_NAMESPACE; cur->next = doc->children->nsDef; doc->children->nsDef = doc->oldNs; doc->oldNs = NULL;}/** * 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. * Returns returns a new namespace pointer or NULL */xmlNsPtrxmlNewNs(xmlNodePtr node, const xmlChar *href, const xmlChar *prefix) { xmlNsPtr cur; if (href == NULL) {#ifdef DEBUG_TREE fprintf(stderr, "xmlNewNs: href == NULL !\n");#endif return(NULL); } /* * Allocate a new Namespace and fill the fields. */ cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); if (cur == NULL) { fprintf(stderr, "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)) || (!xmlStrcmp(prev->prefix, cur->prefix))) { xmlFreeNs(cur); return(NULL); } while (prev->next != NULL) { prev = prev->next; if (((prev->prefix == NULL) && (cur->prefix == NULL)) || (!xmlStrcmp(prev->prefix, cur->prefix))) { xmlFreeNs(cur); return(NULL); } } prev->next = cur; } } return(cur);}/** * xmlNewGlobalNs: * @doc: the document carrying the namespace * @href: the URI associated * @prefix: the prefix for the namespace * * Creation of a Namespace, the old way using PI and without scoping * DEPRECATED !!! * It now create a namespace on the root element of the document if found. * Returns NULL this functionnality had been removed */xmlNsPtrxmlNewGlobalNs(xmlDocPtr doc, const xmlChar *href, const xmlChar *prefix) { xmlNodePtr root; xmlNsPtr cur; root = xmlDocGetRootElement(doc); if (root != NULL) return(xmlNewNs(root, href, prefix)); /* * if there is no root element yet, create an old Namespace type * and it will be moved to the root at save time. */ cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); if (cur == NULL) { fprintf(stderr, "xmlNewGlobalNs : malloc failed\n"); return(NULL); } memset(cur, 0, sizeof(xmlNs)); cur->type = XML_GLOBAL_NAMESPACE; if (href != NULL) cur->href = xmlStrdup(href); if (prefix != NULL) cur->prefix = xmlStrdup(prefix); /* * Add it at the end to preserve parsing order ... */ if (doc != NULL) { if (doc->oldNs == NULL) { doc->oldNs = cur; } else { xmlNsPtr prev = doc->oldNs; while (prev->next != NULL) prev = prev->next; prev->next = cur; } } return(NULL);}/** * xmlSetNs: * @node: a node in the document * @ns: a namespace pointer * * Associate a namespace to a node, a posteriori. */voidxmlSetNs(xmlNodePtr node, xmlNsPtr ns) { if (node == NULL) {#ifdef DEBUG_TREE fprintf(stderr, "xmlSetNs: node == NULL\n");#endif return; } node->ns = ns;}/** * xmlFreeNs: * @cur: the namespace pointer * * Free up the structures associated to a namespace */voidxmlFreeNs(xmlNsPtr cur) { if (cur == NULL) {#ifdef DEBUG_TREE fprintf(stderr, "xmlFreeNs : ns == NULL\n");#endif return; } if (cur->href != NULL) xmlFree((char *) cur->href); if (cur->prefix != NULL) xmlFree((char *) cur->prefix); memset(cur, -1, sizeof(xmlNs)); xmlFree(cur);}/** * xmlFreeNsList: * @cur: the first namespace pointer * * Free up all the structures associated to the chained namespaces. */voidxmlFreeNsList(xmlNsPtr cur) { xmlNsPtr next; if (cur == NULL) {#ifdef DEBUG_TREE fprintf(stderr, "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 */xmlDtdPtrxmlNewDtd(xmlDocPtr doc, const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID) { xmlDtdPtr cur; if ((doc != NULL) && (doc->extSubset != NULL)) {#ifdef DEBUG_TREE fprintf(stderr, "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) { fprintf(stderr, "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 */xmlDtdPtrxmlGetIntSubset(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 ID * @SystemID: the system ID * * Create the internal subset of a document * Returns a pointer to the new DTD structure */xmlDtdPtrxmlCreateIntSubset(xmlDocPtr doc, const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID) { xmlDtdPtr cur; if ((doc != NULL) && (xmlGetIntSubset(doc) != NULL)) {#ifdef DEBUG_TREE fprintf(stderr, "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) { fprintf(stderr, "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->intSubset = cur; cur->parent = doc; cur->doc = doc; if (doc->children == NULL) { doc->children = (xmlNodePtr) cur; doc->last = (xmlNodePtr) cur; } else { xmlNodePtr prev; prev = doc->last; prev->next = (xmlNodePtr) cur; cur->prev = prev; doc->last = (xmlNodePtr) cur; } } return(cur);}/** * xmlFreeDtd: * @cur: the DTD structure to free up * * Free a DTD structure. */voidxmlFreeDtd(xmlDtdPtr cur) { if (cur == NULL) {#ifdef DEBUG_TREE fprintf(stderr, "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); memset(cur, -1, sizeof(xmlDtd)); xmlFree(cur);}/** * xmlNewDoc: * @version: xmlChar string giving the version of XML "1.0" * * Returns a new document */xmlDocPtrxmlNewDoc(const xmlChar *version) { xmlDocPtr cur; if (version == NULL) {#ifdef DEBUG_TREE fprintf(stderr, "xmlNewDoc : version == NULL\n");#endif return(NULL); } /* * Allocate a new document and fill the fields. */ cur = (xmlDocPtr) xmlMalloc(sizeof(xmlDoc)); if (cur == NULL) { fprintf(stderr, "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; return(cur);}/** * xmlFreeDoc: * @cur: pointer to the document * @: * * Free up all the structures used by a document, tree included. */voidxmlFreeDoc(xmlDocPtr cur) { if (cur == NULL) {#ifdef DEBUG_TREE fprintf(stderr, "xmlFreeDoc : document == NULL\n");#endif return; } if (cur->version != NULL) xmlFree((char *) cur->version); if (cur->name != NULL) xmlFree((char *) cur->name);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -