2001-02-23 17:55:21 +00:00
/*
* xinclude . c : Code to implement XInclude processing
*
2003-12-09 11:35:37 +00:00
* World Wide Web Consortium W3C Last Call Working Draft 10 November 2003
* http : //www.w3.org/TR/2003/WD-xinclude-20031110
2001-02-23 17:55:21 +00:00
*
* See Copyright for the status of this software .
*
2001-06-24 12:13:24 +00:00
* daniel @ veillard . com
2001-02-23 17:55:21 +00:00
*/
2002-03-18 19:37:11 +00:00
# define IN_LIBXML
2001-04-21 16:57:29 +00:00
# include "libxml.h"
2001-02-23 17:55:21 +00: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>
2002-11-20 13:28:31 +00:00
# include <libxml/encoding.h>
2001-10-17 15:58:35 +00:00
# include <libxml/globals.h>
2001-02-23 17:55:21 +00:00
# ifdef LIBXML_XINCLUDE_ENABLED
# include <libxml/xinclude.h>
2003-02-13 11:02:08 +00:00
# define XINCLUDE_MAX_DEPTH 40
2003-08-14 15:44:40 +00:00
/* #define DEBUG_XINCLUDE */
2001-06-21 11:20:21 +00:00
# ifdef DEBUG_XINCLUDE
# ifdef LIBXML_DEBUG_ENABLED
# include <libxml/debugXML.h>
# endif
# endif
2001-02-23 17:55:21 +00:00
/************************************************************************
* *
2003-12-30 08:30:19 +00:00
* XInclude context handling *
2001-02-23 17:55:21 +00:00
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* An XInclude context
*/
2001-02-26 01:36:19 +00:00
typedef xmlChar * xmlURL ;
2002-09-05 10:52:10 +00:00
typedef struct _xmlXIncludeRef xmlXIncludeRef ;
typedef xmlXIncludeRef * xmlXIncludeRefPtr ;
struct _xmlXIncludeRef {
2003-12-30 08:30:19 +00:00
xmlChar * URI ; /* the fully resolved resource URL */
2002-09-05 10:52:10 +00:00
xmlChar * fragment ; /* the fragment in the URI */
xmlDocPtr doc ; /* the parsed document */
xmlNodePtr ref ; /* the node making the reference in the source */
xmlNodePtr inc ; /* the included copy */
int xml ; /* xml or txt */
int count ; /* how many refs use that specific doc */
2003-02-13 11:02:08 +00:00
xmlXPathObjectPtr xptr ; /* the xpointer if needed */
2004-02-08 04:12:49 +00:00
int emptyFb ; /* flag to show fallback empty */
2002-09-05 10:52:10 +00:00
} ;
2001-02-23 17:55:21 +00:00
struct _xmlXIncludeCtxt {
xmlDocPtr doc ; /* the source document */
2002-09-05 10:52:10 +00:00
int incBase ; /* the first include for this document */
2001-02-23 17:55:21 +00:00
int incNr ; /* number of includes */
int incMax ; /* size of includes tab */
2002-09-05 10:52:10 +00:00
xmlXIncludeRefPtr * incTab ; /* array of included references */
2001-02-23 17:55:21 +00:00
int txtNr ; /* number of unparsed documents */
int txtMax ; /* size of unparsed documents tab */
xmlNodePtr * txtTab ; /* array of unparsed text nodes */
2003-12-30 08:30:19 +00:00
xmlURL * txturlTab ; /* array of unparsed text URLs */
2003-02-11 18:03:05 +00:00
2003-02-13 11:02:08 +00:00
xmlChar * url ; /* the current URL processed */
2003-12-30 08:30:19 +00:00
int urlNr ; /* number of URLs stacked */
int urlMax ; /* size of URL stack */
xmlChar * * urlTab ; /* URL stack */
2003-02-13 11:02:08 +00:00
2003-02-11 18:03:05 +00:00
int nbErrors ; /* the number of errors detected */
2003-12-08 17:41:29 +00:00
int legacy ; /* using XINCLUDE_OLD_NS */
2003-12-09 11:35:37 +00:00
int parseFlags ; /* the flags used for parsing XML documents */
2004-06-07 08:57:27 +00:00
xmlChar * base ; /* the current xml:base */
2001-02-23 17:55:21 +00:00
} ;
2001-05-23 13:44:21 +00:00
static int
2003-07-22 20:52:14 +00:00
xmlXIncludeDoProcess ( xmlXIncludeCtxtPtr ctxt , xmlDocPtr doc , xmlNodePtr tree ) ;
2001-05-23 13:44:21 +00:00
2003-08-14 15:44:40 +00:00
2003-10-08 22:38:13 +00:00
/************************************************************************
* *
2003-10-09 11:46:07 +00:00
* XInclude error handler *
2003-10-08 22:38:13 +00:00
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-08-14 15:44:40 +00:00
/**
2003-10-08 22:38:13 +00:00
* xmlXIncludeErrMemory :
2003-12-30 08:30:19 +00:00
* @ extra : extra information
2003-08-14 15:44:40 +00:00
*
2003-10-08 22:38:13 +00:00
* Handle an out of memory condition
2003-08-14 15:44:40 +00:00
*/
static void
2003-10-08 22:38:13 +00:00
xmlXIncludeErrMemory ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr node ,
const char * extra )
2003-08-14 15:44:40 +00:00
{
2003-10-08 22:38:13 +00:00
if ( ctxt ! = NULL )
ctxt - > nbErrors + + ;
2003-10-10 14:10:40 +00:00
__xmlRaiseError ( NULL , NULL , NULL , ctxt , node , XML_FROM_XINCLUDE ,
2003-10-08 22:38:13 +00:00
XML_ERR_NO_MEMORY , XML_ERR_ERROR , NULL , 0 ,
extra , NULL , NULL , 0 , 0 ,
" Memory allocation failed : %s \n " , extra ) ;
}
2003-08-14 15:44:40 +00:00
2003-10-08 22:38:13 +00:00
/**
* xmlXIncludeErr :
* @ ctxt : the XInclude context
* @ node : the context node
* @ msg : the error message
2003-12-30 08:30:19 +00:00
* @ extra : extra information
2003-10-08 22:38:13 +00:00
*
2003-12-08 17:41:29 +00:00
* Handle an XInclude error
2003-10-08 22:38:13 +00:00
*/
static void
xmlXIncludeErr ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr node , int error ,
const char * msg , const xmlChar * extra )
{
if ( ctxt ! = NULL )
ctxt - > nbErrors + + ;
2003-10-10 14:10:40 +00:00
__xmlRaiseError ( NULL , NULL , NULL , ctxt , node , XML_FROM_XINCLUDE ,
2003-10-08 22:38:13 +00:00
error , XML_ERR_ERROR , NULL , 0 ,
( const char * ) extra , NULL , NULL , 0 , 0 ,
msg , ( const char * ) extra ) ;
2003-08-14 15:44:40 +00:00
}
2004-02-25 11:52:31 +00:00
#if 0
2003-12-08 17:41:29 +00:00
/**
* xmlXIncludeWarn :
* @ ctxt : the XInclude context
* @ node : the context node
* @ msg : the error message
2003-12-30 08:30:19 +00:00
* @ extra : extra information
2003-12-08 17:41:29 +00:00
*
* Emit an XInclude warning .
*/
static void
xmlXIncludeWarn ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr node , int error ,
const char * msg , const xmlChar * extra )
{
__xmlRaiseError ( NULL , NULL , NULL , ctxt , node , XML_FROM_XINCLUDE ,
error , XML_ERR_WARNING , NULL , 0 ,
( const char * ) extra , NULL , NULL , 0 , 0 ,
msg , ( const char * ) extra ) ;
}
2004-02-25 11:52:31 +00:00
# endif
2003-12-08 17:41:29 +00:00
/**
* xmlXIncludeGetProp :
* @ ctxt : the XInclude context
* @ cur : the node
* @ name : the attribute name
*
* Get an XInclude attribute
*
* Returns the value ( to be freed ) or NULL if not found
*/
static xmlChar *
xmlXIncludeGetProp ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr cur ,
const xmlChar * name ) {
xmlChar * ret ;
ret = xmlGetNsProp ( cur , XINCLUDE_NS , name ) ;
if ( ret ! = NULL )
return ( ret ) ;
if ( ctxt - > legacy ! = 0 ) {
ret = xmlGetNsProp ( cur , XINCLUDE_OLD_NS , name ) ;
if ( ret ! = NULL )
return ( ret ) ;
}
ret = xmlGetProp ( cur , name ) ;
return ( ret ) ;
}
2002-09-05 10:52:10 +00:00
/**
* xmlXIncludeFreeRef :
* @ ref : the XInclude reference
*
* Free an XInclude reference
*/
static void
xmlXIncludeFreeRef ( xmlXIncludeRefPtr ref ) {
if ( ref = = NULL )
return ;
# ifdef DEBUG_XINCLUDE
xmlGenericError ( xmlGenericErrorContext , " Freeing ref \n " ) ;
# endif
if ( ref - > doc ! = NULL ) {
# ifdef DEBUG_XINCLUDE
xmlGenericError ( xmlGenericErrorContext , " Freeing doc %s \n " , ref - > URI ) ;
# endif
xmlFreeDoc ( ref - > doc ) ;
}
if ( ref - > URI ! = NULL )
xmlFree ( ref - > URI ) ;
if ( ref - > fragment ! = NULL )
xmlFree ( ref - > fragment ) ;
2003-02-13 11:02:08 +00:00
if ( ref - > xptr ! = NULL )
xmlXPathFreeObject ( ref - > xptr ) ;
2002-09-05 10:52:10 +00:00
xmlFree ( ref ) ;
}
/**
* xmlXIncludeNewRef :
* @ ctxt : the XInclude context
* @ URI : the resource URI
*
* Creates a new reference within an XInclude context
*
* Returns the new set
*/
static xmlXIncludeRefPtr
xmlXIncludeNewRef ( xmlXIncludeCtxtPtr ctxt , const xmlChar * URI ,
xmlNodePtr ref ) {
xmlXIncludeRefPtr ret ;
# ifdef DEBUG_XINCLUDE
xmlGenericError ( xmlGenericErrorContext , " New ref %s \n " , URI ) ;
# endif
ret = ( xmlXIncludeRefPtr ) xmlMalloc ( sizeof ( xmlXIncludeRef ) ) ;
2003-10-08 22:38:13 +00:00
if ( ret = = NULL ) {
xmlXIncludeErrMemory ( ctxt , ref , " growing XInclude context " ) ;
2002-09-05 10:52:10 +00:00
return ( NULL ) ;
2003-10-08 22:38:13 +00:00
}
2002-09-05 10:52:10 +00:00
memset ( ret , 0 , sizeof ( xmlXIncludeRef ) ) ;
if ( URI = = NULL )
ret - > URI = NULL ;
else
ret - > URI = xmlStrdup ( URI ) ;
ret - > fragment = NULL ;
ret - > ref = ref ;
2005-07-28 23:49:35 +00:00
ret - > doc = NULL ;
2002-09-05 10:52:10 +00:00
ret - > count = 0 ;
ret - > xml = 0 ;
ret - > inc = NULL ;
if ( ctxt - > incMax = = 0 ) {
ctxt - > incMax = 4 ;
ctxt - > incTab = ( xmlXIncludeRefPtr * ) xmlMalloc ( ctxt - > incMax *
sizeof ( ctxt - > incTab [ 0 ] ) ) ;
if ( ctxt - > incTab = = NULL ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErrMemory ( ctxt , ref , " growing XInclude context " ) ;
2002-09-05 10:52:10 +00:00
xmlXIncludeFreeRef ( ret ) ;
return ( NULL ) ;
}
}
if ( ctxt - > incNr > = ctxt - > incMax ) {
ctxt - > incMax * = 2 ;
ctxt - > incTab = ( xmlXIncludeRefPtr * ) xmlRealloc ( ctxt - > incTab ,
ctxt - > incMax * sizeof ( ctxt - > incTab [ 0 ] ) ) ;
if ( ctxt - > incTab = = NULL ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErrMemory ( ctxt , ref , " growing XInclude context " ) ;
2002-09-05 10:52:10 +00:00
xmlXIncludeFreeRef ( ret ) ;
return ( NULL ) ;
}
}
ctxt - > incTab [ ctxt - > incNr + + ] = ret ;
return ( ret ) ;
}
2001-05-23 13:44:21 +00:00
/**
* xmlXIncludeNewContext :
* @ doc : an XML Document
*
* Creates a new XInclude context
*
* Returns the new set
*/
2003-11-03 12:31:38 +00:00
xmlXIncludeCtxtPtr
2001-05-23 13:44:21 +00:00
xmlXIncludeNewContext ( xmlDocPtr doc ) {
xmlXIncludeCtxtPtr ret ;
2002-09-05 10:52:10 +00:00
# ifdef DEBUG_XINCLUDE
xmlGenericError ( xmlGenericErrorContext , " New context \n " ) ;
# endif
2001-05-23 13:44:21 +00:00
if ( doc = = NULL )
return ( NULL ) ;
ret = ( xmlXIncludeCtxtPtr ) xmlMalloc ( sizeof ( xmlXIncludeCtxt ) ) ;
2003-10-08 22:38:13 +00:00
if ( ret = = NULL ) {
xmlXIncludeErrMemory ( NULL , ( xmlNodePtr ) doc ,
" creating XInclude context " ) ;
2001-05-23 13:44:21 +00:00
return ( NULL ) ;
2003-10-08 22:38:13 +00:00
}
2001-05-23 13:44:21 +00:00
memset ( ret , 0 , sizeof ( xmlXIncludeCtxt ) ) ;
ret - > doc = doc ;
ret - > incNr = 0 ;
2002-09-05 10:52:10 +00:00
ret - > incBase = 0 ;
2001-05-23 13:44:21 +00:00
ret - > incMax = 0 ;
ret - > incTab = NULL ;
2003-02-11 18:03:05 +00:00
ret - > nbErrors = 0 ;
2001-05-23 13:44:21 +00:00
return ( ret ) ;
}
2003-02-13 11:02:08 +00:00
/**
* xmlXIncludeURLPush :
* @ ctxt : the parser context
* @ value : the url
*
* Pushes a new url on top of the url stack
*
* Returns - 1 in case of error , the index in the stack otherwise
*/
static int
xmlXIncludeURLPush ( xmlXIncludeCtxtPtr ctxt ,
const xmlChar * value )
{
if ( ctxt - > urlNr > XINCLUDE_MAX_DEPTH ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , NULL , XML_XINCLUDE_RECURSION ,
" detected a recursion in %s \n " , value ) ;
2003-02-13 11:02:08 +00:00
return ( - 1 ) ;
}
if ( ctxt - > urlTab = = NULL ) {
ctxt - > urlMax = 4 ;
ctxt - > urlNr = 0 ;
ctxt - > urlTab = ( xmlChar * * ) xmlMalloc (
ctxt - > urlMax * sizeof ( ctxt - > urlTab [ 0 ] ) ) ;
if ( ctxt - > urlTab = = NULL ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErrMemory ( ctxt , NULL , " adding URL " ) ;
2003-02-13 11:02:08 +00:00
return ( - 1 ) ;
}
}
if ( ctxt - > urlNr > = ctxt - > urlMax ) {
ctxt - > urlMax * = 2 ;
ctxt - > urlTab =
( xmlChar * * ) xmlRealloc ( ctxt - > urlTab ,
ctxt - > urlMax *
sizeof ( ctxt - > urlTab [ 0 ] ) ) ;
if ( ctxt - > urlTab = = NULL ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErrMemory ( ctxt , NULL , " adding URL " ) ;
2003-02-13 11:02:08 +00:00
return ( - 1 ) ;
}
}
ctxt - > url = ctxt - > urlTab [ ctxt - > urlNr ] = xmlStrdup ( value ) ;
return ( ctxt - > urlNr + + ) ;
}
/**
* xmlXIncludeURLPop :
* @ ctxt : the parser context
*
2003-12-30 08:30:19 +00:00
* Pops the top URL from the URL stack
2003-02-13 11:02:08 +00:00
*/
static void
xmlXIncludeURLPop ( xmlXIncludeCtxtPtr ctxt )
{
xmlChar * ret ;
if ( ctxt - > urlNr < = 0 )
return ;
ctxt - > urlNr - - ;
if ( ctxt - > urlNr > 0 )
ctxt - > url = ctxt - > urlTab [ ctxt - > urlNr - 1 ] ;
else
ctxt - > url = NULL ;
ret = ctxt - > urlTab [ ctxt - > urlNr ] ;
2005-07-28 23:49:35 +00:00
ctxt - > urlTab [ ctxt - > urlNr ] = NULL ;
2003-02-13 11:02:08 +00:00
if ( ret ! = NULL )
xmlFree ( ret ) ;
}
2001-05-23 13:44:21 +00:00
/**
* xmlXIncludeFreeContext :
* @ ctxt : the XInclude context
*
* Free an XInclude context
*/
2003-11-03 12:31:38 +00:00
void
2001-05-23 13:44:21 +00:00
xmlXIncludeFreeContext ( xmlXIncludeCtxtPtr ctxt ) {
int i ;
2002-09-05 10:52:10 +00:00
# ifdef DEBUG_XINCLUDE
xmlGenericError ( xmlGenericErrorContext , " Freeing context \n " ) ;
# endif
2001-05-23 13:44:21 +00:00
if ( ctxt = = NULL )
return ;
2003-02-13 11:02:08 +00:00
while ( ctxt - > urlNr > 0 )
xmlXIncludeURLPop ( ctxt ) ;
if ( ctxt - > urlTab ! = NULL )
xmlFree ( ctxt - > urlTab ) ;
2002-09-05 10:52:10 +00:00
for ( i = 0 ; i < ctxt - > incNr ; i + + ) {
if ( ctxt - > incTab [ i ] ! = NULL )
xmlXIncludeFreeRef ( ctxt - > incTab [ i ] ) ;
2001-05-23 13:44:21 +00:00
}
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 - > txtTab ! = NULL )
xmlFree ( ctxt - > txtTab ) ;
if ( ctxt - > txturlTab ! = NULL )
xmlFree ( ctxt - > txturlTab ) ;
2004-11-05 10:03:46 +00:00
if ( ctxt - > base ! = NULL ) {
xmlFree ( ctxt - > base ) ;
}
2001-05-23 13:44:21 +00:00
xmlFree ( ctxt ) ;
}
2003-08-14 15:44:40 +00:00
/**
* xmlXIncludeParseFile :
* @ ctxt : the XInclude context
* @ URL : the URL or file path
*
2003-12-30 08:30:19 +00:00
* parse a document for XInclude
2003-08-14 15:44:40 +00:00
*/
static xmlDocPtr
2003-12-09 11:35:37 +00:00
xmlXIncludeParseFile ( xmlXIncludeCtxtPtr ctxt , const char * URL ) {
2003-08-14 15:44:40 +00:00
xmlDocPtr ret ;
xmlParserCtxtPtr pctxt ;
char * directory = NULL ;
2003-12-09 11:35:37 +00:00
xmlParserInputPtr inputStream ;
2003-08-14 15:44:40 +00:00
xmlInitParser ( ) ;
2003-12-09 11:35:37 +00:00
pctxt = xmlNewParserCtxt ( ) ;
2003-08-14 15:44:40 +00:00
if ( pctxt = = NULL ) {
2003-12-09 11:35:37 +00:00
xmlXIncludeErrMemory ( ctxt , NULL , " cannot allocate parser context " ) ;
return ( NULL ) ;
}
/*
2003-12-30 08:30:19 +00:00
* try to ensure that new documents included are actually
2003-12-09 11:35:37 +00:00
* built with the same dictionary as the including document .
*/
if ( ( ctxt - > doc ! = NULL ) & & ( ctxt - > doc - > dict ! = NULL ) & &
( pctxt - > dict ! = NULL ) ) {
xmlDictFree ( pctxt - > dict ) ;
pctxt - > dict = ctxt - > doc - > dict ;
xmlDictReference ( pctxt - > dict ) ;
}
xmlCtxtUseOptions ( pctxt , ctxt - > parseFlags | XML_PARSE_DTDLOAD ) ;
inputStream = xmlLoadExternalEntity ( URL , NULL , pctxt ) ;
if ( inputStream = = NULL ) {
xmlFreeParserCtxt ( pctxt ) ;
2003-08-14 15:44:40 +00:00
return ( NULL ) ;
}
2003-12-09 11:35:37 +00:00
inputPush ( pctxt , inputStream ) ;
2003-08-14 15:44:40 +00:00
if ( ( pctxt - > directory = = NULL ) & & ( directory = = NULL ) )
directory = xmlParserGetDirectory ( URL ) ;
if ( ( pctxt - > directory = = NULL ) & & ( directory ! = NULL ) )
pctxt - > directory = ( char * ) xmlStrdup ( ( xmlChar * ) directory ) ;
2005-02-12 01:08:22 +00:00
pctxt - > loadsubset | = XML_DETECT_IDS ;
2003-08-14 15:44:40 +00:00
xmlParseDocument ( pctxt ) ;
2003-12-31 14:05:15 +00:00
if ( pctxt - > wellFormed ) {
2003-08-14 15:44:40 +00:00
ret = pctxt - > myDoc ;
2003-12-31 14:05:15 +00:00
}
2003-08-14 15:44:40 +00:00
else {
ret = NULL ;
2004-03-22 15:22:58 +00:00
if ( pctxt - > myDoc ! = NULL )
2004-01-23 13:15:13 +00:00
xmlFreeDoc ( pctxt - > myDoc ) ;
2003-08-14 15:44:40 +00:00
pctxt - > myDoc = NULL ;
}
xmlFreeParserCtxt ( pctxt ) ;
return ( ret ) ;
}
2001-02-23 17:55:21 +00:00
/**
* xmlXIncludeAddNode :
* @ ctxt : the XInclude context
2002-09-05 10:52:10 +00:00
* @ cur : the new node
2001-02-23 17:55:21 +00:00
*
* Add a new node to process to an XInclude context
*/
2002-09-05 10:52:10 +00:00
static int
xmlXIncludeAddNode ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr cur ) {
xmlXIncludeRefPtr ref ;
xmlURIPtr uri ;
xmlChar * URL ;
xmlChar * fragment = NULL ;
xmlChar * href ;
xmlChar * parse ;
xmlChar * base ;
xmlChar * URI ;
2003-02-13 11:02:08 +00:00
int xml = 1 , i ; /* default Issue 64 */
int local = 0 ;
2002-09-05 10:52:10 +00:00
if ( ctxt = = NULL )
return ( - 1 ) ;
if ( cur = = NULL )
return ( - 1 ) ;
# ifdef DEBUG_XINCLUDE
xmlGenericError ( xmlGenericErrorContext , " Add node \n " ) ;
# endif
/*
* read the attributes
*/
2003-12-08 17:41:29 +00:00
href = xmlXIncludeGetProp ( ctxt , cur , XINCLUDE_HREF ) ;
2002-09-05 10:52:10 +00:00
if ( href = = NULL ) {
2003-12-08 17:41:29 +00:00
href = xmlStrdup ( BAD_CAST " " ) ; /* @@@@ href is now optional */
if ( href = = NULL )
2002-09-05 10:52:10 +00:00
return ( - 1 ) ;
2003-12-08 17:41:29 +00:00
local = 1 ;
2001-02-23 17:55:21 +00:00
}
2003-02-13 11:02:08 +00:00
if ( href [ 0 ] = = ' # ' )
local = 1 ;
2003-12-08 17:41:29 +00:00
parse = xmlXIncludeGetProp ( ctxt , cur , XINCLUDE_PARSE ) ;
2002-09-05 10:52:10 +00:00
if ( parse ! = NULL ) {
if ( xmlStrEqual ( parse , XINCLUDE_PARSE_XML ) )
xml = 1 ;
else if ( xmlStrEqual ( parse , XINCLUDE_PARSE_TEXT ) )
xml = 0 ;
else {
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , cur , XML_XINCLUDE_PARSE_VALUE ,
" invalid value %s for 'parse' \n " , parse ) ;
2002-09-05 10:52:10 +00:00
if ( href ! = NULL )
xmlFree ( href ) ;
if ( parse ! = NULL )
xmlFree ( parse ) ;
return ( - 1 ) ;
2001-02-23 17:55:21 +00:00
}
}
2002-09-05 10:52:10 +00:00
/*
* 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 ( parse ! = NULL )
xmlFree ( parse ) ;
if ( href ! = NULL )
xmlFree ( href ) ;
if ( base ! = NULL )
xmlFree ( base ) ;
if ( URI = = NULL ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , cur , XML_XINCLUDE_HREF_URI ,
" failed build URL \n " , NULL ) ;
2002-09-05 10:52:10 +00:00
return ( - 1 ) ;
}
2003-12-09 11:35:37 +00:00
fragment = xmlXIncludeGetProp ( ctxt , cur , XINCLUDE_PARSE_XPOINTER ) ;
2002-09-05 10:52:10 +00:00
/*
* Check the URL and remove any fragment identifier
*/
uri = xmlParseURI ( ( const char * ) URI ) ;
if ( uri = = NULL ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , cur , XML_XINCLUDE_HREF_URI ,
" invalid value URI %s \n " , URI ) ;
2003-12-09 11:35:37 +00:00
if ( fragment ! = NULL )
xmlFree ( fragment ) ;
xmlFree ( URI ) ;
2002-09-05 10:52:10 +00:00
return ( - 1 ) ;
}
2003-12-09 11:35:37 +00:00
2002-09-05 10:52:10 +00:00
if ( uri - > fragment ! = NULL ) {
2003-12-09 11:35:37 +00:00
if ( ctxt - > legacy ! = 0 ) {
if ( fragment = = NULL ) {
fragment = ( xmlChar * ) uri - > fragment ;
} else {
xmlFree ( uri - > fragment ) ;
}
} else {
xmlXIncludeErr ( ctxt , cur , XML_XINCLUDE_FRAGMENT_ID ,
" Invalid fragment identifier in URI %s use the xpointer attribute \n " ,
URI ) ;
if ( fragment ! = NULL )
xmlFree ( fragment ) ;
xmlFreeURI ( uri ) ;
xmlFree ( URI ) ;
return ( - 1 ) ;
}
2002-09-05 10:52:10 +00:00
uri - > fragment = NULL ;
}
URL = xmlSaveUri ( uri ) ;
xmlFreeURI ( uri ) ;
xmlFree ( URI ) ;
if ( URL = = NULL ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , cur , XML_XINCLUDE_HREF_URI ,
" invalid value URI %s \n " , URI ) ;
2002-09-05 10:52:10 +00:00
if ( fragment ! = NULL )
xmlFree ( fragment ) ;
return ( - 1 ) ;
}
2003-02-13 11:02:08 +00:00
/*
* Check the URL against the stack for recursions
*/
if ( ! local ) {
for ( i = 0 ; i < ctxt - > urlNr ; i + + ) {
if ( xmlStrEqual ( URL , ctxt - > urlTab [ i ] ) ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , cur , XML_XINCLUDE_RECURSION ,
" detected a recursion in %s \n " , URL ) ;
2003-02-13 11:02:08 +00:00
return ( - 1 ) ;
}
}
}
2002-09-05 10:52:10 +00:00
ref = xmlXIncludeNewRef ( ctxt , URL , cur ) ;
if ( ref = = NULL ) {
return ( - 1 ) ;
}
ref - > fragment = fragment ;
ref - > doc = NULL ;
ref - > xml = xml ;
ref - > count = 1 ;
xmlFree ( URL ) ;
return ( 0 ) ;
2001-02-23 17:55:21 +00:00
}
/**
2002-09-05 10:52:10 +00:00
* xmlXIncludeRecurseDoc :
2001-02-23 17:55:21 +00:00
* @ ctxt : the XInclude context
* @ doc : the new document
* @ url : the associated URL
*
2002-09-05 10:52:10 +00:00
* The XInclude recursive nature is handled at this point .
2001-02-23 17:55:21 +00:00
*/
2001-03-24 17:00:36 +00:00
static void
2002-09-24 14:13:13 +00:00
xmlXIncludeRecurseDoc ( xmlXIncludeCtxtPtr ctxt , xmlDocPtr doc ,
2002-09-26 09:47:36 +00:00
const xmlURL url ATTRIBUTE_UNUSED ) {
2001-05-23 13:44:21 +00:00
xmlXIncludeCtxtPtr newctxt ;
int i ;
2003-02-13 11:02:08 +00:00
/*
* Avoid recursion in already substitued resources
for ( i = 0 ; i < ctxt - > urlNr ; i + + ) {
if ( xmlStrEqual ( doc - > URL , ctxt - > urlTab [ i ] ) )
return ;
}
*/
2002-09-05 10:52:10 +00:00
# ifdef DEBUG_XINCLUDE
xmlGenericError ( xmlGenericErrorContext , " Recursing in doc %s \n " , doc - > URL ) ;
# endif
2001-05-23 13:44:21 +00:00
/*
* Handle recursion here .
*/
newctxt = xmlXIncludeNewContext ( doc ) ;
if ( newctxt ! = NULL ) {
/*
* Copy the existing document set
*/
2002-09-05 10:52:10 +00:00
newctxt - > incMax = ctxt - > incMax ;
newctxt - > incNr = ctxt - > incNr ;
newctxt - > incTab = ( xmlXIncludeRefPtr * ) xmlMalloc ( newctxt - > incMax *
sizeof ( newctxt - > incTab [ 0 ] ) ) ;
if ( newctxt - > incTab = = NULL ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErrMemory ( ctxt , ( xmlNodePtr ) doc , " processing doc " ) ;
2001-05-23 13:44:21 +00:00
xmlFree ( newctxt ) ;
return ;
}
2003-02-13 11:02:08 +00:00
/*
* copy the urlTab
*/
newctxt - > urlMax = ctxt - > urlMax ;
newctxt - > urlNr = ctxt - > urlNr ;
newctxt - > urlTab = ctxt - > urlTab ;
2001-05-23 13:44:21 +00:00
2004-06-07 08:57:27 +00:00
/*
* Inherit the existing base
*/
2004-11-05 10:03:46 +00:00
newctxt - > base = xmlStrdup ( ctxt - > base ) ;
2004-06-07 08:57:27 +00:00
2002-09-05 10:52:10 +00:00
/*
2003-12-30 08:30:19 +00:00
* Inherit the documents already in use by other includes
2002-09-05 10:52:10 +00:00
*/
newctxt - > incBase = ctxt - > incNr ;
for ( i = 0 ; i < ctxt - > incNr ; i + + ) {
newctxt - > incTab [ i ] = ctxt - > incTab [ i ] ;
newctxt - > incTab [ i ] - > count + + ; /* prevent the recursion from
freeing it */
2001-05-23 13:44:21 +00:00
}
2004-03-07 11:03:43 +00:00
/*
* The new context should also inherit the Parse Flags
* ( bug 132597 )
*/
newctxt - > parseFlags = ctxt - > parseFlags ;
2003-07-22 20:52:14 +00:00
xmlXIncludeDoProcess ( newctxt , doc , xmlDocGetRootElement ( doc ) ) ;
2002-09-05 10:52:10 +00:00
for ( i = 0 ; i < ctxt - > incNr ; i + + ) {
newctxt - > incTab [ i ] - > count - - ;
newctxt - > incTab [ i ] = NULL ;
2001-05-23 13:44:21 +00:00
}
2003-03-27 14:24:00 +00:00
/* urlTab may have been reallocated */
ctxt - > urlTab = newctxt - > urlTab ;
ctxt - > urlMax = newctxt - > urlMax ;
2003-02-13 11:02:08 +00:00
newctxt - > urlMax = 0 ;
newctxt - > urlNr = 0 ;
newctxt - > urlTab = NULL ;
2001-05-23 13:44:21 +00:00
xmlXIncludeFreeContext ( newctxt ) ;
}
2002-09-05 10:52:10 +00:00
# ifdef DEBUG_XINCLUDE
xmlGenericError ( xmlGenericErrorContext , " Done recursing in doc %s \n " , url ) ;
# endif
2001-02-23 17:55:21 +00: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 17:00:36 +00:00
static void
2001-02-26 01:36:19 +00:00
xmlXIncludeAddTxt ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr txt , const xmlURL url ) {
2002-09-05 10:52:10 +00:00
# ifdef DEBUG_XINCLUDE
xmlGenericError ( xmlGenericErrorContext , " Adding text %s \n " , url ) ;
# endif
2001-02-23 17:55:21 +00:00
if ( ctxt - > txtMax = = 0 ) {
ctxt - > txtMax = 4 ;
ctxt - > txtTab = ( xmlNodePtr * ) xmlMalloc ( ctxt - > txtMax *
sizeof ( ctxt - > txtTab [ 0 ] ) ) ;
if ( ctxt - > txtTab = = NULL ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErrMemory ( ctxt , NULL , " processing text " ) ;
2001-02-23 17:55:21 +00:00
return ;
}
2001-02-26 01:36:19 +00:00
ctxt - > txturlTab = ( xmlURL * ) xmlMalloc ( ctxt - > txtMax *
2001-02-23 17:55:21 +00:00
sizeof ( ctxt - > txturlTab [ 0 ] ) ) ;
if ( ctxt - > txturlTab = = NULL ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErrMemory ( ctxt , NULL , " processing text " ) ;
2001-02-23 17:55:21 +00:00
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 ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErrMemory ( ctxt , NULL , " processing text " ) ;
2001-02-23 17:55:21 +00:00
return ;
}
2001-02-26 01:36:19 +00:00
ctxt - > txturlTab = ( xmlURL * ) xmlRealloc ( ctxt - > txturlTab ,
2002-09-05 10:52:10 +00:00
ctxt - > txtMax * sizeof ( ctxt - > txturlTab [ 0 ] ) ) ;
2001-02-23 17:55:21 +00:00
if ( ctxt - > txturlTab = = NULL ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErrMemory ( ctxt , NULL , " processing text " ) ;
2001-02-23 17:55:21 +00:00
return ;
}
}
ctxt - > txtTab [ ctxt - > txtNr ] = txt ;
ctxt - > txturlTab [ ctxt - > txtNr ] = xmlStrdup ( url ) ;
ctxt - > txtNr + + ;
}
2002-02-10 11:57:22 +00: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 ) ;
}
/**
2003-12-30 08:30:19 +00:00
* xmlXIncludeGetNthChild :
2002-02-10 11:57:22 +00:00
* @ cur : the node
* @ no : the child number
*
2003-12-30 08:30:19 +00:00
* Returns the @ n ' th element child of @ cur or NULL
2002-02-10 11:57:22 +00:00
*/
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 ) ;
}
2003-12-31 07:59:17 +00:00
xmlNodePtr xmlXPtrAdvanceNode ( xmlNodePtr cur , int * level ) ; /* in xpointer.c */
2002-02-10 11:57:22 +00:00
/**
* 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 .
2003-12-30 08:30:19 +00:00
* The caller has to free the node tree .
2002-02-10 11:57:22 +00:00
*/
static xmlNodePtr
xmlXIncludeCopyRange ( xmlXIncludeCtxtPtr ctxt , xmlDocPtr target ,
xmlDocPtr source , xmlXPathObjectPtr range ) {
/* pointers to generated nodes */
2003-12-31 07:59:17 +00:00
xmlNodePtr list = NULL , last = NULL , listParent = NULL ;
xmlNodePtr tmp , tmp2 ;
2002-02-10 11:57:22 +00:00
/* pointers to traversal nodes */
xmlNodePtr start , cur , end ;
int index1 , index2 ;
2004-02-07 08:53:23 +00:00
int level = 0 , lastLevel = 0 , endLevel = 0 , endFlag = 0 ;
2002-02-10 11:57:22 +00:00
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 ;
2003-12-31 07:59:17 +00:00
/*
* level is depth of the current node under consideration
* list is the pointer to the root of the output tree
* listParent is a pointer to the parent of output tree ( within
the included file ) in case we need to add another level
* last is a pointer to the last node added to the output tree
* lastLevel is the depth of last ( relative to the root )
*/
2002-02-10 11:57:22 +00:00
while ( cur ! = NULL ) {
2003-12-31 07:59:17 +00:00
/*
* Check if our output tree needs a parent
*/
if ( level < 0 ) {
while ( level < 0 ) {
2004-03-09 16:19:02 +00:00
/* copy must include namespaces and properties */
tmp2 = xmlDocCopyNode ( listParent , target , 2 ) ;
2003-12-31 07:59:17 +00:00
xmlAddChild ( tmp2 , list ) ;
list = tmp2 ;
listParent = listParent - > parent ;
level + + ;
}
last = list ;
lastLevel = 0 ;
}
/*
* Check whether we need to change our insertion point
*/
while ( level < lastLevel ) {
last = last - > parent ;
lastLevel - - ;
}
2003-12-30 08:30:19 +00:00
if ( cur = = end ) { /* Are we at the end of the range? */
2002-02-10 11:57:22 +00:00
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 */
2003-12-31 07:59:17 +00:00
if ( level = = lastLevel )
2002-02-10 11:57:22 +00:00
xmlAddNextSibling ( last , tmp ) ;
else
2003-12-31 07:59:17 +00:00
xmlAddChild ( last , tmp ) ;
2002-02-10 11:57:22 +00:00
return ( list ) ;
2003-12-30 08:30:19 +00:00
} else { /* ending node not a text node */
2004-02-07 08:53:23 +00:00
endLevel = level ; /* remember the level of the end node */
endFlag = 1 ;
2004-03-09 16:19:02 +00:00
/* last node - need to take care of properties + namespaces */
tmp = xmlDocCopyNode ( cur , target , 2 ) ;
2003-12-31 07:59:17 +00:00
if ( list = = NULL ) {
2002-02-10 11:57:22 +00:00
list = tmp ;
2003-12-31 07:59:17 +00:00
listParent = cur - > parent ;
} else {
if ( level = = lastLevel )
2002-02-10 11:57:22 +00:00
xmlAddNextSibling ( last , tmp ) ;
2003-12-31 07:59:17 +00:00
else {
xmlAddChild ( last , tmp ) ;
lastLevel = level ;
}
2002-02-10 11:57:22 +00:00
}
2003-12-31 07:59:17 +00:00
last = tmp ;
2002-02-10 11:57:22 +00:00
if ( index2 > 1 ) {
end = xmlXIncludeGetNthChild ( cur , index2 - 1 ) ;
index2 = 0 ;
}
if ( ( cur = = start ) & & ( index1 > 1 ) ) {
cur = xmlXIncludeGetNthChild ( cur , index1 - 1 ) ;
index1 = 0 ;
2004-02-07 08:53:23 +00:00
} else {
2002-02-10 11:57:22 +00:00
cur = cur - > children ;
}
2004-02-07 08:53:23 +00:00
level + + ; /* increment level to show change */
2002-02-10 11:57:22 +00:00
/*
* Now gather the remaining nodes from cur to end
*/
2004-02-07 08:53:23 +00:00
continue ; /* while */
2002-02-10 11:57:22 +00:00
}
2003-12-31 07:59:17 +00:00
} else if ( cur = = start ) { /* Not at the end, are we at start? */
2002-02-10 11:57:22 +00:00
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 ) ;
2003-12-30 08:30:19 +00:00
index1 = 0 ;
2002-02-10 11:57:22 +00:00
}
tmp = xmlNewText ( content ) ;
}
last = list = tmp ;
2003-12-31 07:59:17 +00:00
listParent = cur - > parent ;
2003-12-30 08:30:19 +00:00
} else { /* Not text node */
2004-03-09 16:19:02 +00:00
/*
* start of the range - need to take care of
* properties and namespaces
*/
tmp = xmlDocCopyNode ( cur , target , 2 ) ;
2003-12-31 07:59:17 +00:00
list = last = tmp ;
listParent = cur - > parent ;
2003-12-30 08:30:19 +00:00
if ( index1 > 1 ) { /* Do we need to position? */
2002-02-10 11:57:22 +00:00
cur = xmlXIncludeGetNthChild ( cur , index1 - 1 ) ;
2003-12-31 07:59:17 +00:00
level = lastLevel = 1 ;
2002-02-10 11:57:22 +00:00
index1 = 0 ;
/*
* Now gather the remaining nodes from cur to end
*/
continue ; /* while */
}
}
} 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 :
2004-03-09 16:19:02 +00:00
/*
* Middle of the range - need to take care of
* properties and namespaces
*/
tmp = xmlDocCopyNode ( cur , target , 2 ) ;
2002-02-10 11:57:22 +00:00
break ;
}
if ( tmp ! = NULL ) {
2003-12-31 07:59:17 +00:00
if ( level = = lastLevel )
2002-02-10 11:57:22 +00:00
xmlAddNextSibling ( last , tmp ) ;
else {
2003-12-31 07:59:17 +00:00
xmlAddChild ( last , tmp ) ;
lastLevel = level ;
2002-02-10 11:57:22 +00:00
}
2003-12-31 07:59:17 +00:00
last = tmp ;
2002-02-10 11:57:22 +00:00
}
}
/*
* Skip to next node in document order
*/
2003-12-31 07:59:17 +00:00
cur = xmlXPtrAdvanceNode ( cur , & level ) ;
2004-02-07 08:53:23 +00:00
if ( endFlag & & ( level > = endLevel ) )
break ;
2002-02-10 11:57:22 +00:00
}
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 ;
2003-02-13 11:02:08 +00:00
if ( source = = NULL )
source = ctxt - > doc ;
2002-02-10 11:57:22 +00:00
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_END :
break ;
2003-02-13 11:02:08 +00:00
case XML_XINCLUDE_START : {
xmlNodePtr tmp , cur = set - > nodeTab [ i ] ;
cur = cur - > next ;
while ( cur ! = NULL ) {
switch ( cur - > 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 :
tmp = xmlXIncludeCopyNode ( ctxt , target ,
source , cur ) ;
if ( last = = NULL ) {
list = last = tmp ;
} else {
xmlAddNextSibling ( last , tmp ) ;
last = tmp ;
}
cur = cur - > next ;
continue ;
default :
break ;
}
break ;
}
continue ;
}
2002-02-10 11:57:22 +00:00
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 ;
}
2003-09-01 20:59:40 +00:00
# ifdef LIBXML_XPTR_ENABLED
2002-02-10 11:57:22 +00:00
case XPATH_RANGE :
return ( xmlXIncludeCopyRange ( ctxt , target , source , obj ) ) ;
2003-09-01 20:59:40 +00:00
# endif
2002-02-10 11:57:22 +00:00
case XPATH_POINT :
/* points are ignored in XInclude */
break ;
default :
break ;
}
return ( list ) ;
}
2001-02-23 17:55:21 +00:00
/************************************************************************
* *
* XInclude I / O handling *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-02-13 11:02:08 +00:00
typedef struct _xmlXIncludeMergeData xmlXIncludeMergeData ;
typedef xmlXIncludeMergeData * xmlXIncludeMergeDataPtr ;
struct _xmlXIncludeMergeData {
xmlDocPtr doc ;
xmlXIncludeCtxtPtr ctxt ;
} ;
2003-02-04 22:48:53 +00:00
/**
* xmlXIncludeMergeOneEntity :
* @ ent : the entity
* @ doc : the including doc
* @ nr : the entity name
*
* Inplements the merge of one entity
*/
static void
2003-02-13 11:02:08 +00:00
xmlXIncludeMergeEntity ( xmlEntityPtr ent , xmlXIncludeMergeDataPtr data ,
2003-02-04 22:48:53 +00:00
xmlChar * name ATTRIBUTE_UNUSED ) {
2003-02-13 11:02:08 +00:00
xmlEntityPtr ret , prev ;
xmlDocPtr doc ;
xmlXIncludeCtxtPtr ctxt ;
2003-02-04 22:48:53 +00:00
2003-02-13 11:02:08 +00:00
if ( ( ent = = NULL ) | | ( data = = NULL ) )
return ;
ctxt = data - > ctxt ;
doc = data - > doc ;
if ( ( ctxt = = NULL ) | | ( doc = = NULL ) )
2003-02-04 22:48:53 +00:00
return ;
2003-02-13 11:02:08 +00:00
switch ( ent - > etype ) {
case XML_INTERNAL_PARAMETER_ENTITY :
case XML_EXTERNAL_PARAMETER_ENTITY :
case XML_INTERNAL_PREDEFINED_ENTITY :
return ;
case XML_INTERNAL_GENERAL_ENTITY :
case XML_EXTERNAL_GENERAL_PARSED_ENTITY :
case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY :
break ;
}
2003-02-04 22:48:53 +00:00
ret = xmlAddDocEntity ( doc , ent - > name , ent - > etype , ent - > ExternalID ,
ent - > SystemID , ent - > content ) ;
if ( ret ! = NULL ) {
if ( ent - > URI ! = NULL )
ret - > URI = xmlStrdup ( ent - > URI ) ;
2003-02-13 11:02:08 +00:00
} else {
prev = xmlGetDocEntity ( doc , ent - > name ) ;
if ( prev ! = NULL ) {
if ( ent - > etype ! = prev - > etype )
goto error ;
if ( ( ent - > SystemID ! = NULL ) & & ( prev - > SystemID ! = NULL ) ) {
if ( ! xmlStrEqual ( ent - > SystemID , prev - > SystemID ) )
goto error ;
2003-03-29 16:41:55 +00:00
} else if ( ( ent - > ExternalID ! = NULL ) & &
( prev - > ExternalID ! = NULL ) ) {
2003-02-13 11:02:08 +00:00
if ( ! xmlStrEqual ( ent - > ExternalID , prev - > ExternalID ) )
goto error ;
2003-02-24 18:16:47 +00:00
} else if ( ( ent - > content ! = NULL ) & & ( prev - > content ! = NULL ) ) {
if ( ! xmlStrEqual ( ent - > content , prev - > content ) )
goto error ;
2003-02-13 11:02:08 +00:00
} else {
goto error ;
}
}
2003-02-04 22:48:53 +00:00
}
2003-02-13 11:02:08 +00:00
return ;
error :
2003-03-31 16:09:37 +00:00
switch ( ent - > etype ) {
case XML_INTERNAL_PARAMETER_ENTITY :
case XML_EXTERNAL_PARAMETER_ENTITY :
case XML_INTERNAL_PREDEFINED_ENTITY :
case XML_INTERNAL_GENERAL_ENTITY :
case XML_EXTERNAL_GENERAL_PARSED_ENTITY :
return ;
case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY :
break ;
}
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , ( xmlNodePtr ) ent , XML_XINCLUDE_ENTITY_DEF_MISMATCH ,
" mismatch in redefinition of entity %s \n " ,
ent - > name ) ;
2003-02-04 22:48:53 +00:00
}
/**
* xmlXIncludeMergeEntities :
* @ ctxt : an XInclude context
* @ doc : the including doc
* @ from : the included doc
*
* Inplements the entity merge
*
* Returns 0 if merge succeeded , - 1 if some processing failed
*/
static int
xmlXIncludeMergeEntities ( xmlXIncludeCtxtPtr ctxt , xmlDocPtr doc ,
xmlDocPtr from ) {
xmlNodePtr cur ;
xmlDtdPtr target , source ;
if ( ctxt = = NULL )
return ( - 1 ) ;
if ( ( from = = NULL ) | | ( from - > intSubset = = NULL ) )
return ( 0 ) ;
target = doc - > intSubset ;
if ( target = = NULL ) {
cur = xmlDocGetRootElement ( doc ) ;
if ( cur = = NULL )
return ( - 1 ) ;
target = xmlCreateIntSubset ( doc , cur - > name , NULL , NULL ) ;
if ( target = = NULL )
return ( - 1 ) ;
}
source = from - > intSubset ;
if ( ( source ! = NULL ) & & ( source - > entities ! = NULL ) ) {
2003-02-13 11:02:08 +00:00
xmlXIncludeMergeData data ;
data . ctxt = ctxt ;
data . doc = doc ;
2003-02-04 22:48:53 +00:00
xmlHashScan ( ( xmlHashTablePtr ) source - > entities ,
2003-02-13 11:02:08 +00:00
( xmlHashScanner ) xmlXIncludeMergeEntity , & data ) ;
2003-02-04 22:48:53 +00:00
}
source = from - > extSubset ;
if ( ( source ! = NULL ) & & ( source - > entities ! = NULL ) ) {
2003-02-13 11:02:08 +00:00
xmlXIncludeMergeData data ;
data . ctxt = ctxt ;
data . doc = doc ;
2003-02-04 22:48:53 +00:00
/*
* don ' t duplicate existing stuff when external subsets are the same
*/
if ( ( ! xmlStrEqual ( target - > ExternalID , source - > ExternalID ) ) & &
( ! xmlStrEqual ( target - > SystemID , source - > SystemID ) ) ) {
xmlHashScan ( ( xmlHashTablePtr ) source - > entities ,
2003-02-13 11:02:08 +00:00
( xmlHashScanner ) xmlXIncludeMergeEntity , & data ) ;
2003-02-04 22:48:53 +00:00
}
}
return ( 0 ) ;
}
2001-02-23 17:55:21 +00:00
/**
* 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 14:11:30 +00:00
*
* Returns 0 in case of success , - 1 in case of failure
2001-02-23 17:55:21 +00:00
*/
2002-08-14 14:11:30 +00:00
static int
2001-02-23 17:55:21 +00:00
xmlXIncludeLoadDoc ( xmlXIncludeCtxtPtr ctxt , const xmlChar * url , int nr ) {
xmlDocPtr doc ;
xmlURIPtr uri ;
xmlChar * URL ;
xmlChar * fragment = NULL ;
2002-09-05 10:52:10 +00:00
int i = 0 ;
2004-03-08 14:42:31 +00:00
# ifdef LIBXML_XPTR_ENABLED
int saveFlags ;
# endif
2002-09-05 10:52:10 +00:00
# ifdef DEBUG_XINCLUDE
xmlGenericError ( xmlGenericErrorContext , " Loading doc %s:%d \n " , url , nr ) ;
# endif
2001-02-23 17:55:21 +00:00
/*
* Check the URL and remove any fragment identifier
*/
uri = xmlParseURI ( ( const char * ) url ) ;
if ( uri = = NULL ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , ctxt - > incTab [ nr ] - > ref ,
XML_XINCLUDE_HREF_URI ,
" invalid value URI %s \n " , url ) ;
2002-08-14 14:11:30 +00:00
return ( - 1 ) ;
2001-02-23 17:55:21 +00:00
}
if ( uri - > fragment ! = NULL ) {
fragment = ( xmlChar * ) uri - > fragment ;
uri - > fragment = NULL ;
}
2003-12-24 11:06:25 +00:00
if ( ( ctxt - > incTab ! = NULL ) & & ( ctxt - > incTab [ nr ] ! = NULL ) & &
( ctxt - > incTab [ nr ] - > fragment ! = NULL ) ) {
if ( fragment ! = NULL ) xmlFree ( fragment ) ;
fragment = xmlStrdup ( ctxt - > incTab [ nr ] - > fragment ) ;
}
2001-02-23 17:55:21 +00:00
URL = xmlSaveUri ( uri ) ;
xmlFreeURI ( uri ) ;
if ( URL = = NULL ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , ctxt - > incTab [ nr ] - > ref ,
XML_XINCLUDE_HREF_URI ,
" invalid value URI %s \n " , url ) ;
2001-02-23 17:55:21 +00:00
if ( fragment ! = NULL )
xmlFree ( fragment ) ;
2002-08-14 14:11:30 +00:00
return ( - 1 ) ;
2001-02-23 17:55:21 +00:00
}
/*
* Handling of references to the local document are done
* directly through ctxt - > doc .
*/
2003-02-13 11:02:08 +00:00
if ( ( URL [ 0 ] = = 0 ) | | ( URL [ 0 ] = = ' # ' ) | |
( ( ctxt - > doc ! = NULL ) & & ( xmlStrEqual ( URL , ctxt - > doc - > URL ) ) ) ) {
2001-02-23 17:55:21 +00:00
doc = NULL ;
goto loaded ;
}
/*
* Prevent reloading twice the document .
*/
2002-09-05 10:52:10 +00:00
for ( i = 0 ; i < ctxt - > incNr ; i + + ) {
if ( ( xmlStrEqual ( URL , ctxt - > incTab [ i ] - > URI ) ) & &
( ctxt - > incTab [ i ] - > doc ! = NULL ) ) {
doc = ctxt - > incTab [ i ] - > doc ;
# ifdef DEBUG_XINCLUDE
printf ( " Already loaded %s \n " , URL ) ;
# endif
2001-02-23 17:55:21 +00:00
goto loaded ;
}
}
2002-09-05 10:52:10 +00:00
2001-02-23 17:55:21 +00:00
/*
* Load it .
*/
2002-09-05 10:52:10 +00:00
# ifdef DEBUG_XINCLUDE
printf ( " loading %s \n " , URL ) ;
# endif
2004-03-08 14:42:31 +00:00
# ifdef LIBXML_XPTR_ENABLED
/*
* If this is an XPointer evaluation , we want to assure that
* all entities have been resolved prior to processing the
* referenced document
*/
saveFlags = ctxt - > parseFlags ;
if ( fragment ! = NULL ) { /* if this is an XPointer eval */
ctxt - > parseFlags | = XML_PARSE_NOENT ;
}
# endif
2003-08-14 15:44:40 +00:00
doc = xmlXIncludeParseFile ( ctxt , ( const char * ) URL ) ;
2004-03-08 14:42:31 +00:00
# ifdef LIBXML_XPTR_ENABLED
ctxt - > parseFlags = saveFlags ;
# endif
2001-02-23 17:55:21 +00:00
if ( doc = = NULL ) {
xmlFree ( URL ) ;
if ( fragment ! = NULL )
xmlFree ( fragment ) ;
2002-08-14 14:11:30 +00:00
return ( - 1 ) ;
2001-02-23 17:55:21 +00:00
}
2002-09-05 10:52:10 +00:00
ctxt - > incTab [ nr ] - > doc = doc ;
2004-07-26 00:20:13 +00:00
/*
* It ' s possible that the requested URL has been mapped to a
* completely different location ( e . g . through a catalog entry ) .
* To check for this , we compare the URL with that of the doc
* and change it if they disagree ( bug 146988 ) .
*/
if ( ! xmlStrEqual ( URL , doc - > URL ) ) {
xmlFree ( URL ) ;
URL = xmlStrdup ( doc - > URL ) ;
}
2003-08-14 15:44:40 +00:00
for ( i = nr + 1 ; i < ctxt - > incNr ; i + + ) {
if ( xmlStrEqual ( URL , ctxt - > incTab [ i ] - > URI ) ) {
ctxt - > incTab [ nr ] - > count + + ;
# ifdef DEBUG_XINCLUDE
printf ( " Increasing %s count since reused \n " , URL ) ;
# endif
break ;
}
}
2002-09-05 10:52:10 +00:00
/*
2003-02-04 22:48:53 +00:00
* Make sure we have all entities fixed up
2002-09-05 10:52:10 +00:00
*/
2003-02-04 22:48:53 +00:00
xmlXIncludeMergeEntities ( ctxt , ctxt - > doc , doc ) ;
2002-09-05 10:52:10 +00:00
/*
* We don ' t need the DTD anymore , free up space
if ( doc - > intSubset ! = NULL ) {
xmlUnlinkNode ( ( xmlNodePtr ) doc - > intSubset ) ;
xmlFreeNode ( ( xmlNodePtr ) doc - > intSubset ) ;
doc - > intSubset = NULL ;
}
if ( doc - > extSubset ! = NULL ) {
xmlUnlinkNode ( ( xmlNodePtr ) doc - > extSubset ) ;
xmlFreeNode ( ( xmlNodePtr ) doc - > extSubset ) ;
doc - > extSubset = NULL ;
}
*/
xmlXIncludeRecurseDoc ( ctxt , doc , URL ) ;
2001-02-23 17:55:21 +00:00
loaded :
if ( fragment = = NULL ) {
/*
* Add the top children list as the replacement copy .
*/
if ( doc = = NULL )
2001-06-09 14:19:02 +00:00
{
/* Hopefully a DTD declaration won't be copied from
* the same document */
2002-09-05 10:52:10 +00:00
ctxt - > incTab [ nr ] - > inc = xmlCopyNodeList ( ctxt - > doc - > children ) ;
2001-06-09 14:19:02 +00:00
} else {
2002-09-05 10:52:10 +00:00
ctxt - > incTab [ nr ] - > inc = xmlXIncludeCopyNodeList ( ctxt , ctxt - > doc ,
2002-02-10 11:57:22 +00:00
doc , doc - > children ) ;
2001-06-09 14:19:02 +00:00
}
2003-09-01 20:59:40 +00:00
}
# ifdef LIBXML_XPTR_ENABLED
else {
2001-02-23 17:55:21 +00:00
/*
* Computes the XPointer expression and make a copy used
* as the replacement copy .
*/
xmlXPathObjectPtr xptr ;
xmlXPathContextPtr xptrctxt ;
2001-06-19 18:09:42 +00:00
xmlNodeSetPtr set ;
2001-02-23 17:55:21 +00:00
if ( doc = = NULL ) {
2002-09-05 10:52:10 +00:00
xptrctxt = xmlXPtrNewContext ( ctxt - > doc , ctxt - > incTab [ nr ] - > ref ,
NULL ) ;
2001-02-23 17:55:21 +00:00
} else {
xptrctxt = xmlXPtrNewContext ( doc , NULL , NULL ) ;
}
if ( xptrctxt = = NULL ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , ctxt - > incTab [ nr ] - > ref ,
XML_XINCLUDE_XPTR_FAILED ,
2003-11-19 16:24:26 +00:00
" could not create XPointer context \n " , NULL ) ;
2001-02-23 17:55:21 +00:00
xmlFree ( URL ) ;
xmlFree ( fragment ) ;
2002-08-14 14:11:30 +00:00
return ( - 1 ) ;
2001-02-23 17:55:21 +00:00
}
xptr = xmlXPtrEval ( fragment , xptrctxt ) ;
if ( xptr = = NULL ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , ctxt - > incTab [ nr ] - > ref ,
XML_XINCLUDE_XPTR_FAILED ,
" XPointer evaluation failed: #%s \n " ,
fragment ) ;
2001-02-23 17:55:21 +00:00
xmlXPathFreeContext ( xptrctxt ) ;
xmlFree ( URL ) ;
xmlFree ( fragment ) ;
2002-08-14 14:11:30 +00:00
return ( - 1 ) ;
2001-02-23 17:55:21 +00:00
}
2001-06-19 18:09:42 +00: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 :
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , ctxt - > incTab [ nr ] - > ref ,
XML_XINCLUDE_XPTR_RESULT ,
" XPointer is not a range: #%s \n " ,
fragment ) ;
2001-06-19 18:09:42 +00:00
xmlXPathFreeContext ( xptrctxt ) ;
xmlFree ( URL ) ;
xmlFree ( fragment ) ;
2002-08-14 14:11:30 +00:00
return ( - 1 ) ;
2001-06-19 18:09:42 +00:00
case XPATH_NODESET :
2003-11-03 17:13:52 +00:00
if ( ( xptr - > nodesetval = = NULL ) | |
( xptr - > nodesetval - > nodeNr < = 0 ) ) {
xmlXPathFreeContext ( xptrctxt ) ;
xmlFree ( URL ) ;
xmlFree ( fragment ) ;
return ( - 1 ) ;
}
2004-06-08 02:01:28 +00:00
2001-06-19 18:09:42 +00:00
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_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 ;
2004-06-08 02:01:28 +00:00
case XML_ELEMENT_NODE : {
xmlChar * nodeBase ;
xmlNodePtr el = set - > nodeTab [ i ] ;
nodeBase = xmlNodeGetBase ( el - > doc , el ) ;
if ( nodeBase ! = NULL ) {
if ( ! xmlStrEqual ( nodeBase , el - > doc - > URL ) )
xmlNodeSetBase ( el , nodeBase ) ;
xmlFree ( nodeBase ) ;
}
continue ;
}
2001-06-19 18:09:42 +00:00
case XML_ATTRIBUTE_NODE :
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , ctxt - > incTab [ nr ] - > ref ,
XML_XINCLUDE_XPTR_RESULT ,
" XPointer selects an attribute: #%s \n " ,
fragment ) ;
2001-06-19 18:09:42 +00:00
set - > nodeTab [ i ] = NULL ;
continue ;
case XML_NAMESPACE_DECL :
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , ctxt - > incTab [ nr ] - > ref ,
XML_XINCLUDE_XPTR_RESULT ,
" XPointer selects a namespace: #%s \n " ,
fragment ) ;
2001-06-19 18:09:42 +00:00
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 :
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , ctxt - > incTab [ nr ] - > ref ,
XML_XINCLUDE_XPTR_RESULT ,
" XPointer selects unexpected nodes: #%s \n " ,
fragment ) ;
2001-06-19 18:09:42 +00:00
set - > nodeTab [ i ] = NULL ;
set - > nodeTab [ i ] = NULL ;
continue ; /* for */
}
}
}
2003-02-13 11:02:08 +00:00
if ( doc = = NULL ) {
ctxt - > incTab [ nr ] - > xptr = xptr ;
ctxt - > incTab [ nr ] - > inc = NULL ;
} else {
ctxt - > incTab [ nr ] - > inc =
xmlXIncludeCopyXPointer ( ctxt , ctxt - > doc , doc , xptr ) ;
xmlXPathFreeObject ( xptr ) ;
}
2001-02-23 17:55:21 +00:00
xmlXPathFreeContext ( xptrctxt ) ;
xmlFree ( fragment ) ;
}
2003-09-01 20:59:40 +00:00
# endif
2002-08-14 14:45:25 +00:00
/*
* Do the xml : base fixup if needed
*/
if ( ( doc ! = NULL ) & & ( URL ! = NULL ) & & ( xmlStrchr ( URL , ( xmlChar ) ' / ' ) ) ) {
xmlNodePtr node ;
2005-06-01 03:37:59 +00:00
xmlChar * base ;
2004-06-08 02:01:28 +00:00
xmlChar * curBase ;
2002-08-14 14:45:25 +00:00
2004-06-07 08:57:27 +00:00
/*
2005-06-01 03:37:59 +00:00
* The base is only adjusted if " necessary " , i . e . if the xinclude node
* has a base specified , or the URL is relative
2004-06-07 08:57:27 +00:00
*/
2005-06-01 03:37:59 +00:00
base = xmlGetNsProp ( ctxt - > incTab [ nr ] - > ref , BAD_CAST " base " ,
XML_XML_NAMESPACE ) ;
if ( base = = NULL ) {
/*
* No xml : base on the xinclude node , so we check whether the
* URI base is different than ( relative to ) the context base
*/
curBase = xmlBuildRelativeURI ( URL , ctxt - > base ) ;
if ( curBase = = NULL ) { /* Error return */
xmlXIncludeErr ( ctxt , ctxt - > incTab [ nr ] - > ref ,
2004-06-07 08:57:27 +00:00
XML_XINCLUDE_HREF_URI ,
" trying to build relative URI from %s \n " , URL ) ;
2005-06-01 03:37:59 +00:00
} else {
/* If the URI doesn't contain a slash, it's not relative */
if ( ! xmlStrchr ( curBase , ( xmlChar ) ' / ' ) )
xmlFree ( curBase ) ;
else
base = curBase ;
}
}
if ( base ! = NULL ) { /* Adjustment may be needed */
node = ctxt - > incTab [ nr ] - > inc ;
while ( node ! = NULL ) {
/* Only work on element nodes */
if ( node - > type = = XML_ELEMENT_NODE ) {
curBase = xmlNodeGetBase ( node - > doc , node ) ;
/* If no current base, set it */
if ( curBase = = NULL ) {
xmlNodeSetBase ( node , base ) ;
} else {
/*
* If the current base is the same as the
* URL of the document , then reset it to be
* the specified xml : base or the relative URI
*/
if ( xmlStrEqual ( curBase , node - > doc - > URL ) ) {
xmlNodeSetBase ( node , base ) ;
} else {
/*
* If the element already has an xml : base
* set , then relativise it if necessary
*/
xmlChar * xmlBase ;
xmlBase = xmlGetNsProp ( node ,
BAD_CAST " base " ,
XML_XML_NAMESPACE ) ;
if ( xmlBase ! = NULL ) {
xmlChar * relBase ;
relBase = xmlBuildURI ( xmlBase , base ) ;
if ( relBase = = NULL ) { /* error */
xmlXIncludeErr ( ctxt ,
ctxt - > incTab [ nr ] - > ref ,
XML_XINCLUDE_HREF_URI ,
" trying to rebuild base from %s \n " ,
xmlBase ) ;
} else {
xmlNodeSetBase ( node , relBase ) ;
xmlFree ( relBase ) ;
}
xmlFree ( xmlBase ) ;
}
}
xmlFree ( curBase ) ;
2004-06-08 02:01:28 +00:00
}
2004-06-07 08:57:27 +00:00
}
2005-06-01 03:37:59 +00:00
node = node - > next ;
2004-06-07 08:57:27 +00:00
}
2005-06-01 03:37:59 +00:00
xmlFree ( base ) ;
2002-08-14 14:45:25 +00:00
}
}
2002-09-05 10:52:10 +00:00
if ( ( nr < ctxt - > incNr ) & & ( ctxt - > incTab [ nr ] - > doc ! = NULL ) & &
( ctxt - > incTab [ nr ] - > count < = 1 ) ) {
# ifdef DEBUG_XINCLUDE
printf ( " freeing %s \n " , ctxt - > incTab [ nr ] - > doc - > URL ) ;
# endif
xmlFreeDoc ( ctxt - > incTab [ nr ] - > doc ) ;
ctxt - > incTab [ nr ] - > doc = NULL ;
}
2001-02-23 17:55:21 +00:00
xmlFree ( URL ) ;
2002-08-14 14:11:30 +00:00
return ( 0 ) ;
2001-02-23 17:55:21 +00: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 14:11:30 +00:00
*
* Returns 0 in case of success , - 1 in case of failure
2001-02-23 17:55:21 +00:00
*/
2002-08-14 14:11:30 +00:00
static int
2001-02-23 17:55:21 +00:00
xmlXIncludeLoadTxt ( xmlXIncludeCtxtPtr ctxt , const xmlChar * url , int nr ) {
xmlParserInputBufferPtr buf ;
xmlNodePtr node ;
xmlURIPtr uri ;
xmlChar * URL ;
int i ;
2002-11-20 13:28:31 +00:00
xmlChar * encoding = NULL ;
2003-07-31 14:47:38 +00:00
xmlCharEncoding enc = ( xmlCharEncoding ) 0 ;
2002-11-20 13:28:31 +00:00
2001-02-23 17:55:21 +00:00
/*
* Check the URL and remove any fragment identifier
*/
uri = xmlParseURI ( ( const char * ) url ) ;
if ( uri = = NULL ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , ctxt - > incTab [ nr ] - > ref , XML_XINCLUDE_HREF_URI ,
" invalid value URI %s \n " , url ) ;
2002-08-14 14:11:30 +00:00
return ( - 1 ) ;
2001-02-23 17:55:21 +00:00
}
if ( uri - > fragment ! = NULL ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , ctxt - > incTab [ nr ] - > ref , XML_XINCLUDE_TEXT_FRAGMENT ,
" fragment identifier forbidden for text: %s \n " ,
( const xmlChar * ) uri - > fragment ) ;
2001-02-23 17:55:21 +00:00
xmlFreeURI ( uri ) ;
2002-08-14 14:11:30 +00:00
return ( - 1 ) ;
2001-02-23 17:55:21 +00:00
}
URL = xmlSaveUri ( uri ) ;
xmlFreeURI ( uri ) ;
if ( URL = = NULL ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , ctxt - > incTab [ nr ] - > ref , XML_XINCLUDE_HREF_URI ,
" invalid value URI %s \n " , url ) ;
2002-08-14 14:11:30 +00:00
return ( - 1 ) ;
2001-02-23 17:55:21 +00:00
}
/*
* Handling of references to the local document are done
* directly through ctxt - > doc .
*/
if ( URL [ 0 ] = = 0 ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , ctxt - > incTab [ nr ] - > ref ,
XML_XINCLUDE_TEXT_DOCUMENT ,
" text serialization of document not available \n " , NULL ) ;
2001-02-23 17:55:21 +00:00
xmlFree ( URL ) ;
2002-08-14 14:11:30 +00:00
return ( - 1 ) ;
2001-02-23 17:55:21 +00: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 ;
}
}
2002-11-20 13:28:31 +00:00
/*
* Try to get the encoding if available
*/
if ( ( ctxt - > incTab [ nr ] ! = NULL ) & & ( ctxt - > incTab [ nr ] - > ref ! = NULL ) ) {
encoding = xmlGetProp ( ctxt - > incTab [ nr ] - > ref , XINCLUDE_PARSE_ENCODING ) ;
}
if ( encoding ! = NULL ) {
/*
* TODO : we should not have to remap to the xmlCharEncoding
* predefined set , a better interface than
* xmlParserInputBufferCreateFilename should allow any
* encoding supported by iconv
*/
enc = xmlParseCharEncoding ( ( const char * ) encoding ) ;
if ( enc = = XML_CHAR_ENCODING_ERROR ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , ctxt - > incTab [ nr ] - > ref ,
XML_XINCLUDE_UNKNOWN_ENCODING ,
" encoding %s not supported \n " , encoding ) ;
2002-11-20 13:28:31 +00:00
xmlFree ( encoding ) ;
xmlFree ( URL ) ;
return ( - 1 ) ;
}
xmlFree ( encoding ) ;
}
2001-02-23 17:55:21 +00:00
/*
* Load it .
*/
2002-11-20 13:28:31 +00:00
buf = xmlParserInputBufferCreateFilename ( ( const char * ) URL , enc ) ;
2001-02-23 17:55:21 +00:00
if ( buf = = NULL ) {
xmlFree ( URL ) ;
2002-08-14 14:11:30 +00:00
return ( - 1 ) ;
2001-02-23 17:55:21 +00: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 ) ;
2002-11-20 13:28:31 +00:00
for ( i = 0 ; i < len ; ) {
int cur ;
int l ;
cur = xmlStringCurrentChar ( NULL , & content [ i ] , & l ) ;
if ( ! IS_CHAR ( cur ) ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , ctxt - > incTab [ nr ] - > ref ,
XML_XINCLUDE_INVALID_CHAR ,
" %s contains invalid char \n " , URL ) ;
2001-02-23 17:55:21 +00:00
} else {
2002-11-20 13:28:31 +00:00
xmlNodeAddContentLen ( node , & content [ i ] , l ) ;
2001-02-23 17:55:21 +00:00
}
2002-11-20 13:28:31 +00:00
i + = l ;
2001-02-23 17:55:21 +00:00
}
xmlBufferShrink ( buf - > buffer , len ) ;
}
xmlFreeParserInputBuffer ( buf ) ;
xmlXIncludeAddTxt ( ctxt , node , URL ) ;
loaded :
/*
* Add the element as the replacement copy .
*/
2002-09-05 10:52:10 +00:00
ctxt - > incTab [ nr ] - > inc = node ;
2001-02-23 17:55:21 +00:00
xmlFree ( URL ) ;
2002-08-14 14:11:30 +00:00
return ( 0 ) ;
}
/**
* xmlXIncludeLoadFallback :
* @ ctxt : the XInclude context
* @ fallback : the fallback node
* @ nr : the xinclude node number
*
2002-09-05 10:52:10 +00:00
* Load the content of the fallback node , and store the result
2002-08-14 14:11:30 +00:00
* in the XInclude context
*
* Returns 0 in case of success , - 1 in case of failure
*/
static int
xmlXIncludeLoadFallback ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr fallback , int nr ) {
2004-01-02 14:59:41 +00:00
xmlXIncludeCtxtPtr newctxt ;
int ret = 0 ;
2002-08-14 14:11:30 +00:00
if ( ( fallback = = NULL ) | | ( ctxt = = NULL ) )
return ( - 1 ) ;
2004-02-06 09:33:59 +00:00
if ( fallback - > children ! = NULL ) {
/*
* It ' s possible that the fallback also has ' includes '
* ( Bug 129969 ) , so we re - process the fallback just in case
*/
newctxt = xmlXIncludeNewContext ( ctxt - > doc ) ;
if ( newctxt = = NULL )
return ( - 1 ) ;
2004-11-05 10:03:46 +00:00
newctxt - > base = xmlStrdup ( ctxt - > base ) ; /* Inherit the base from the existing context */
2004-02-06 09:33:59 +00:00
xmlXIncludeSetFlags ( newctxt , ctxt - > parseFlags ) ;
ret = xmlXIncludeDoProcess ( newctxt , ctxt - > doc , fallback - > children ) ;
2004-04-17 14:58:15 +00:00
if ( ctxt - > nbErrors > 0 )
2004-02-06 09:33:59 +00:00
ret = - 1 ;
2004-04-17 14:58:15 +00:00
else if ( ret > 0 )
ret = 0 ; /* xmlXIncludeDoProcess can return +ve number */
2004-02-06 09:33:59 +00:00
xmlXIncludeFreeContext ( newctxt ) ;
2004-10-26 16:06:51 +00:00
ctxt - > incTab [ nr ] - > inc = xmlDocCopyNodeList ( ctxt - > doc ,
fallback - > children ) ;
2004-02-06 09:33:59 +00:00
} else {
ctxt - > incTab [ nr ] - > inc = NULL ;
2004-02-08 04:12:49 +00:00
ctxt - > incTab [ nr ] - > emptyFb = 1 ; /* flag empty callback */
2004-02-06 09:33:59 +00:00
}
2004-01-02 14:59:41 +00:00
return ( ret ) ;
2001-02-23 17:55:21 +00:00
}
/************************************************************************
* *
* XInclude Processing *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlXIncludePreProcessNode :
* @ ctxt : an XInclude context
* @ node : an XInclude node
*
2001-05-23 13:44:21 +00:00
* Implement the XInclude preprocessing , currently just adding the element
* for further processing .
2001-02-23 17:55:21 +00:00
*
* Returns the result list or NULL in case of error
*/
2001-03-24 17:00:36 +00:00
static xmlNodePtr
2001-02-23 17:55:21 +00:00
xmlXIncludePreProcessNode ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr node ) {
xmlXIncludeAddNode ( ctxt , node ) ;
2005-07-28 23:49:35 +00:00
return ( NULL ) ;
2001-02-23 17:55:21 +00:00
}
/**
* xmlXIncludeLoadNode :
* @ ctxt : an XInclude context
* @ nr : the node number
*
* Find and load the infoset replacement for the given node .
*
2001-12-31 16:16:02 +00:00
* Returns 0 if substitution succeeded , - 1 if some processing failed
2001-02-23 17:55:21 +00:00
*/
2001-03-24 17:00:36 +00:00
static int
2001-02-23 17:55:21 +00:00
xmlXIncludeLoadNode ( xmlXIncludeCtxtPtr ctxt , int nr ) {
xmlNodePtr cur ;
xmlChar * href ;
xmlChar * parse ;
xmlChar * base ;
2004-06-07 08:57:27 +00:00
xmlChar * oldBase ;
2001-02-23 17:55:21 +00:00
xmlChar * URI ;
int xml = 1 ; /* default Issue 64 */
2002-08-14 14:11:30 +00:00
int ret ;
2001-02-23 17:55:21 +00:00
if ( ctxt = = NULL )
return ( - 1 ) ;
if ( ( nr < 0 ) | | ( nr > = ctxt - > incNr ) )
return ( - 1 ) ;
2002-09-05 10:52:10 +00:00
cur = ctxt - > incTab [ nr ] - > ref ;
2001-02-23 17:55:21 +00:00
if ( cur = = NULL )
return ( - 1 ) ;
/*
* read the attributes
*/
2003-12-08 17:41:29 +00:00
href = xmlXIncludeGetProp ( ctxt , cur , XINCLUDE_HREF ) ;
2001-02-23 17:55:21 +00:00
if ( href = = NULL ) {
2004-01-25 19:54:59 +00:00
href = xmlStrdup ( BAD_CAST " " ) ; /* @@@@ href is now optional */
if ( href = = NULL )
return ( - 1 ) ;
2001-02-23 17:55:21 +00:00
}
2003-12-08 17:41:29 +00:00
parse = xmlXIncludeGetProp ( ctxt , cur , XINCLUDE_PARSE ) ;
2001-02-23 17:55:21 +00:00
if ( parse ! = NULL ) {
if ( xmlStrEqual ( parse , XINCLUDE_PARSE_XML ) )
xml = 1 ;
else if ( xmlStrEqual ( parse , XINCLUDE_PARSE_TEXT ) )
xml = 0 ;
else {
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , ctxt - > incTab [ nr ] - > ref ,
XML_XINCLUDE_PARSE_VALUE ,
" invalid value %s for 'parse' \n " , parse ) ;
2001-02-23 17:55:21 +00:00
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 16:16:02 +00:00
* Some escaping may be needed
2001-02-23 17:55:21 +00:00
*/
escbase = xmlURIEscape ( base ) ;
eschref = xmlURIEscape ( href ) ;
URI = xmlBuildURI ( eschref , escbase ) ;
if ( escbase ! = NULL )
xmlFree ( escbase ) ;
if ( eschref ! = NULL )
xmlFree ( eschref ) ;
}
if ( URI = = NULL ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , ctxt - > incTab [ nr ] - > ref ,
XML_XINCLUDE_HREF_URI , " failed build URL \n " , NULL ) ;
2001-02-23 17:55:21 +00:00
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
/*
2004-06-07 08:57:27 +00:00
* Save the base for this include ( saving the current one )
2001-02-23 17:55:21 +00:00
*/
2004-06-07 08:57:27 +00:00
oldBase = ctxt - > base ;
ctxt - > base = base ;
2001-02-23 17:55:21 +00:00
if ( xml ) {
2002-08-14 14:11:30 +00:00
ret = xmlXIncludeLoadDoc ( ctxt , URI , nr ) ;
2001-02-23 17:55:21 +00:00
/* xmlXIncludeGetFragment(ctxt, cur, URI); */
} else {
2002-08-14 14:11:30 +00:00
ret = xmlXIncludeLoadTxt ( ctxt , URI , nr ) ;
}
2004-06-07 08:57:27 +00:00
/*
* Restore the original base before checking for fallback
*/
ctxt - > base = oldBase ;
2002-08-14 14:11:30 +00:00
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 ) ) & &
2003-12-08 17:41:29 +00:00
( ( xmlStrEqual ( children - > ns - > href , XINCLUDE_NS ) ) | |
( xmlStrEqual ( children - > ns - > href , XINCLUDE_OLD_NS ) ) ) ) {
2002-08-14 14:11:30 +00:00
ret = xmlXIncludeLoadFallback ( ctxt , children , nr ) ;
2003-12-31 14:05:15 +00:00
if ( ret = = 0 )
2002-08-14 14:11:30 +00:00
break ;
}
children = children - > next ;
}
}
if ( ret < 0 ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , ctxt - > incTab [ nr ] - > ref ,
XML_XINCLUDE_NO_FALLBACK ,
" could not load %s, and no fallback was found \n " ,
URI ) ;
2001-02-23 17:55:21 +00: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 16:16:02 +00:00
* Returns 0 if substitution succeeded , - 1 if some processing failed
2001-02-23 17:55:21 +00:00
*/
2001-03-24 17:00:36 +00:00
static int
2001-02-23 17:55:21 +00:00
xmlXIncludeIncludeNode ( xmlXIncludeCtxtPtr ctxt , int nr ) {
2003-02-13 11:02:08 +00:00
xmlNodePtr cur , end , list , tmp ;
2001-02-23 17:55:21 +00:00
if ( ctxt = = NULL )
return ( - 1 ) ;
if ( ( nr < 0 ) | | ( nr > = ctxt - > incNr ) )
return ( - 1 ) ;
2002-09-05 10:52:10 +00:00
cur = ctxt - > incTab [ nr ] - > ref ;
2001-02-23 17:55:21 +00:00
if ( cur = = NULL )
return ( - 1 ) ;
2003-02-13 11:02:08 +00:00
/*
* 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 ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , ctxt - > incTab [ nr ] - > ref ,
XML_XINCLUDE_MULTIPLE_ROOT ,
" XInclude error: would result in multiple root nodes \n " ,
NULL ) ;
2003-02-13 11:02:08 +00:00
return ( - 1 ) ;
}
}
2004-08-16 12:34:50 +00:00
if ( ctxt - > parseFlags & XML_PARSE_NOXINCNODE ) {
/*
* Add the list of nodes
*/
while ( list ! = NULL ) {
end = list ;
list = list - > next ;
2001-02-23 17:55:21 +00:00
2004-08-16 12:34:50 +00:00
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 ;
2004-10-26 16:06:51 +00:00
end = xmlNewDocNode ( cur - > doc , cur - > ns , cur - > name , NULL ) ;
2004-08-16 12:34:50 +00:00
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 ) ;
2001-02-23 17:55:21 +00:00
2004-08-16 12:34:50 +00:00
/*
* Add the list of nodes
*/
while ( list ! = NULL ) {
cur = list ;
list = list - > next ;
xmlAddPrevSibling ( end , cur ) ;
}
2001-02-23 17:55:21 +00:00
}
2002-02-10 11:57:22 +00:00
2001-02-23 17:55:21 +00:00
return ( 0 ) ;
}
/**
* xmlXIncludeTestNode :
2003-02-13 11:02:08 +00:00
* @ ctxt : the XInclude processing context
2001-02-23 17:55:21 +00:00
* @ node : an XInclude node
*
* test if the node is an XInclude node
*
* Returns 1 true , 0 otherwise
*/
2001-03-24 17:00:36 +00:00
static int
2003-02-13 11:02:08 +00:00
xmlXIncludeTestNode ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr node ) {
2001-02-23 17:55:21 +00:00
if ( node = = NULL )
return ( 0 ) ;
2003-07-06 17:35:43 +00:00
if ( node - > type ! = XML_ELEMENT_NODE )
return ( 0 ) ;
2001-02-23 17:55:21 +00:00
if ( node - > ns = = NULL )
return ( 0 ) ;
2003-12-08 17:41:29 +00:00
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 ) {
2004-02-09 12:39:02 +00:00
#if 0 /* wait for the XML Core Working Group to get something stable ! */
2003-12-08 17:41:29 +00:00
xmlXIncludeWarn ( ctxt , node , XML_XINCLUDE_DEPRECATED_NS ,
" Deprecated XInclude namespace found, use %s " ,
XINCLUDE_NS ) ;
2004-02-09 12:39:02 +00:00
# endif
2003-12-09 11:35:37 +00:00
ctxt - > legacy = 1 ;
2003-12-08 17:41:29 +00:00
}
}
2003-02-13 11:02:08 +00:00
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 ) & &
2003-12-08 17:41:29 +00:00
( ( xmlStrEqual ( child - > ns - > href , XINCLUDE_NS ) ) | |
( xmlStrEqual ( child - > ns - > href , XINCLUDE_OLD_NS ) ) ) ) {
2003-02-13 11:02:08 +00:00
if ( xmlStrEqual ( child - > name , XINCLUDE_NODE ) ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , node ,
XML_XINCLUDE_INCLUDE_IN_INCLUDE ,
" %s has an 'include' child \n " ,
XINCLUDE_NODE ) ;
2003-02-13 11:02:08 +00:00
return ( 0 ) ;
}
if ( xmlStrEqual ( child - > name , XINCLUDE_FALLBACK ) ) {
nb_fallback + + ;
}
}
child = child - > next ;
}
if ( nb_fallback > 1 ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , node , XML_XINCLUDE_FALLBACKS_IN_INCLUDE ,
" %s has multiple fallback children \n " ,
XINCLUDE_NODE ) ;
2003-02-13 11:02:08 +00:00
return ( 0 ) ;
}
return ( 1 ) ;
}
if ( xmlStrEqual ( node - > name , XINCLUDE_FALLBACK ) ) {
if ( ( node - > parent = = NULL ) | |
( node - > parent - > type ! = XML_ELEMENT_NODE ) | |
( node - > parent - > ns = = NULL ) | |
2003-12-08 17:41:29 +00:00
( ( ! xmlStrEqual ( node - > parent - > ns - > href , XINCLUDE_NS ) ) & &
( ! xmlStrEqual ( node - > parent - > ns - > href , XINCLUDE_OLD_NS ) ) ) | |
2003-02-13 11:02:08 +00:00
( ! xmlStrEqual ( node - > parent - > name , XINCLUDE_NODE ) ) ) {
2003-10-08 22:38:13 +00:00
xmlXIncludeErr ( ctxt , node ,
XML_XINCLUDE_FALLBACK_NOT_IN_INCLUDE ,
" %s is not the child of an 'include' \n " ,
XINCLUDE_FALLBACK ) ;
2003-02-13 11:02:08 +00:00
}
}
}
2001-02-23 17:55:21 +00:00
return ( 0 ) ;
}
/**
2001-05-23 13:44:21 +00:00
* xmlXIncludeDoProcess :
2003-02-13 11:02:08 +00:00
* @ ctxt : the XInclude processing context
2001-02-23 17:55:21 +00:00
* @ doc : an XML document
2003-07-22 20:52:14 +00:00
* @ tree : the top of the tree to process
2001-02-23 17:55:21 +00:00
*
* Implement the XInclude substitution on the XML document @ doc
*
2001-12-31 16:16:02 +00:00
* Returns 0 if no substitution were done , - 1 if some processing failed
2001-02-23 17:55:21 +00:00
* or the number of substitutions done .
*/
2001-05-23 13:44:21 +00:00
static int
2003-07-22 20:52:14 +00:00
xmlXIncludeDoProcess ( xmlXIncludeCtxtPtr ctxt , xmlDocPtr doc , xmlNodePtr tree ) {
2001-02-23 17:55:21 +00:00
xmlNodePtr cur ;
int ret = 0 ;
2005-08-10 13:39:10 +00:00
int i , start ;
2001-02-23 17:55:21 +00:00
2003-07-22 20:52:14 +00:00
if ( ( doc = = NULL ) | | ( tree = = NULL ) )
2001-02-23 17:55:21 +00:00
return ( - 1 ) ;
if ( ctxt = = NULL )
return ( - 1 ) ;
2003-02-13 11:02:08 +00:00
if ( doc - > URL ! = NULL ) {
ret = xmlXIncludeURLPush ( ctxt , doc - > URL ) ;
if ( ret < 0 )
return ( - 1 ) ;
}
2005-08-10 13:39:10 +00:00
if ( tree )
start = ctxt - > incNr ;
else
start = ctxt - > incBase ;
2003-02-13 11:02:08 +00:00
2001-02-23 17:55:21 +00:00
/*
* First phase : lookup the elements in the document
*/
2003-07-22 20:52:14 +00:00
cur = tree ;
2003-02-13 11:02:08 +00:00
if ( xmlXIncludeTestNode ( ctxt , cur ) = = 1 )
2001-02-23 17:55:21 +00:00
xmlXIncludePreProcessNode ( ctxt , cur ) ;
2004-05-12 09:33:23 +00:00
while ( ( cur ! = NULL ) & & ( cur ! = tree - > parent ) ) {
2001-02-23 17:55:21 +00:00
/* TODO: need to work on entities -> stack */
if ( ( cur - > children ! = NULL ) & &
2003-07-06 17:35:43 +00:00
( cur - > children - > type ! = XML_ENTITY_DECL ) & &
( cur - > children - > type ! = XML_XINCLUDE_START ) & &
( cur - > children - > type ! = XML_XINCLUDE_END ) ) {
2001-02-23 17:55:21 +00:00
cur = cur - > children ;
2003-02-13 11:02:08 +00:00
if ( xmlXIncludeTestNode ( ctxt , cur ) )
2001-02-23 17:55:21 +00:00
xmlXIncludePreProcessNode ( ctxt , cur ) ;
} else if ( cur - > next ! = NULL ) {
cur = cur - > next ;
2003-02-13 11:02:08 +00:00
if ( xmlXIncludeTestNode ( ctxt , cur ) )
2001-02-23 17:55:21 +00:00
xmlXIncludePreProcessNode ( ctxt , cur ) ;
} else {
2004-04-16 08:11:26 +00:00
if ( cur = = tree )
break ;
2001-02-23 17:55:21 +00:00
do {
cur = cur - > parent ;
2004-05-12 09:33:23 +00:00
if ( ( cur = = NULL ) | | ( cur = = tree - > parent ) )
break ; /* do */
2001-02-23 17:55:21 +00:00
if ( cur - > next ! = NULL ) {
cur = cur - > next ;
2003-02-13 11:02:08 +00:00
if ( xmlXIncludeTestNode ( ctxt , cur ) )
2001-02-23 17:55:21 +00:00
xmlXIncludePreProcessNode ( ctxt , cur ) ;
break ; /* do */
}
} while ( cur ! = NULL ) ;
}
}
/*
* Second Phase : collect the infosets fragments
*/
2005-08-10 13:39:10 +00:00
for ( i = start ; i < ctxt - > incNr ; i + + ) {
2001-02-23 17:55:21 +00:00
xmlXIncludeLoadNode ( ctxt , i ) ;
2003-02-07 13:01:54 +00:00
ret + + ;
2001-02-23 17:55:21 +00:00
}
/*
* Third phase : extend the original document infoset .
2004-02-06 11:24:44 +00:00
*
* 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 .
*
2001-02-23 17:55:21 +00:00
*/
2004-02-06 11:24:44 +00:00
for ( i = ctxt - > incBase ; i < ctxt - > incNr ; i + + ) {
2004-02-08 04:12:49 +00:00
if ( ( ctxt - > incTab [ i ] - > inc ! = NULL ) | |
( ctxt - > incTab [ i ] - > xptr ! = NULL ) | |
( ctxt - > incTab [ i ] - > emptyFb ! = 0 ) ) /* (empty fallback) */
2003-02-13 11:02:08 +00:00
xmlXIncludeIncludeNode ( ctxt , i ) ;
2001-02-23 17:55:21 +00:00
}
2003-02-13 11:02:08 +00:00
if ( doc - > URL ! = NULL )
xmlXIncludeURLPop ( ctxt ) ;
2001-05-23 13:44:21 +00:00
return ( ret ) ;
}
/**
2003-12-09 11:35:37 +00:00
* 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 .
*/
int
xmlXIncludeSetFlags ( xmlXIncludeCtxtPtr ctxt , int flags ) {
if ( ctxt = = NULL )
return ( - 1 ) ;
ctxt - > parseFlags = flags ;
return ( 0 ) ;
}
/**
* xmlXIncludeProcessFlags :
2001-05-23 13:44:21 +00:00
* @ doc : an XML document
2003-12-09 11:35:37 +00:00
* @ flags : a set of xmlParserOption used for parsing XML includes
2001-05-23 13:44:21 +00:00
*
* Implement the XInclude substitution on the XML document @ doc
*
2001-12-31 16:16:02 +00:00
* Returns 0 if no substitution were done , - 1 if some processing failed
2001-05-23 13:44:21 +00:00
* or the number of substitutions done .
*/
int
2003-12-09 11:35:37 +00:00
xmlXIncludeProcessFlags ( xmlDocPtr doc , int flags ) {
2001-05-23 13:44:21 +00:00
xmlXIncludeCtxtPtr ctxt ;
2003-07-22 20:52:14 +00:00
xmlNodePtr tree ;
2001-05-23 13:44:21 +00:00
int ret = 0 ;
if ( doc = = NULL )
return ( - 1 ) ;
2003-07-22 20:52:14 +00:00
tree = xmlDocGetRootElement ( doc ) ;
if ( tree = = NULL )
return ( - 1 ) ;
2001-05-23 13:44:21 +00:00
ctxt = xmlXIncludeNewContext ( doc ) ;
if ( ctxt = = NULL )
return ( - 1 ) ;
2004-11-05 10:03:46 +00:00
ctxt - > base = xmlStrdup ( ( xmlChar * ) doc - > URL ) ;
2003-12-09 11:35:37 +00:00
xmlXIncludeSetFlags ( ctxt , flags ) ;
2003-07-22 20:52:14 +00:00
ret = xmlXIncludeDoProcess ( ctxt , doc , tree ) ;
if ( ( ret > = 0 ) & & ( ctxt - > nbErrors > 0 ) )
ret = - 1 ;
xmlXIncludeFreeContext ( ctxt ) ;
return ( ret ) ;
}
/**
2003-12-09 11:35:37 +00:00
* 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 .
*/
int
xmlXIncludeProcess ( xmlDocPtr doc ) {
return ( xmlXIncludeProcessFlags ( doc , 0 ) ) ;
}
/**
* xmlXIncludeProcessTreeFlags :
2003-07-22 20:52:14 +00:00
* @ tree : a node in an XML document
2003-12-09 11:35:37 +00:00
* @ flags : a set of xmlParserOption used for parsing XML includes
2003-07-22 20:52:14 +00:00
*
* 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 .
*/
int
2003-12-09 11:35:37 +00:00
xmlXIncludeProcessTreeFlags ( xmlNodePtr tree , int flags ) {
2003-07-22 20:52:14 +00:00
xmlXIncludeCtxtPtr ctxt ;
int ret = 0 ;
if ( ( tree = = NULL ) | | ( tree - > doc = = NULL ) )
return ( - 1 ) ;
ctxt = xmlXIncludeNewContext ( tree - > doc ) ;
if ( ctxt = = NULL )
return ( - 1 ) ;
2004-06-07 08:57:27 +00:00
ctxt - > base = xmlNodeGetBase ( tree - > doc , tree ) ;
2003-12-09 11:35:37 +00:00
xmlXIncludeSetFlags ( ctxt , flags ) ;
2003-07-22 20:52:14 +00:00
ret = xmlXIncludeDoProcess ( ctxt , tree - > doc , tree ) ;
2003-02-11 18:03:05 +00:00
if ( ( ret > = 0 ) & & ( ctxt - > nbErrors > 0 ) )
ret = - 1 ;
2001-05-23 13:44:21 +00:00
2001-02-23 17:55:21 +00:00
xmlXIncludeFreeContext ( ctxt ) ;
return ( ret ) ;
}
2003-12-09 11:35:37 +00:00
/**
* xmlXIncludeProcessTree :
* @ tree : a node in an XML document
*
* 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 .
*/
int
xmlXIncludeProcessTree ( xmlNodePtr tree ) {
return ( xmlXIncludeProcessTreeFlags ( tree , 0 ) ) ;
}
2003-11-03 12:31:38 +00:00
/**
* xmlXIncludeProcessNode :
* @ ctxt : an existing XInclude context
* @ node : a node in an XML document
*
* Implement the XInclude substitution for the given subtree reusing
* the informations and data coming from the given context .
*
* Returns 0 if no substitution were done , - 1 if some processing failed
* or the number of substitutions done .
*/
int
xmlXIncludeProcessNode ( xmlXIncludeCtxtPtr ctxt , xmlNodePtr node ) {
int ret = 0 ;
if ( ( node = = NULL ) | | ( node - > doc = = NULL ) | | ( ctxt = = NULL ) )
return ( - 1 ) ;
ret = xmlXIncludeDoProcess ( ctxt , node - > doc , node ) ;
if ( ( ret > = 0 ) & & ( ctxt - > nbErrors > 0 ) )
ret = - 1 ;
return ( ret ) ;
}
2001-02-23 17:55:21 +00:00
# else /* !LIBXML_XINCLUDE_ENABLED */
# endif
2005-04-01 13:11:58 +00:00
# define bottom_xinclude
# include "elfgcchack.h"