📄 tree.c
字号:
} else ret->ns = NULL; if (cur->children != NULL) ret->children = xmlCopyNodeList(cur->children); 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. */xmlAttrPtrxmlCopyPropList(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 abeut the CopyNode operations ! * * They are splitted 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 xmlNodePtrxmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent);static xmlNodePtrxmlStaticCopyNode(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent, int recursive) { xmlNodePtr ret; if (node == NULL) return(NULL); /* * Allocate a new node and fill the fields. */ ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode)); if (ret == NULL) { fprintf(stderr, "xmlStaticCopyNode : malloc failed\n"); return(NULL); } memset(ret, 0, sizeof(xmlNode)); ret->type = node->type; ret->doc = doc; ret->parent = parent; if (node->name != NULL) ret->name = xmlStrdup(node->name); if ((node->content != NULL) && (node->type != XML_ENTITY_REF_NODE)) {#ifndef XML_USE_BUFFER_CONTENT ret->content = xmlStrdup(node->content);#else ret->content = xmlBufferCreateSize(xmlBufferLength(node->content)); xmlBufferSetAllocationScheme(ret->content, xmlGetBufferAllocationScheme()); xmlBufferAdd(ret->content, xmlBufferContent(node->content), xmlBufferLength(node->content));#endif } if (parent != NULL) xmlAddChild(parent, ret); 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; 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->children != NULL) ret->children = xmlStaticCopyNodeList(node->children, doc, ret); UPDATE_LAST_CHILD(ret) return(ret);}static xmlNodePtrxmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent) { xmlNodePtr ret = NULL; xmlNodePtr p = NULL,q; while (node != NULL) { q = xmlStaticCopyNode(node, doc, parent, 1); if (parent == NULL) { if (ret == NULL) ret = q; } else { if (ret == NULL) { q->prev = NULL; ret = p = q; } else { 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. */xmlNodePtrxmlCopyNode(xmlNodePtr node, int recursive) { xmlNodePtr ret; ret = xmlStaticCopyNode(node, NULL, 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(xmlNodePtr node) { xmlNodePtr ret = xmlStaticCopyNodeList(node, NULL, NULL); return(ret);}/** * xmlCopyElement: * @elem: the element * * Do a copy of the element definition. * * Returns: a new xmlElementPtr, or NULL in case of error.xmlElementPtrxmlCopyElement(xmlElementPtr elem) { xmlElementPtr ret; if (elem == NULL) return(NULL); ret = xmlNewDocElement(elem->doc, elem->ns, elem->name, elem->content); if (ret == NULL) return(NULL); if (!recursive) return(ret); if (elem->properties != NULL) ret->properties = xmlCopyPropList(elem->properties); if (elem->nsDef != NULL) ret->nsDef = xmlCopyNamespaceList(elem->nsDef); if (elem->children != NULL) ret->children = xmlCopyElementList(elem->children); return(ret);} *//** * xmlCopyDtd: * @dtd: the dtd * * Do a copy of the dtd. * * Returns: a new xmlDtdPtr, or NULL in case of error. */xmlDtdPtrxmlCopyDtd(xmlDtdPtr dtd) { xmlDtdPtr ret; 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); 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. */xmlDocPtrxmlCopyDoc(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->compression = doc->compression; ret->standalone = doc->standalone; if (!recursive) return(ret); if (doc->intSubset != NULL) ret->intSubset = xmlCopyDtd(doc->intSubset); if (doc->oldNs != NULL) ret->oldNs = xmlCopyNamespaceList(doc->oldNs); if (doc->children != NULL) ret->children = xmlStaticCopyNodeList(doc->children, ret, NULL); return(ret);}/************************************************************************ * * * Content access functions * * * ************************************************************************/ /** * 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 */xmlNodePtrxmlDocGetRootElement(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 */xmlNodePtrxmlDocSetRootElement(xmlDocPtr doc, xmlNodePtr root) { xmlNodePtr old = NULL; if (doc == NULL) return(NULL); 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; } else { xmlAddSibling(doc->children, root); } } else { xmlReplaceNode(old, root); } return(old);} /** * xmlNodeSetLang: * @cur: the node being changed * @lang: the langage description * * Set the language of a node, i.e. the values of the xml:lang * attribute. */voidxmlNodeSetLang(xmlNodePtr cur, const xmlChar *lang) { 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: return; case XML_ELEMENT_NODE: case XML_ATTRIBUTE_NODE: case XML_PI_NODE: case XML_ENTITY_REF_NODE: case XML_ENTITY_NODE: break; } xmlSetProp(cur, BAD_CAST "xml: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. */xmlChar *xmlNodeGetLang(xmlNodePtr cur) { xmlChar *lang; while (cur != NULL) { lang = xmlGetProp(cur, BAD_CAST "xml:lang"); if (lang != NULL) return(lang); cur = cur->parent; } return(NULL);} /** * xmlNodeGetSpacePreserve: * @cur: the node being checked * * Searches the language 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 inheried, 0 if "default", 1 if "preserve" */intxmlNodeGetSpacePreserve(xmlNodePtr cur) { xmlChar *space; while (cur != NULL) { space = xmlGetProp(cur, BAD_CAST "xml:space"); if (space != NULL) { if (!xmlStrcmp(space, BAD_CAST "preserve")) { xmlFree(space); return(1); } if (!xmlStrcmp(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 * * Searches the language of a node, i.e. the values of the xml:lang * attribute or the one carried by the nearest ancestor. */voidxmlNodeSetName(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: 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);} /** * 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. * * Returns a pointer to the base URL, or NULL if not found * It's up to the caller to free the memory. */xmlChar *xmlNodeGetBase(xmlDocPtr doc, xmlNodePtr cur) { xmlChar *base; 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 ((!xmlStrcmp(cur->name, BAD_CAST "html")) || (!xmlStrcmp(cur->name, BAD_CAST "HTML"))) { cur = cur->children; continue; } if ((!xmlStrcmp(cur->name, BAD_CAST "head")) || (!xmlStrcmp(cur->name, BAD_CAST "HEAD"))) { cur = cur->children; continue; } if ((!xmlStrcmp(cur->name, BAD_CAST "base")) || (!xmlStrcmp(cur->name, BAD_CAST "BASE"))) { base = xmlGetProp(cur, BAD_CAST "href"); if (base != NULL) return(base); return(xmlGetProp(cur, BAD_CAST "HREF")); } cur = cur->next; } if ((doc != NULL) && (doc->URL != NULL)) return(xmlStrdup(doc->URL)); return(NULL); } while (cur != NULL) { base = xmlGetProp(cur, BAD_CAST "xml:base"); if (base != NULL) return(base); cur = cur->parent; } if ((doc != NULL) && (doc->URL != NULL)) return(xmlStrdup(doc->URL)); return(NULL);} /** * 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 substitued. * Returns a new xmlChar * or NULL if no content is available. * It's up to the caller to free the memory. */xmlChar *xmlNodeGetContent(xmlNodePtr cur) { if (cur == NULL) return(NULL); switch (cur->type) { case XML_DOCUMENT_FRAG_NODE: case XML_ELEMENT_NODE: return(xmlNodeListGetString(cur->doc, cur->children, 1)); break; case XML_ATTRIBUTE_NODE: {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -