2001-02-23 20:55:21 +03:00
/*
* xinclude . c : Code to implement XInclude processing
*
2001-05-23 16:02:27 +04:00
* World Wide Web Consortium W3C Last Call Working Draft 16 May 2001
* http : //www.w3.org/TR/2001/WD-xinclude-20010516/
2001-02-23 20:55:21 +03:00
*
* See Copyright for the status of this software .
*
2001-06-24 16:13:24 +04:00
* daniel @ veillard . com
2001-02-23 20:55:21 +03:00
*/
/*
* TODO : compute XPointers nodesets
2001-05-23 17:44:21 +04:00
* TODO : add an node intermediate API and handle recursion at this level
2001-02-23 20:55:21 +03:00
*/
2002-03-18 22:37:11 +03:00
# define IN_LIBXML
2001-04-21 20:57:29 +04:00
# include "libxml.h"
2001-02-23 20:55:21 +03:00
# 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>
2001-10-17 19:58:35 +04:00
# include <libxml/globals.h>
2001-02-23 20:55:21 +03:00
# ifdef LIBXML_XINCLUDE_ENABLED
# include <libxml/xinclude.h>
2001-05-23 16:02:27 +04:00
# define XINCLUDE_NS (const xmlChar *) "http: //www.w3.org/2001/XInclude"
2001-02-23 20:55:21 +03:00
# define XINCLUDE_NODE (const xmlChar *) "include"
2002-08-03 02:19:49 +04:00
# define XINCLUDE_FALLBACK (const xmlChar *) "fallback"
2001-02-23 20:55:21 +03:00
# 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"
/* #define DEBUG_XINCLUDE */
2001-06-21 15:20:21 +04:00
# ifdef DEBUG_XINCLUDE
# ifdef LIBXML_DEBUG_ENABLED
# include <libxml/debugXML.h>
# endif
# endif
2001-02-23 20:55:21 +03:00
/************************************************************************
* *
* XInclude contexts handling *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* An XInclude context
*/
2001-02-26 04:36:19 +03:00
typedef xmlChar * xmlURL ;
2001-02-23 20:55:21 +03:00
typedef struct _xmlXIncludeCtxt xmlXIncludeCtxt ;
typedef xmlXIncludeCtxt * xmlXIncludeCtxtPtr ;
struct _xmlXIncludeCtxt {
xmlDocPtr doc ; /* the source document */
int incNr ; /* number of includes */
int incMax ; /* size of includes tab */
xmlNodePtr * incTab ; /* array of include nodes */
xmlNodePtr * repTab ; /* array of replacement node lists */
int docNr ; /* number of parsed documents */
int docMax ; /* size of parsed documents tab */
xmlDocPtr * docTab ; /* array of parsed documents */
2001-02-26 04:36:19 +03:00
xmlURL * urlTab ; /* array of parsed documents URLs */
2001-02-23 20:55:21 +03:00
int txtNr ; /* number of unparsed documents */
int txtMax ; /* size of unparsed documents tab */
xmlNodePtr * txtTab ; /* array of unparsed text nodes */
2001-02-26 04:36:19 +03:00
xmlURL * txturlTab ; /* array of unparsed txtuments URLs */
2001-02-23 20:55:21 +03:00
} ;
2001-05-23 17:44:21 +04:00
static int
xmlXIncludeDoProcess ( xmlXIncludeCtxtPtr ctxt , xmlDocPtr doc ) ;
/**
* xmlXIncludeNewContext :
* @ doc : an XML Document
*
* Creates a new XInclude context
*
* Returns the new set
*/
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 ) ;
}
/**
* xmlXIncludeFreeContext :
* @ ctxt : the XInclude context
*
* Free an XInclude context
*/
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 ) ;
}
2001-02-23 20:55:21 +03:00
/**
* xmlXIncludeAddNode :
* @ ctxt : the XInclude context
* @ node : the new node
*
* Add a new node to process to an XInclude context
*/
2001-03-24 20:00:36 +03:00
static void
2001-02-23 20:55:21 +03:00
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 + + ;
}
/**
* xmlXIncludeAddDoc :
* @ ctxt : the XInclude context
* @ doc : the new document
* @ url : the associated URL
*
2001-05-23 17:44:21 +04:00
* Add a new document to the list . The XInclude recursive nature is handled
* at this point .
2001-02-23 20:55:21 +03:00
*/
2001-03-24 20:00:36 +03:00
static void
2001-02-26 04:36:19 +03:00
xmlXIncludeAddDoc ( xmlXIncludeCtxtPtr ctxt , xmlDocPtr doc , const xmlURL url ) {
2001-05-23 17:44:21 +04:00
xmlXIncludeCtxtPtr newctxt ;
int i ;
2001-02-23 20:55:21 +03:00
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 ;
}
2001-02-26 04:36:19 +03:00
ctxt - > urlTab = ( xmlURL * ) xmlMalloc ( ctxt - > docMax *
2001-02-23 20:55:21 +03:00
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 ;
}
2001-02-26 04:36:19 +03:00
ctxt - > urlTab = ( xmlURL * ) xmlRealloc ( ctxt - > urlTab ,
2001-02-23 20:55:21 +03:00
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 + + ;
2001-05-23 17:44:21 +04:00
/*
* Handle recursion here .
*/
newctxt = xmlXIncludeNewContext ( doc ) ;
if ( newctxt ! = NULL ) {
/*
* Copy the existing document set
*/
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 ) ;
}
2001-02-23 20:55:21 +03:00
}
/**
* xmlXIncludeAddTxt :
* @ ctxt : the XInclude context
* @ txt : the new text node
* @ url : the associated URL
*
* Add a new txtument to the list
*/
2001-03-24 20:00:36 +03:00
static void
2001-02-26 04:36:19 +03:00
xmlXIncludeAddTxt ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr txt , const xmlURL url ) {
2001-02-23 20:55:21 +03:00
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 ;
}
2001-02-26 04:36:19 +03:00
ctxt - > txturlTab = ( xmlURL * ) xmlMalloc ( ctxt - > txtMax *
2001-02-23 20:55:21 +03:00
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 ;
}
2001-02-26 04:36:19 +03:00
ctxt - > txturlTab = ( xmlURL * ) xmlRealloc ( ctxt - > txturlTab ,
2001-02-23 20:55:21 +03:00
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 + + ;
}
2002-02-10 14:57:22 +03:00
/************************************************************************
* *
* Node copy with specific semantic *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlXIncludeCopyNode :
* @ ctxt : the XInclude context
* @ target : the document target
* @ source : the document source
* @ elem : the element
*
* Make a copy of the node while preserving the XInclude semantic
* of the Infoset copy
*/
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 ) ;
}
/**
* xmlXIncludeCopyNodeList :
* @ ctxt : the XInclude context
* @ target : the document target
* @ source : the document source
* @ elem : the element list
*
* Make a copy of the node list while preserving the XInclude semantic
* of the Infoset copy
*/
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 ) ;
}
/**
* xmlXInclueGetNthChild :
* @ cur : the node
* @ no : the child number
*
* Returns the @ no ' th element child of @ cur or NULL
*/
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 ) ;
/**
* xmlXIncludeCopyRange :
* @ ctxt : the XInclude context
* @ target : the document target
* @ source : the document source
* @ obj : the XPointer result from the evaluation .
*
* Build a node list tree copy of the XPointer result .
*
* Returns an xmlNodePtr list or NULL .
* the caller has to free the node tree .
*/
static xmlNodePtr
xmlXIncludeCopyRange ( xmlXIncludeCtxtPtr ctxt , xmlDocPtr target ,
xmlDocPtr source , xmlXPathObjectPtr range ) {
/* pointers to generated nodes */
xmlNodePtr list = NULL , last = NULL , parent = NULL , tmp ;
/* pointers to traversal nodes */
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 ) ;
}
/* single sub text node selection */
if ( list = = NULL )
return ( tmp ) ;
/* prune and return full set */
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 ;
}
/*
* Now gather the remaining nodes from cur to end
*/
continue ; /* while */
}
} else if ( ( cur = = start ) & &
( list = = NULL ) /* looks superfluous but ... */ ) {
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 ;
/*
* Now gather the remaining nodes from cur to end
*/
continue ; /* while */
}
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 :
/* Do not copy DTD informations */
break ;
case XML_ENTITY_DECL :
/* handle crossing entities -> stack needed */
break ;
case XML_XINCLUDE_START :
case XML_XINCLUDE_END :
/* don't consider it part of the tree content */
break ;
case XML_ATTRIBUTE_NODE :
/* Humm, should not happen ! */
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 ;
}
}
}
/*
* Skip to next node in document order
*/
if ( ( list = = NULL ) | | ( ( last = = NULL ) & & ( parent = = NULL ) ) ) {
return ( NULL ) ;
}
cur = xmlXPtrAdvanceNode ( cur ) ;
}
return ( list ) ;
}
/**
* xmlXIncludeBuildNodeList :
* @ ctxt : the XInclude context
* @ target : the document target
* @ source : the document source
* @ obj : the XPointer result from the evaluation .
*
* Build a node list tree copy of the XPointer result .
* This will drop Attributes and Namespace declarations .
*
* Returns an xmlNodePtr list or NULL .
* the caller has to free the node tree .
*/
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 ; /* for */
}
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 :
/* points are ignored in XInclude */
break ;
default :
break ;
}
return ( list ) ;
}
2001-02-23 20:55:21 +03:00
/************************************************************************
* *
* XInclude I / O handling *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlXIncludeLoadDoc :
* @ ctxt : the XInclude context
* @ url : the associated URL
* @ nr : the xinclude node number
*
* Load the document , and store the result in the XInclude context
2002-08-14 18:11:30 +04:00
*
* Returns 0 in case of success , - 1 in case of failure
2001-02-23 20:55:21 +03:00
*/
2002-08-14 18:11:30 +04:00
static int
2001-02-23 20:55:21 +03:00
xmlXIncludeLoadDoc ( xmlXIncludeCtxtPtr ctxt , const xmlChar * url , int nr ) {
xmlDocPtr doc ;
xmlURIPtr uri ;
xmlChar * URL ;
xmlChar * fragment = NULL ;
int i ;
/*
* Check the URL and remove any fragment identifier
*/
uri = xmlParseURI ( ( const char * ) url ) ;
if ( uri = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" XInclude: invalid value URI %s \n " , url ) ;
2002-08-14 18:11:30 +04:00
return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
}
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 ) ;
2002-08-14 18:11:30 +04:00
return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
}
/*
* Handling of references to the local document are done
* directly through ctxt - > doc .
*/
if ( ( URL [ 0 ] = = 0 ) | | ( URL [ 0 ] = = ' # ' ) ) {
doc = NULL ;
goto loaded ;
}
/*
* Prevent reloading twice the document .
*/
for ( i = 0 ; i < ctxt - > docNr ; i + + ) {
if ( xmlStrEqual ( URL , ctxt - > urlTab [ i ] ) ) {
doc = ctxt - > docTab [ i ] ;
goto loaded ;
}
}
/*
* Load it .
*/
doc = xmlParseFile ( ( const char * ) URL ) ;
if ( doc = = NULL ) {
xmlFree ( URL ) ;
if ( fragment ! = NULL )
xmlFree ( fragment ) ;
2002-08-14 18:11:30 +04:00
return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
}
xmlXIncludeAddDoc ( ctxt , doc , URL ) ;
loaded :
if ( fragment = = NULL ) {
/*
* Add the top children list as the replacement copy .
*/
if ( doc = = NULL )
2001-06-09 18:19:02 +04:00
{
/* Hopefully a DTD declaration won't be copied from
* the same document */
2001-02-23 20:55:21 +03:00
ctxt - > repTab [ nr ] = xmlCopyNodeList ( ctxt - > doc - > children ) ;
2001-06-09 18:19:02 +04:00
} else {
2002-02-10 14:57:22 +03:00
ctxt - > repTab [ nr ] = xmlXIncludeCopyNodeList ( ctxt , ctxt - > doc ,
doc , doc - > children ) ;
2001-06-09 18:19:02 +04:00
}
2001-02-23 20:55:21 +03:00
} else {
/*
* Computes the XPointer expression and make a copy used
* as the replacement copy .
*/
xmlXPathObjectPtr xptr ;
xmlXPathContextPtr xptrctxt ;
2001-06-19 22:09:42 +04:00
xmlNodeSetPtr set ;
2001-02-23 20:55:21 +03:00
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 ) ;
2002-08-14 18:11:30 +04:00
return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
}
xptr = xmlXPtrEval ( fragment , xptrctxt ) ;
if ( xptr = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" XInclude: XPointer evaluation failed: #%s \n " ,
fragment ) ;
xmlXPathFreeContext ( xptrctxt ) ;
xmlFree ( URL ) ;
xmlFree ( fragment ) ;
2002-08-14 18:11:30 +04:00
return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
}
2001-06-19 22:09:42 +04:00
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 ) ;
2002-08-14 18:11:30 +04:00
return ( - 1 ) ;
2001-06-19 22:09:42 +04:00
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 ; /* for */
}
}
}
2002-02-10 14:57:22 +03:00
ctxt - > repTab [ nr ] = xmlXIncludeCopyXPointer ( ctxt , ctxt - > doc , doc , xptr ) ;
2001-02-23 20:55:21 +03:00
xmlXPathFreeObject ( xptr ) ;
xmlXPathFreeContext ( xptrctxt ) ;
xmlFree ( fragment ) ;
}
2002-08-14 18:45:25 +04:00
/*
* Do the xml : base fixup if needed
*/
if ( ( doc ! = NULL ) & & ( URL ! = NULL ) & & ( xmlStrchr ( URL , ( xmlChar ) ' / ' ) ) ) {
xmlNodePtr node ;
node = ctxt - > repTab [ nr ] ;
while ( node ! = NULL ) {
if ( node - > type = = XML_ELEMENT_NODE )
xmlNodeSetBase ( node , URL ) ;
node = node - > next ;
}
}
2001-02-23 20:55:21 +03:00
xmlFree ( URL ) ;
2002-08-14 18:11:30 +04:00
return ( 0 ) ;
2001-02-23 20:55:21 +03:00
}
/**
* xmlXIncludeLoadTxt :
* @ ctxt : the XInclude context
* @ url : the associated URL
* @ nr : the xinclude node number
*
* Load the content , and store the result in the XInclude context
2002-08-14 18:11:30 +04:00
*
* Returns 0 in case of success , - 1 in case of failure
2001-02-23 20:55:21 +03:00
*/
2002-08-14 18:11:30 +04:00
static int
2001-02-23 20:55:21 +03:00
xmlXIncludeLoadTxt ( xmlXIncludeCtxtPtr ctxt , const xmlChar * url , int nr ) {
xmlParserInputBufferPtr buf ;
xmlNodePtr node ;
xmlURIPtr uri ;
xmlChar * URL ;
int i ;
/*
* Check the URL and remove any fragment identifier
*/
uri = xmlParseURI ( ( const char * ) url ) ;
if ( uri = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" XInclude: invalid value URI %s \n " , url ) ;
2002-08-14 18:11:30 +04:00
return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
}
if ( uri - > fragment ! = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" XInclude: fragment identifier forbidden for text: %s \n " ,
uri - > fragment ) ;
xmlFreeURI ( uri ) ;
2002-08-14 18:11:30 +04:00
return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
}
URL = xmlSaveUri ( uri ) ;
xmlFreeURI ( uri ) ;
if ( URL = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" XInclude: invalid value URI %s \n " , url ) ;
2002-08-14 18:11:30 +04:00
return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
}
/*
* Handling of references to the local document are done
* directly through ctxt - > doc .
*/
if ( URL [ 0 ] = = 0 ) {
xmlGenericError ( xmlGenericErrorContext ,
" XInclude: text serialization of document not available \n " ) ;
xmlFree ( URL ) ;
2002-08-14 18:11:30 +04:00
return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
}
/*
* Prevent reloading twice the document .
*/
for ( i = 0 ; i < ctxt - > txtNr ; i + + ) {
if ( xmlStrEqual ( URL , ctxt - > txturlTab [ i ] ) ) {
node = xmlCopyNode ( ctxt - > txtTab [ i ] , 1 ) ;
goto loaded ;
}
}
/*
* Load it .
* Issue 62 : how to detect the encoding
*/
buf = xmlParserInputBufferCreateFilename ( ( const char * ) URL , 0 ) ;
if ( buf = = NULL ) {
xmlFree ( URL ) ;
2002-08-14 18:11:30 +04:00
return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
}
node = xmlNewText ( NULL ) ;
/*
* Scan all chars from the resource and add the to the node
*/
while ( xmlParserInputBufferRead ( buf , 128 ) > 0 ) {
int len ;
const xmlChar * content ;
content = xmlBufferContent ( buf - > buffer ) ;
len = xmlBufferLength ( buf - > buffer ) ;
for ( i = 0 ; i < len ; i + + ) {
/*
* TODO : if the encoding issue is solved , scan UTF8 chars instead
*/
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 :
/*
* Add the element as the replacement copy .
*/
ctxt - > repTab [ nr ] = node ;
xmlFree ( URL ) ;
2002-08-14 18:11:30 +04:00
return ( 0 ) ;
}
/**
* xmlXIncludeLoadFallback :
* @ ctxt : the XInclude context
* @ fallback : the fallback node
* @ nr : the xinclude node number
*
* Load the content of teh fallback node , and store the result
* in the XInclude context
*
* Returns 0 in case of success , - 1 in case of failure
*/
static int
xmlXIncludeLoadFallback ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr fallback , int nr ) {
if ( ( fallback = = NULL ) | | ( ctxt = = NULL ) )
return ( - 1 ) ;
ctxt - > repTab [ nr ] = xmlCopyNode ( fallback - > children , 1 ) ;
return ( 0 ) ;
2001-02-23 20:55:21 +03:00
}
/************************************************************************
* *
* XInclude Processing *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlXIncludePreProcessNode :
* @ ctxt : an XInclude context
* @ node : an XInclude node
*
2001-05-23 17:44:21 +04:00
* Implement the XInclude preprocessing , currently just adding the element
* for further processing .
2001-02-23 20:55:21 +03:00
*
* Returns the result list or NULL in case of error
*/
2001-03-24 20:00:36 +03:00
static xmlNodePtr
2001-02-23 20:55:21 +03:00
xmlXIncludePreProcessNode ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr node ) {
xmlXIncludeAddNode ( ctxt , node ) ;
return ( 0 ) ;
}
/**
* xmlXIncludeLoadNode :
* @ ctxt : an XInclude context
* @ nr : the node number
*
* Find and load the infoset replacement for the given node .
*
2001-12-31 19:16:02 +03:00
* Returns 0 if substitution succeeded , - 1 if some processing failed
2001-02-23 20:55:21 +03:00
*/
2001-03-24 20:00:36 +03:00
static int
2001-02-23 20:55:21 +03:00
xmlXIncludeLoadNode ( xmlXIncludeCtxtPtr ctxt , int nr ) {
xmlNodePtr cur ;
xmlChar * href ;
xmlChar * parse ;
xmlChar * base ;
xmlChar * URI ;
int xml = 1 ; /* default Issue 64 */
2002-08-14 18:11:30 +04:00
int ret ;
2001-02-23 20:55:21 +03:00
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
/*
* read the attributes
*/
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 ) ;
}
}
/*
* 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 ;
/*
2001-12-31 19:16:02 +03:00
* Some escaping may be needed
2001-02-23 20:55:21 +03:00
*/
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
/*
* Cleanup
*/
if ( xml ) {
2002-08-14 18:11:30 +04:00
ret = xmlXIncludeLoadDoc ( ctxt , URI , nr ) ;
2001-02-23 20:55:21 +03:00
/* xmlXIncludeGetFragment(ctxt, cur, URI); */
} else {
2002-08-14 18:11:30 +04:00
ret = xmlXIncludeLoadTxt ( ctxt , URI , nr ) ;
}
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 ) ) ) {
ret = xmlXIncludeLoadFallback ( ctxt , children , nr ) ;
if ( ret = = 0 )
break ;
}
children = children - > next ;
}
}
if ( ret < 0 ) {
xmlGenericError ( xmlGenericErrorContext ,
" XInclude: could not load %s, and no fallback was found \n " ,
URI ) ;
2001-02-23 20:55:21 +03:00
}
/*
* 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
*
2001-12-31 19:16:02 +03:00
* Returns 0 if substitution succeeded , - 1 if some processing failed
2001-02-23 20:55:21 +03:00
*/
2001-03-24 20:00:36 +03:00
static int
2001-02-23 20:55:21 +03:00
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 ) ;
/*
* Change the current node as an XInclude start one , and add an
* entity end one
*/
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 ) ;
/*
* Add the list of nodes
*/
list = ctxt - > repTab [ nr ] ;
ctxt - > repTab [ nr ] = NULL ;
while ( list ! = NULL ) {
cur = list ;
list = list - > next ;
xmlAddPrevSibling ( end , cur ) ;
}
2002-02-10 14:57:22 +03:00
2001-02-23 20:55:21 +03:00
return ( 0 ) ;
}
/**
* xmlXIncludeTestNode :
* @ node : an XInclude node
*
* test if the node is an XInclude node
*
* Returns 1 true , 0 otherwise
*/
2001-03-24 20:00:36 +03:00
static int
xmlXIncludeTestNode ( xmlNodePtr node ) {
2001-02-23 20:55:21 +03:00
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 ) ;
}
/**
2001-05-23 17:44:21 +04:00
* xmlXIncludeDoProcess :
* @ ctxt :
2001-02-23 20:55:21 +03:00
* @ doc : an XML document
*
* Implement the XInclude substitution on the XML document @ doc
*
2001-12-31 19:16:02 +03:00
* Returns 0 if no substitution were done , - 1 if some processing failed
2001-02-23 20:55:21 +03:00
* or the number of substitutions done .
*/
2001-05-23 17:44:21 +04:00
static int
xmlXIncludeDoProcess ( xmlXIncludeCtxtPtr ctxt , xmlDocPtr doc ) {
2001-02-23 20:55:21 +03:00
xmlNodePtr cur ;
int ret = 0 ;
int i ;
if ( doc = = NULL )
return ( - 1 ) ;
if ( ctxt = = NULL )
return ( - 1 ) ;
/*
* First phase : lookup the elements in the document
*/
cur = xmlDocGetRootElement ( doc ) ;
2001-03-24 20:00:36 +03:00
if ( xmlXIncludeTestNode ( cur ) )
2001-02-23 20:55:21 +03:00
xmlXIncludePreProcessNode ( ctxt , cur ) ;
while ( cur ! = NULL ) {
/* TODO: need to work on entities -> stack */
if ( ( cur - > children ! = NULL ) & &
( cur - > children - > type ! = XML_ENTITY_DECL ) ) {
cur = cur - > children ;
2001-03-24 20:00:36 +03:00
if ( xmlXIncludeTestNode ( cur ) )
2001-02-23 20:55:21 +03:00
xmlXIncludePreProcessNode ( ctxt , cur ) ;
} else if ( cur - > next ! = NULL ) {
cur = cur - > next ;
2001-03-24 20:00:36 +03:00
if ( xmlXIncludeTestNode ( cur ) )
2001-02-23 20:55:21 +03:00
xmlXIncludePreProcessNode ( ctxt , cur ) ;
} else {
do {
cur = cur - > parent ;
if ( cur = = NULL ) break ; /* do */
if ( cur - > next ! = NULL ) {
cur = cur - > next ;
2001-03-24 20:00:36 +03:00
if ( xmlXIncludeTestNode ( cur ) )
2001-02-23 20:55:21 +03:00
xmlXIncludePreProcessNode ( ctxt , cur ) ;
break ; /* do */
}
} while ( cur ! = NULL ) ;
}
}
/*
* Second Phase : collect the infosets fragments
*/
for ( i = 0 ; i < ctxt - > incNr ; i + + ) {
xmlXIncludeLoadNode ( ctxt , i ) ;
}
/*
* Third phase : extend the original document infoset .
*/
for ( i = 0 ; i < ctxt - > incNr ; i + + ) {
xmlXIncludeIncludeNode ( ctxt , i ) ;
}
2001-05-23 17:44:21 +04:00
return ( ret ) ;
}
/**
* xmlXIncludeProcess :
* @ doc : an XML document
*
* Implement the XInclude substitution on the XML document @ doc
*
2001-12-31 19:16:02 +03:00
* Returns 0 if no substitution were done , - 1 if some processing failed
2001-05-23 17:44:21 +04:00
* or the number of substitutions done .
*/
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 ) ;
2001-02-23 20:55:21 +03:00
xmlXIncludeFreeContext ( ctxt ) ;
return ( ret ) ;
}
# else /* !LIBXML_XINCLUDE_ENABLED */
# endif