#define IN_LIBXML
#include "libxml.h"
#include <string.h>
#include <libxml/xmlmemory.h>
#include <libxml/tree.h>
#include <libxml/parser.h>
#include <libxml/uri.h>
#include <libxml/xpointer.h>
#include <libxml/parserInternals.h>
#include <libxml/xmlerror.h>
#include <libxml/globals.h>
#ifdef LIBXML_XINCLUDE_ENABLED
#include <libxml/xinclude.h>
#define XINCLUDE_NODE (const xmlChar *) "include"
#define XINCLUDE_HREF (const xmlChar *) "href"
#define XINCLUDE_PARSE (const xmlChar *) "parse"
#define XINCLUDE_PARSE_XML (const xmlChar *) "xml"
#define XINCLUDE_PARSE_TEXT (const xmlChar *) "text"
#ifdef DEBUG_XINCLUDE
#ifdef LIBXML_DEBUG_ENABLED
#include <libxml/debugXML.h>
#endif
#endif
typedef
xmlChar *xmlURL;
typedef
struct
_xmlXIncludeCtxt xmlXIncludeCtxt;
typedef
xmlXIncludeCtxt *xmlXIncludeCtxtPtr;
struct
_xmlXIncludeCtxt {
xmlDocPtr doc;
int
incNr;
int
incMax;
xmlNodePtr *incTab;
xmlNodePtr *repTab;
int
docNr;
int
docMax;
xmlDocPtr *docTab;
xmlURL *urlTab;
int
txtNr;
int
txtMax;
xmlNodePtr *txtTab;
xmlURL *txturlTab;
};
static
int
xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc);
static
xmlXIncludeCtxtPtr
xmlXIncludeNewContext(xmlDocPtr doc) {
xmlXIncludeCtxtPtr ret;
if
(doc == NULL)
return
(NULL);
ret = (xmlXIncludeCtxtPtr) xmlMalloc(
sizeof
(xmlXIncludeCtxt));
if
(ret == NULL)
return
(NULL);
memset
(ret, 0,
sizeof
(xmlXIncludeCtxt));
ret->doc = doc;
ret->incNr = 0;
ret->incMax = 0;
ret->incTab = NULL;
ret->repTab = NULL;
ret->docNr = 0;
ret->docMax = 0;
ret->docTab = NULL;
ret->urlTab = NULL;
return
(ret);
}
static
void
xmlXIncludeFreeContext(xmlXIncludeCtxtPtr ctxt) {
int
i;
if
(ctxt == NULL)
return
;
for
(i = 0;i < ctxt->docNr;i++) {
xmlFreeDoc(ctxt->docTab[i]);
if
(ctxt->urlTab[i] != NULL)
xmlFree(ctxt->urlTab[i]);
}
for
(i = 0;i < ctxt->txtNr;i++) {
if
(ctxt->txturlTab[i] != NULL)
xmlFree(ctxt->txturlTab[i]);
}
if
(ctxt->incTab != NULL)
xmlFree(ctxt->incTab);
if
(ctxt->repTab != NULL)
xmlFree(ctxt->repTab);
if
(ctxt->urlTab != NULL)
xmlFree(ctxt->urlTab);
if
(ctxt->docTab != NULL)
xmlFree(ctxt->docTab);
if
(ctxt->txtTab != NULL)
xmlFree(ctxt->txtTab);
if
(ctxt->txturlTab != NULL)
xmlFree(ctxt->txturlTab);
xmlFree(ctxt);
}
static
void
xmlXIncludeAddNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
if
(ctxt->incMax == 0) {
ctxt->incMax = 4;
ctxt->incTab = (xmlNodePtr *) xmlMalloc(ctxt->incMax *
sizeof
(ctxt->incTab[0]));
if
(ctxt->incTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc failed !\n"
);
return
;
}
ctxt->repTab = (xmlNodePtr *) xmlMalloc(ctxt->incMax *
sizeof
(ctxt->repTab[0]));
if
(ctxt->repTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc failed !\n"
);
return
;
}
}
if
(ctxt->incNr >= ctxt->incMax) {
ctxt->incMax *= 2;
ctxt->incTab = (xmlNodePtr *) xmlRealloc(ctxt->incTab,
ctxt->incMax *
sizeof
(ctxt->incTab[0]));
if
(ctxt->incTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc failed !\n"
);
return
;
}
ctxt->repTab = (xmlNodePtr *) xmlRealloc(ctxt->repTab,
ctxt->incMax *
sizeof
(ctxt->repTab[0]));
if
(ctxt->repTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc failed !\n"
);
return
;
}
}
ctxt->incTab[ctxt->incNr] = node;
ctxt->repTab[ctxt->incNr] = NULL;
ctxt->incNr++;
}
static
void
xmlXIncludeAddDoc(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc,
const
xmlURL url) {
xmlXIncludeCtxtPtr newctxt;
int
i;
if
(ctxt->docMax == 0) {
ctxt->docMax = 4;
ctxt->docTab = (xmlDocPtr *) xmlMalloc(ctxt->docMax *
sizeof
(ctxt->docTab[0]));
if
(ctxt->docTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc failed !\n"
);
return
;
}
ctxt->urlTab = (xmlURL *) xmlMalloc(ctxt->docMax *
sizeof
(ctxt->urlTab[0]));
if
(ctxt->urlTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc failed !\n"
);
return
;
}
}
if
(ctxt->docNr >= ctxt->docMax) {
ctxt->docMax *= 2;
ctxt->docTab = (xmlDocPtr *) xmlRealloc(ctxt->docTab,
ctxt->docMax *
sizeof
(ctxt->docTab[0]));
if
(ctxt->docTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc failed !\n"
);
return
;
}
ctxt->urlTab = (xmlURL *) xmlRealloc(ctxt->urlTab,
ctxt->docMax *
sizeof
(ctxt->urlTab[0]));
if
(ctxt->urlTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc failed !\n"
);
return
;
}
}
ctxt->docTab[ctxt->docNr] = doc;
ctxt->urlTab[ctxt->docNr] = xmlStrdup(url);
ctxt->docNr++;
newctxt = xmlXIncludeNewContext(doc);
if
(newctxt != NULL) {
newctxt->docMax = ctxt->docMax;
newctxt->docNr = ctxt->docNr;
newctxt->docTab = (xmlDocPtr *) xmlMalloc(newctxt->docMax *
sizeof
(newctxt->docTab[0]));
if
(newctxt->docTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc failed !\n"
);
xmlFree(newctxt);
return
;
}
newctxt->urlTab = (xmlURL *) xmlMalloc(newctxt->docMax *
sizeof
(newctxt->urlTab[0]));
if
(ctxt->urlTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc failed !\n"
);
xmlFree(newctxt);
return
;
}
for
(i = 0;i < ctxt->docNr;i++) {
newctxt->docTab[i] = ctxt->docTab[i];
newctxt->urlTab[i] = ctxt->urlTab[i];
}
xmlXIncludeDoProcess(newctxt, doc);
for
(i = 0;i < ctxt->docNr;i++) {
newctxt->docTab[i] = NULL;
newctxt->urlTab[i] = NULL;
}
xmlXIncludeFreeContext(newctxt);
}
}
static
void
xmlXIncludeAddTxt(xmlXIncludeCtxtPtr ctxt, xmlNodePtr txt,
const
xmlURL url) {
if
(ctxt->txtMax == 0) {
ctxt->txtMax = 4;
ctxt->txtTab = (xmlNodePtr *) xmlMalloc(ctxt->txtMax *
sizeof
(ctxt->txtTab[0]));
if
(ctxt->txtTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc failed !\n"
);
return
;
}
ctxt->txturlTab = (xmlURL *) xmlMalloc(ctxt->txtMax *
sizeof
(ctxt->txturlTab[0]));
if
(ctxt->txturlTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"malloc failed !\n"
);
return
;
}
}
if
(ctxt->txtNr >= ctxt->txtMax) {
ctxt->txtMax *= 2;
ctxt->txtTab = (xmlNodePtr *) xmlRealloc(ctxt->txtTab,
ctxt->txtMax *
sizeof
(ctxt->txtTab[0]));
if
(ctxt->txtTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc failed !\n"
);
return
;
}
ctxt->txturlTab = (xmlURL *) xmlRealloc(ctxt->txturlTab,
ctxt->txtMax *
sizeof
(ctxt->urlTab[0]));
if
(ctxt->txturlTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"realloc failed !\n"
);
return
;
}
}
ctxt->txtTab[ctxt->txtNr] = txt;
ctxt->txturlTab[ctxt->txtNr] = xmlStrdup(url);
ctxt->txtNr++;
}
static
xmlNodePtr
xmlXIncludeCopyNode(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
xmlDocPtr source, xmlNodePtr elem) {
xmlNodePtr result = NULL;
if
((ctxt == NULL) || (target == NULL) || (source == NULL) ||
(elem == NULL))
return
(NULL);
if
(elem->type == XML_DTD_NODE)
return
(NULL);
result = xmlDocCopyNode(elem, target, 1);
return
(result);
}
static
xmlNodePtr
xmlXIncludeCopyNodeList(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
xmlDocPtr source, xmlNodePtr elem) {
xmlNodePtr cur, res, result = NULL, last = NULL;
if
((ctxt == NULL) || (target == NULL) || (source == NULL) ||
(elem == NULL))
return
(NULL);
cur = elem;
while
(cur != NULL) {
res = xmlXIncludeCopyNode(ctxt, target, source, cur);
if
(res != NULL) {
if
(result == NULL) {
result = last = res;
}
else
{
last->next = res;
res->prev = last;
last = res;
}
}
cur = cur->next;
}
return
(result);
}
static
xmlNodePtr
xmlXIncludeGetNthChild(xmlNodePtr cur,
int
no) {
int
i;
if
(cur == NULL)
return
(cur);
cur = cur->children;
for
(i = 0;i <= no;cur = cur->next) {
if
(cur == NULL)
return
(cur);
if
((cur->type == XML_ELEMENT_NODE) ||
(cur->type == XML_DOCUMENT_NODE) ||
(cur->type == XML_HTML_DOCUMENT_NODE)) {
i++;
if
(i == no)
break
;
}
}
return
(cur);
}
xmlNodePtr xmlXPtrAdvanceNode(xmlNodePtr cur);
static
xmlNodePtr
xmlXIncludeCopyRange(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
xmlDocPtr source, xmlXPathObjectPtr range) {
xmlNodePtr list = NULL, last = NULL, parent = NULL, tmp;
xmlNodePtr start, cur, end;
int
index1, index2;
if
((ctxt == NULL) || (target == NULL) || (source == NULL) ||
(range == NULL))
return
(NULL);
if
(range->type != XPATH_RANGE)
return
(NULL);
start = (xmlNodePtr) range->user;
if
(start == NULL)
return
(NULL);
end = range->user2;
if
(end == NULL)
return
(xmlDocCopyNode(start, target, 1));
cur = start;
index1 = range->index;
index2 = range->index2;
while
(cur != NULL) {
if
(cur == end) {
if
(cur->type == XML_TEXT_NODE) {
const
xmlChar *content = cur->content;
int
len;
if
(content == NULL) {
tmp = xmlNewTextLen(NULL, 0);
}
else
{
len = index2;
if
((cur == start) && (index1 > 1)) {
content += (index1 - 1);
len -= (index1 - 1);
index1 = 0;
}
else
{
len = index2;
}
tmp = xmlNewTextLen(content, len);
}
if
(list == NULL)
return
(tmp);
if
(last != NULL)
xmlAddNextSibling(last, tmp);
else
xmlAddChild(parent, tmp);
return
(list);
}
else
{
tmp = xmlDocCopyNode(cur, target, 0);
if
(list == NULL)
list = tmp;
else
{
if
(last != NULL)
xmlAddNextSibling(last, tmp);
else
xmlAddChild(parent, tmp);
}
last = NULL;
parent = tmp;
if
(index2 > 1) {
end = xmlXIncludeGetNthChild(cur, index2 - 1);
index2 = 0;
}
if
((cur == start) && (index1 > 1)) {
cur = xmlXIncludeGetNthChild(cur, index1 - 1);
index1 = 0;
}
else
{
cur = cur->children;
}
continue
;
}
}
else
if
((cur == start) &&
(list == NULL)
) {
if
((cur->type == XML_TEXT_NODE) ||
(cur->type == XML_CDATA_SECTION_NODE)) {
const
xmlChar *content = cur->content;
if
(content == NULL) {
tmp = xmlNewTextLen(NULL, 0);
}
else
{
if
(index1 > 1) {
content += (index1 - 1);
}
tmp = xmlNewText(content);
}
last = list = tmp;
}
else
{
if
((cur == start) && (index1 > 1)) {
tmp = xmlDocCopyNode(cur, target, 0);
list = tmp;
parent = tmp;
last = NULL;
cur = xmlXIncludeGetNthChild(cur, index1 - 1);
index1 = 0;
continue
;
}
tmp = xmlDocCopyNode(cur, target, 1);
list = tmp;
parent = NULL;
last = tmp;
}
}
else
{
tmp = NULL;
switch
(cur->type) {
case
XML_DTD_NODE:
case
XML_ELEMENT_DECL:
case
XML_ATTRIBUTE_DECL:
case
XML_ENTITY_NODE:
break
;
case
XML_ENTITY_DECL:
break
;
case
XML_XINCLUDE_START:
case
XML_XINCLUDE_END:
break
;
case
XML_ATTRIBUTE_NODE:
break
;
default
:
tmp = xmlDocCopyNode(cur, target, 1);
break
;
}
if
(tmp != NULL) {
if
((list == NULL) || ((last == NULL) && (parent == NULL))) {
return
(NULL);
}
if
(last != NULL)
xmlAddNextSibling(last, tmp);
else
{
xmlAddChild(parent, tmp);
last = tmp;
}
}
}
if
((list == NULL) || ((last == NULL) && (parent == NULL))) {
return
(NULL);
}
cur = xmlXPtrAdvanceNode(cur);
}
return
(list);
}
static
xmlNodePtr
xmlXIncludeCopyXPointer(xmlXIncludeCtxtPtr ctxt, xmlDocPtr target,
xmlDocPtr source, xmlXPathObjectPtr obj) {
xmlNodePtr list = NULL, last = NULL;
int
i;
if
((ctxt == NULL) || (target == NULL) || (source == NULL) ||
(obj == NULL))
return
(NULL);
switch
(obj->type) {
case
XPATH_NODESET: {
xmlNodeSetPtr set = obj->nodesetval;
if
(set == NULL)
return
(NULL);
for
(i = 0;i < set->nodeNr;i++) {
if
(set->nodeTab[i] == NULL)
continue
;
switch
(set->nodeTab[i]->type) {
case
XML_TEXT_NODE:
case
XML_CDATA_SECTION_NODE:
case
XML_ELEMENT_NODE:
case
XML_ENTITY_REF_NODE:
case
XML_ENTITY_NODE:
case
XML_PI_NODE:
case
XML_COMMENT_NODE:
case
XML_DOCUMENT_NODE:
case
XML_HTML_DOCUMENT_NODE:
#ifdef LIBXML_DOCB_ENABLED
case
XML_DOCB_DOCUMENT_NODE:
#endif
case
XML_XINCLUDE_START:
case
XML_XINCLUDE_END:
break
;
case
XML_ATTRIBUTE_NODE:
case
XML_NAMESPACE_DECL:
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:
continue
;
}
if
(last == NULL)
list = last = xmlXIncludeCopyNode(ctxt, target, source,
set->nodeTab[i]);
else
{
xmlAddNextSibling(last,
xmlXIncludeCopyNode(ctxt, target, source,
set->nodeTab[i]));
if
(last->next != NULL)
last = last->next;
}
}
break
;
}
case
XPATH_LOCATIONSET: {
xmlLocationSetPtr set = (xmlLocationSetPtr) obj->user;
if
(set == NULL)
return
(NULL);
for
(i = 0;i < set->locNr;i++) {
if
(last == NULL)
list = last = xmlXIncludeCopyXPointer(ctxt, target, source,
set->locTab[i]);
else
xmlAddNextSibling(last,
xmlXIncludeCopyXPointer(ctxt, target, source,
set->locTab[i]));
if
(last != NULL) {
while
(last->next != NULL)
last = last->next;
}
}
break
;
}
case
XPATH_RANGE:
return
(xmlXIncludeCopyRange(ctxt, target, source, obj));
case
XPATH_POINT:
break
;
default
:
break
;
}
return
(list);
}
static
void
xmlXIncludeLoadDoc(xmlXIncludeCtxtPtr ctxt,
const
xmlChar *url,
int
nr) {
xmlDocPtr doc;
xmlURIPtr uri;
xmlChar *URL;
xmlChar *fragment = NULL;
int
i;
uri = xmlParseURI((
const
char
*)url);
if
(uri == NULL) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: invalid value URI %s\n"
, url);
return
;
}
if
(uri->fragment != NULL) {
fragment = (xmlChar *) uri->fragment;
uri->fragment = NULL;
}
URL = xmlSaveUri(uri);
xmlFreeURI(uri);
if
(URL == NULL) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: invalid value URI %s\n"
, url);
if
(fragment != NULL)
xmlFree(fragment);
return
;
}
if
((URL[0] == 0) || (URL[0] ==
'#'
)) {
doc = NULL;
goto
loaded;
}
for
(i = 0; i < ctxt->docNr; i++) {
if
(xmlStrEqual(URL, ctxt->urlTab[i])) {
doc = ctxt->docTab[i];
goto
loaded;
}
}
doc = xmlParseFile((
const
char
*)URL);
if
(doc == NULL) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: could not load %s\n"
, URL);
xmlFree(URL);
if
(fragment != NULL)
xmlFree(fragment);
return
;
}
xmlXIncludeAddDoc(ctxt, doc, URL);
loaded:
if
(fragment == NULL) {
if
(doc == NULL)
{
ctxt->repTab[nr] = xmlCopyNodeList(ctxt->doc->children);
}
else
{
ctxt->repTab[nr] = xmlXIncludeCopyNodeList(ctxt, ctxt->doc,
doc, doc->children);
}
}
else
{
xmlXPathObjectPtr xptr;
xmlXPathContextPtr xptrctxt;
xmlNodeSetPtr set;
if
(doc == NULL) {
xptrctxt = xmlXPtrNewContext(ctxt->doc, ctxt->incTab[nr], NULL);
}
else
{
xptrctxt = xmlXPtrNewContext(doc, NULL, NULL);
}
if
(xptrctxt == NULL) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: could create XPointer context\n"
);
xmlFree(URL);
xmlFree(fragment);
return
;
}
xptr = xmlXPtrEval(fragment, xptrctxt);
if
(xptr == NULL) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: XPointer evaluation failed: #%s\n"
,
fragment);
xmlXPathFreeContext(xptrctxt);
xmlFree(URL);
xmlFree(fragment);
return
;
}
switch
(xptr->type) {
case
XPATH_UNDEFINED:
case
XPATH_BOOLEAN:
case
XPATH_NUMBER:
case
XPATH_STRING:
case
XPATH_POINT:
case
XPATH_USERS:
case
XPATH_XSLT_TREE:
xmlGenericError(xmlGenericErrorContext,
"XInclude: XPointer is not a range: #%s\n"
,
fragment);
xmlXPathFreeContext(xptrctxt);
xmlFree(URL);
xmlFree(fragment);
return
;
case
XPATH_NODESET:
case
XPATH_RANGE:
case
XPATH_LOCATIONSET:
break
;
}
set = xptr->nodesetval;
if
(set != NULL) {
for
(i = 0;i < set->nodeNr;i++) {
if
(set->nodeTab[i] == NULL)
continue
;
switch
(set->nodeTab[i]->type) {
case
XML_TEXT_NODE:
case
XML_CDATA_SECTION_NODE:
case
XML_ELEMENT_NODE:
case
XML_ENTITY_REF_NODE:
case
XML_ENTITY_NODE:
case
XML_PI_NODE:
case
XML_COMMENT_NODE:
case
XML_DOCUMENT_NODE:
case
XML_HTML_DOCUMENT_NODE:
#ifdef LIBXML_DOCB_ENABLED
case
XML_DOCB_DOCUMENT_NODE:
#endif
continue
;
case
XML_ATTRIBUTE_NODE:
xmlGenericError(xmlGenericErrorContext,
"XInclude: XPointer selects an attribute: #%s\n"
,
fragment);
set->nodeTab[i] = NULL;
continue
;
case
XML_NAMESPACE_DECL:
xmlGenericError(xmlGenericErrorContext,
"XInclude: XPointer selects a namespace: #%s\n"
,
fragment);
set->nodeTab[i] = NULL;
continue
;
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_XINCLUDE_START:
case
XML_XINCLUDE_END:
xmlGenericError(xmlGenericErrorContext,
"XInclude: XPointer selects unexpected nodes: #%s\n"
,
fragment);
set->nodeTab[i] = NULL;
set->nodeTab[i] = NULL;
continue
;
}
}
}
ctxt->repTab[nr] = xmlXIncludeCopyXPointer(ctxt, ctxt->doc, doc, xptr);
xmlXPathFreeObject(xptr);
xmlXPathFreeContext(xptrctxt);
xmlFree(fragment);
}
xmlFree(URL);
}
static
void
xmlXIncludeLoadTxt(xmlXIncludeCtxtPtr ctxt,
const
xmlChar *url,
int
nr) {
xmlParserInputBufferPtr buf;
xmlNodePtr node;
xmlURIPtr uri;
xmlChar *URL;
int
i;
uri = xmlParseURI((
const
char
*)url);
if
(uri == NULL) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: invalid value URI %s\n"
, url);
return
;
}
if
(uri->fragment != NULL) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: fragment identifier forbidden for text: %s\n"
,
uri->fragment);
xmlFreeURI(uri);
return
;
}
URL = xmlSaveUri(uri);
xmlFreeURI(uri);
if
(URL == NULL) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: invalid value URI %s\n"
, url);
return
;
}
if
(URL[0] == 0) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: text serialization of document not available\n"
);
xmlFree(URL);
return
;
}
for
(i = 0; i < ctxt->txtNr; i++) {
if
(xmlStrEqual(URL, ctxt->txturlTab[i])) {
node = xmlCopyNode(ctxt->txtTab[i], 1);
goto
loaded;
}
}
buf = xmlParserInputBufferCreateFilename((
const
char
*)URL, 0);
if
(buf == NULL) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: could not load %s\n"
, URL);
xmlFree(URL);
return
;
}
node = xmlNewText(NULL);
while
(xmlParserInputBufferRead(buf, 128) > 0) {
int
len;
const
xmlChar *content;
content = xmlBufferContent(buf->buffer);
len = xmlBufferLength(buf->buffer);
for
(i = 0;i < len; i++) {
if
(!IS_CHAR(content[i])) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: %s contains invalid char %d\n"
, URL, content[i]);
}
else
{
xmlNodeAddContentLen(node, &content[i], 1);
}
}
xmlBufferShrink(buf->buffer, len);
}
xmlFreeParserInputBuffer(buf);
xmlXIncludeAddTxt(ctxt, node, URL);
loaded:
ctxt->repTab[nr] = node;
xmlFree(URL);
}
static
xmlNodePtr
xmlXIncludePreProcessNode(xmlXIncludeCtxtPtr ctxt, xmlNodePtr node) {
xmlXIncludeAddNode(ctxt, node);
return
(0);
}
static
int
xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt,
int
nr) {
xmlNodePtr cur;
xmlChar *href;
xmlChar *parse;
xmlChar *base;
xmlChar *URI;
int
xml = 1;
if
(ctxt == NULL)
return
(-1);
if
((nr < 0) || (nr >= ctxt->incNr))
return
(-1);
cur = ctxt->incTab[nr];
if
(cur == NULL)
return
(-1);
#ifdef DEBUG_XINCLUDE
xmlDebugDumpNode(stdout, cur, 0);
#endif
href = xmlGetNsProp(cur, XINCLUDE_NS, XINCLUDE_HREF);
if
(href == NULL) {
href = xmlGetProp(cur, XINCLUDE_HREF);
if
(href == NULL) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: no href\n"
);
return
(-1);
}
}
parse = xmlGetNsProp(cur, XINCLUDE_NS, XINCLUDE_PARSE);
if
(parse == NULL) {
parse = xmlGetProp(cur, XINCLUDE_PARSE);
}
if
(parse != NULL) {
if
(xmlStrEqual(parse, XINCLUDE_PARSE_XML))
xml = 1;
else
if
(xmlStrEqual(parse, XINCLUDE_PARSE_TEXT))
xml = 0;
else
{
xmlGenericError(xmlGenericErrorContext,
"XInclude: invalid value %s for %s\n"
,
parse, XINCLUDE_PARSE);
if
(href != NULL)
xmlFree(href);
if
(parse != NULL)
xmlFree(parse);
return
(-1);
}
}
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;
escbase = xmlURIEscape(base);
eschref = xmlURIEscape(href);
URI = xmlBuildURI(eschref, escbase);
if
(escbase != NULL)
xmlFree(escbase);
if
(eschref != NULL)
xmlFree(eschref);
}
if
(URI == NULL) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: failed build URL\n"
);
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
if
(xml) {
xmlXIncludeLoadDoc(ctxt, URI, nr);
}
else
{
xmlXIncludeLoadTxt(ctxt, URI, nr);
}
if
(URI != NULL)
xmlFree(URI);
if
(parse != NULL)
xmlFree(parse);
if
(href != NULL)
xmlFree(href);
if
(base != NULL)
xmlFree(base);
return
(0);
}
static
int
xmlXIncludeIncludeNode(xmlXIncludeCtxtPtr ctxt,
int
nr) {
xmlNodePtr cur, end, list;
if
(ctxt == NULL)
return
(-1);
if
((nr < 0) || (nr >= ctxt->incNr))
return
(-1);
cur = ctxt->incTab[nr];
if
(cur == NULL)
return
(-1);
cur->type = XML_XINCLUDE_START;
end = xmlNewNode(cur->ns, cur->name);
if
(end == NULL) {
xmlGenericError(xmlGenericErrorContext,
"XInclude: failed to build node\n"
);
return
(-1);
}
end->type = XML_XINCLUDE_END;
xmlAddNextSibling(cur, end);
list = ctxt->repTab[nr];
ctxt->repTab[nr] = NULL;
while
(list != NULL) {
cur = list;
list = list->next;
xmlAddPrevSibling(end, cur);
}
return
(0);
}
static
int
xmlXIncludeTestNode(xmlNodePtr node) {
if
(node == NULL)
return
(0);
if
(node->ns == NULL)
return
(0);
if
((xmlStrEqual(node->name, XINCLUDE_NODE)) &&
(xmlStrEqual(node->ns->href, XINCLUDE_NS)))
return
(1);
return
(0);
}
static
int
xmlXIncludeDoProcess(xmlXIncludeCtxtPtr ctxt, xmlDocPtr doc) {
xmlNodePtr cur;
int
ret = 0;
int
i;
if
(doc == NULL)
return
(-1);
if
(ctxt == NULL)
return
(-1);
cur = xmlDocGetRootElement(doc);
if
(xmlXIncludeTestNode(cur))
xmlXIncludePreProcessNode(ctxt, cur);
while
(cur != NULL) {
if
((cur->children != NULL) &&
(cur->children->type != XML_ENTITY_DECL)) {
cur = cur->children;
if
(xmlXIncludeTestNode(cur))
xmlXIncludePreProcessNode(ctxt, cur);
}
else
if
(cur->next != NULL) {
cur = cur->next;
if
(xmlXIncludeTestNode(cur))
xmlXIncludePreProcessNode(ctxt, cur);
}
else
{
do
{
cur = cur->parent;
if
(cur == NULL)
break
;
if
(cur->next != NULL) {
cur = cur->next;
if
(xmlXIncludeTestNode(cur))
xmlXIncludePreProcessNode(ctxt, cur);
break
;
}
}
while
(cur != NULL);
}
}
for
(i = 0;i < ctxt->incNr; i++) {
xmlXIncludeLoadNode(ctxt, i);
}
for
(i = 0;i < ctxt->incNr; i++) {
xmlXIncludeIncludeNode(ctxt, i);
}
return
(ret);
}
int
xmlXIncludeProcess(xmlDocPtr doc) {
xmlXIncludeCtxtPtr ctxt;
int
ret = 0;
if
(doc == NULL)
return
(-1);
ctxt = xmlXIncludeNewContext(doc);
if
(ctxt == NULL)
return
(-1);
ret = xmlXIncludeDoProcess(ctxt, doc);
xmlXIncludeFreeContext(ctxt);
return
(ret);
}
#else /* !LIBXML_XINCLUDE_ENABLED */
#endif