📄 xinclude.c
字号:
/* * read the attributes */ href = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_HREF); if (href == NULL) { href = xmlStrdup(BAD_CAST ""); /* @@@@ href is now optional */ if (href == NULL) return(-1); } parse = xmlXIncludeGetProp(ctxt, cur, XINCLUDE_PARSE); if (parse != NULL) { if (xmlStrEqual(parse, XINCLUDE_PARSE_XML)) xml = 1; else if (xmlStrEqual(parse, XINCLUDE_PARSE_TEXT)) xml = 0; else { xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_PARSE_VALUE, "invalid value %s for 'parse'\n", parse); if (href != NULL) xmlFree(href); if (parse != NULL) xmlFree(parse); return(-1); } } /* * compute the URI */ base = xmlNodeGetBase(ctxt->doc, cur); if (base == NULL) { URI = xmlBuildURI(href, ctxt->doc->URL); } else { URI = xmlBuildURI(href, base); } if (URI == NULL) { xmlChar *escbase; xmlChar *eschref; /* * Some escaping may be needed */ escbase = xmlURIEscape(base); eschref = xmlURIEscape(href); URI = xmlBuildURI(eschref, escbase); if (escbase != NULL) xmlFree(escbase); if (eschref != NULL) xmlFree(eschref); } if (URI == NULL) { xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_HREF_URI, "failed build URL\n", NULL); if (parse != NULL) xmlFree(parse); if (href != NULL) xmlFree(href); if (base != NULL) xmlFree(base); return(-1); }#ifdef DEBUG_XINCLUDE xmlGenericError(xmlGenericErrorContext, "parse: %s\n", xml ? "xml": "text"); xmlGenericError(xmlGenericErrorContext, "URI: %s\n", URI);#endif /* * Save the base for this include (saving the current one) */ oldBase = ctxt->base; ctxt->base = base; if (xml) { ret = xmlXIncludeLoadDoc(ctxt, URI, nr); /* xmlXIncludeGetFragment(ctxt, cur, URI); */ } else { ret = xmlXIncludeLoadTxt(ctxt, URI, nr); } /* * Restore the original base before checking for fallback */ ctxt->base = oldBase; if (ret < 0) { xmlNodePtr children; /* * Time to try a fallback if availble */#ifdef DEBUG_XINCLUDE xmlGenericError(xmlGenericErrorContext, "error looking for fallback\n");#endif children = cur->children; while (children != NULL) { if ((children->type == XML_ELEMENT_NODE) && (children->ns != NULL) && (xmlStrEqual(children->name, XINCLUDE_FALLBACK)) && ((xmlStrEqual(children->ns->href, XINCLUDE_NS)) || (xmlStrEqual(children->ns->href, XINCLUDE_OLD_NS)))) { ret = xmlXIncludeLoadFallback(ctxt, children, nr); if (ret == 0) break; } children = children->next; } } if (ret < 0) { xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_NO_FALLBACK, "could not load %s, and no fallback was found\n", URI); } /* * Cleanup */ if (URI != NULL) xmlFree(URI); if (parse != NULL) xmlFree(parse); if (href != NULL) xmlFree(href); if (base != NULL) xmlFree(base); return(0);}/** * xmlXIncludeIncludeNode: * @ctxt: an XInclude context * @nr: the node number * * Inplement the infoset replacement for the given node * * Returns 0 if substitution succeeded, -1 if some processing failed */static intxmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt, int nr) { xmlNodePtr cur, end, list, tmp; if (ctxt == NULL) return(-1); if ((nr < 0) || (nr >= ctxt->incNr)) return(-1); cur = ctxt->incTab[nr]->ref; if (cur == NULL) return(-1); /* * If we stored an XPointer a late computation may be needed */ if ((ctxt->incTab[nr]->inc == NULL) && (ctxt->incTab[nr]->xptr != NULL)) { ctxt->incTab[nr]->inc = xmlXIncludeCopyXPointer(ctxt, ctxt->doc, ctxt->doc, ctxt->incTab[nr]->xptr); xmlXPathFreeObject(ctxt->incTab[nr]->xptr); ctxt->incTab[nr]->xptr = NULL; } list = ctxt->incTab[nr]->inc; ctxt->incTab[nr]->inc = NULL; /* * Check against the risk of generating a multi-rooted document */ if ((cur->parent != NULL) && (cur->parent->type != XML_ELEMENT_NODE)) { int nb_elem = 0; tmp = list; while (tmp != NULL) { if (tmp->type == XML_ELEMENT_NODE) nb_elem++; tmp = tmp->next; } if (nb_elem > 1) { xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_MULTIPLE_ROOT, "XInclude error: would result in multiple root nodes\n", NULL); return(-1); } } if (ctxt->parseFlags & XML_PARSE_NOXINCNODE) { /* * Add the list of nodes */ while (list != NULL) { end = list; list = list->next; xmlAddPrevSibling(cur, end); } xmlUnlinkNode(cur); xmlFreeNode(cur); } else { /* * Change the current node as an XInclude start one, and add an * XInclude end one */ cur->type = XML_XINCLUDE_START; end = xmlNewDocNode(cur->doc, cur->ns, cur->name, NULL); if (end == NULL) { xmlXIncludeErr(ctxt, ctxt->incTab[nr]->ref, XML_XINCLUDE_BUILD_FAILED, "failed to build node\n", NULL); return(-1); } end->type = XML_XINCLUDE_END; xmlAddNextSibling(cur, end); /* * Add the list of nodes */ while (list != NULL) { cur = list; list = list->next; xmlAddPrevSibling(end, cur); } } return(0);}/** * xmlXIncludeTestNode: * @ctxt: the XInclude processing context * @node: an XInclude node * * test if the node is an XInclude node * * Returns 1 true, 0 otherwise */static intxmlXIncludeTestNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) { if (node == NULL) return(0); if (node->type != XML_ELEMENT_NODE) return(0); if (node->ns == NULL) return(0); if ((xmlStrEqual(node->ns->href, XINCLUDE_NS)) || (xmlStrEqual(node->ns->href, XINCLUDE_OLD_NS))) { if (xmlStrEqual(node->ns->href, XINCLUDE_OLD_NS)) { if (ctxt->legacy == 0) {#if 0 /* wait for the XML Core Working Group to get something stable ! */ xmlXIncludeWarn(ctxt, node, XML_XINCLUDE_DEPRECATED_NS, "Deprecated XInclude namespace found, use %s", XINCLUDE_NS);#endif ctxt->legacy = 1; } } if (xmlStrEqual(node->name, XINCLUDE_NODE)) { xmlNodePtr child = node->children; int nb_fallback = 0; while (child != NULL) { if ((child->type == XML_ELEMENT_NODE) && (child->ns != NULL) && ((xmlStrEqual(child->ns->href, XINCLUDE_NS)) || (xmlStrEqual(child->ns->href, XINCLUDE_OLD_NS)))) { if (xmlStrEqual(child->name, XINCLUDE_NODE)) { xmlXIncludeErr(ctxt, node, XML_XINCLUDE_INCLUDE_IN_INCLUDE, "%s has an 'include' child\n", XINCLUDE_NODE); return(0); } if (xmlStrEqual(child->name, XINCLUDE_FALLBACK)) { nb_fallback++; } } child = child->next; } if (nb_fallback > 1) { xmlXIncludeErr(ctxt, node, XML_XINCLUDE_FALLBACKS_IN_INCLUDE, "%s has multiple fallback children\n", XINCLUDE_NODE); return(0); } return(1); } if (xmlStrEqual(node->name, XINCLUDE_FALLBACK)) { if ((node->parent == NULL) || (node->parent->type != XML_ELEMENT_NODE) || (node->parent->ns == NULL) || ((!xmlStrEqual(node->parent->ns->href, XINCLUDE_NS)) && (!xmlStrEqual(node->parent->ns->href, XINCLUDE_OLD_NS))) || (!xmlStrEqual(node->parent->name, XINCLUDE_NODE))) { xmlXIncludeErr(ctxt, node, XML_XINCLUDE_FALLBACK_NOT_IN_INCLUDE, "%s is not the child of an 'include'\n", XINCLUDE_FALLBACK); } } } return(0);}/** * xmlXIncludeDoProcess: * @ctxt: the XInclude processing context * @doc: an XML document * @tree: the top of the tree to process * * Implement the XInclude substitution on the XML document @doc * * Returns 0 if no substitution were done, -1 if some processing failed * or the number of substitutions done. */static intxmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr tree) { xmlNodePtr cur; int ret = 0; int i, start; if ((doc == NULL) || (tree == NULL)) return(-1); if (ctxt == NULL) return(-1); if (doc->URL != NULL) { ret = xmlXIncludeURLPush(ctxt, doc->URL); if (ret < 0) return(-1); } start = ctxt->incNr; /* * First phase: lookup the elements in the document */ cur = tree; if (xmlXIncludeTestNode(ctxt, cur) == 1) xmlXIncludePreProcessNode(ctxt, cur); while ((cur != NULL) && (cur != tree->parent)) { /* TODO: need to work on entities -> stack */ if ((cur->children != NULL) && (cur->children->type != XML_ENTITY_DECL) && (cur->children->type != XML_XINCLUDE_START) && (cur->children->type != XML_XINCLUDE_END)) { cur = cur->children; if (xmlXIncludeTestNode(ctxt, cur)) xmlXIncludePreProcessNode(ctxt, cur); } else if (cur->next != NULL) { cur = cur->next; if (xmlXIncludeTestNode(ctxt, cur)) xmlXIncludePreProcessNode(ctxt, cur); } else { if (cur == tree) break; do { cur = cur->parent; if ((cur == NULL) || (cur == tree->parent)) break; /* do */ if (cur->next != NULL) { cur = cur->next; if (xmlXIncludeTestNode(ctxt, cur)) xmlXIncludePreProcessNode(ctxt, cur); break; /* do */ } } while (cur != NULL); } } /* * Second Phase : collect the infosets fragments */ for (i = start;i < ctxt->incNr; i++) { xmlXIncludeLoadNode(ctxt, i); ret++; } /* * Third phase: extend the original document infoset. * * Originally we bypassed the inclusion if there were any errors * encountered on any of the XIncludes. A bug was raised (bug * 132588) requesting that we output the XIncludes without error, * so the check for inc!=NULL || xptr!=NULL was put in. This may * give some other problems in the future, but for now it seems to * work ok. * */ for (i = ctxt->incBase;i < ctxt->incNr; i++) { if ((ctxt->incTab[i]->inc != NULL) || (ctxt->incTab[i]->xptr != NULL) || (ctxt->incTab[i]->emptyFb != 0)) /* (empty fallback) */ xmlXIncludeIncludeNode(ctxt, i); } if (doc->URL != NULL) xmlXIncludeURLPop(ctxt); return(ret);}/** * xmlXIncludeSetFlags: * @ctxt: an XInclude processing context * @flags: a set of xmlParserOption used for parsing XML includes * * Set the flags used for further processing of XML resources. * * Returns 0 in case of success and -1 in case of error. */intxmlXIncludeSetFlags(xmlXIncludeCtxtPtr ctxt, int flags) { if (ctxt == NULL) return(-1); ctxt->parseFlags = flags; return(0);} /** * xmlXIncludeProcessFlagsData: * @doc: an XML document * @flags: a set of xmlParserOption used for parsing XML includes * @data: application data that will be passed to the parser context * in the _private field of the parser context(s) * * Implement the XInclude substitution on the XML document @doc * * Returns 0 if no substitution were done, -1 if some processing failed * or the number of substitutions done. */intxmlXIncludeProcessFlagsData(xmlDocPtr doc, int flags, void *data) { xmlXIncludeCtxtPtr ctxt; xmlNodePtr tree; int ret = 0; if (doc == NULL) return(-1); tree = xmlDocGetRootElement(doc); if (tree == NULL) return(-1); ctxt = xmlXIncludeNewContext(doc); if (ctxt == NULL) return(-1); ctxt->_private = data; ctxt->base = xmlStrdup((xmlChar *)doc->URL); xmlXIncludeSetFlags(ctxt, flags); ret = xmlXIncludeDoProcess(ctxt, doc, tree); if ((ret >= 0) && (ctxt->nbErrors > 0)) ret = -1; xmlXIncludeFreeContext(ctxt); return(ret);}/** * xmlXIncludeProcessFlags: * @doc: an XML document * @flags: a set of xmlParserOption used for parsing XML includes * * Implement the XInclude substitution on the XML document @doc * * Returns 0 if no substitution were done, -1 if some processing failed * or the number of substitutions done. */intxmlXIncludeProcessFlags(xmlDocPtr doc, int flags) { return xmlXIncludeProcessFlagsData(doc, flags, NULL);}/** * xmlXIncludeProcess: * @doc: an XML document * * Implement the XInclude substitution on the XML document @doc * * Returns 0 if no substitution were done, -1 if some processing failed * or the number of substitutions done. */intxmlXIncludeProcess(xmlDocPtr doc) { return(xmlXIncludeProcessFlags(doc, 0));}/** * xmlXIncludeProcessTreeFlags: * @tree: a node in an XML document * @flags: a set of xmlParserOption used for parsing XML includes * * Implement the XInclude substitution for the given subtree * * Returns 0 if no substitution were done, -1 if some processing failed * or the number of substitutions done. */intxmlXIncludeProcessTreeFlags(xmlNodePtr tree, int flags) { xmlXIncludeCtxtPtr ctxt; int ret = 0; if ((tree == NULL) || (tree->doc =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -