2001-02-23 20:55:21 +03:00
/*
* tree . c : implemetation of access function for an XML tree .
*
* 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
*
* 14 Nov 2000 ht - Changed the name of function xmlBufferWriteChar under VMS
* as it was similar to xmlBufferWriteCHAR when compiling without case
* sensitivity .
*
*/
2001-04-21 20:57:29 +04:00
# include "libxml.h"
2001-02-23 20:55:21 +03:00
# include <string.h> /* for memset() only ! */
# ifdef HAVE_CTYPE_H
# include <ctype.h>
# endif
# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# endif
# ifdef HAVE_ZLIB_H
# include <zlib.h>
# endif
# include <libxml/xmlmemory.h>
# include <libxml/tree.h>
# include <libxml/parser.h>
2001-07-09 20:01:19 +04:00
# include <libxml/uri.h>
2001-02-23 20:55:21 +03:00
# include <libxml/entities.h>
# include <libxml/valid.h>
# include <libxml/xmlerror.h>
2001-04-11 15:28:06 +04:00
# include <libxml/parserInternals.h>
2001-10-17 19:58:35 +04:00
# include <libxml/globals.h>
2001-02-23 20:55:21 +03:00
2001-03-24 20:00:36 +03:00
xmlNsPtr xmlNewReconciliedNs ( xmlDocPtr doc , xmlNodePtr tree , xmlNsPtr ns ) ;
/************************************************************************
* *
* A few static variables and macros *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-13 13:15:48 +04:00
/* #undef xmlStringText */
2001-07-16 04:06:07 +04:00
const xmlChar xmlStringText [ ] = { ' t ' , ' e ' , ' x ' , ' t ' , 0 } ;
2001-10-13 13:15:48 +04:00
/* #undef xmlStringTextNoenc */
2001-07-16 04:06:07 +04:00
const xmlChar xmlStringTextNoenc [ ] =
2001-02-23 20:55:21 +03:00
{ ' t ' , ' e ' , ' x ' , ' t ' , ' n ' , ' o ' , ' e ' , ' n ' , ' c ' , 0 } ;
2001-10-13 13:15:48 +04:00
/* #undef xmlStringComment */
2001-07-16 04:06:07 +04:00
const xmlChar xmlStringComment [ ] = { ' c ' , ' o ' , ' m ' , ' m ' , ' e ' , ' n ' , ' t ' , 0 } ;
2001-02-23 20:55:21 +03:00
static int xmlCompressMode = 0 ;
static int xmlCheckDTD = 1 ;
# define UPDATE_LAST_CHILD_AND_PARENT(n) if ((n) != NULL) { \
xmlNodePtr ulccur = ( n ) - > children ; \
if ( ulccur = = NULL ) { \
( n ) - > last = NULL ; \
} else { \
while ( ulccur - > next ! = NULL ) { \
ulccur - > parent = ( n ) ; \
ulccur = ulccur - > next ; \
} \
ulccur - > parent = ( n ) ; \
( n ) - > last = ulccur ; \
} }
/* #define DEBUG_BUFFER */
/* #define DEBUG_TREE */
/************************************************************************
* *
* Allocation and deallocation of basic structures *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlSetBufferAllocationScheme :
* @ scheme : allocation method to use
*
* Set the buffer allocation method . Types are
* XML_BUFFER_ALLOC_EXACT - use exact sizes , keeps memory usage down
* XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed ,
* improves performance
*/
void
xmlSetBufferAllocationScheme ( xmlBufferAllocationScheme scheme ) {
xmlBufferAllocScheme = scheme ;
}
/**
* xmlGetBufferAllocationScheme :
*
* Types are
* XML_BUFFER_ALLOC_EXACT - use exact sizes , keeps memory usage down
* XML_BUFFER_ALLOC_DOUBLEIT - double buffer when extra needed ,
* improves performance
*
* Returns the current allocation scheme
*/
xmlBufferAllocationScheme
2001-03-24 20:00:36 +03:00
xmlGetBufferAllocationScheme ( void ) {
2001-04-16 18:08:07 +04:00
return ( xmlBufferAllocScheme ) ;
2001-02-23 20:55:21 +03:00
}
/**
* xmlNewNs :
* @ node : the element carrying the namespace
* @ href : the URI associated
* @ prefix : the prefix for the namespace
*
* Creation of a new Namespace . This function will refuse to create
* a namespace with a similar prefix than an existing one present on this
* node .
* We use href = = NULL in the case of an element creation where the namespace
* was not defined .
* Returns returns a new namespace pointer or NULL
*/
xmlNsPtr
xmlNewNs ( xmlNodePtr node , const xmlChar * href , const xmlChar * prefix ) {
xmlNsPtr cur ;
if ( ( node ! = NULL ) & & ( node - > type ! = XML_ELEMENT_NODE ) )
return ( NULL ) ;
2001-10-05 13:18:14 +04:00
if ( ( prefix ! = NULL ) & & ( xmlStrEqual ( prefix , BAD_CAST " xml " ) ) )
return ( NULL ) ;
2001-02-23 20:55:21 +03:00
/*
* Allocate a new Namespace and fill the fields .
*/
cur = ( xmlNsPtr ) xmlMalloc ( sizeof ( xmlNs ) ) ;
if ( cur = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewNs : malloc failed \n " ) ;
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlNs ) ) ;
cur - > type = XML_LOCAL_NAMESPACE ;
if ( href ! = NULL )
cur - > href = xmlStrdup ( href ) ;
if ( prefix ! = NULL )
cur - > prefix = xmlStrdup ( prefix ) ;
/*
* Add it at the end to preserve parsing order . . .
* and checks for existing use of the prefix
*/
if ( node ! = NULL ) {
if ( node - > nsDef = = NULL ) {
node - > nsDef = cur ;
} else {
xmlNsPtr prev = node - > nsDef ;
if ( ( ( prev - > prefix = = NULL ) & & ( cur - > prefix = = NULL ) ) | |
( xmlStrEqual ( prev - > prefix , cur - > prefix ) ) ) {
xmlFreeNs ( cur ) ;
return ( NULL ) ;
}
while ( prev - > next ! = NULL ) {
prev = prev - > next ;
if ( ( ( prev - > prefix = = NULL ) & & ( cur - > prefix = = NULL ) ) | |
( xmlStrEqual ( prev - > prefix , cur - > prefix ) ) ) {
xmlFreeNs ( cur ) ;
return ( NULL ) ;
}
}
prev - > next = cur ;
}
}
return ( cur ) ;
}
/**
* xmlSetNs :
* @ node : a node in the document
* @ ns : a namespace pointer
*
* Associate a namespace to a node , a posteriori .
*/
void
xmlSetNs ( xmlNodePtr node , xmlNsPtr ns ) {
if ( node = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlSetNs: node == NULL \n " ) ;
# endif
return ;
}
node - > ns = ns ;
}
/**
* xmlFreeNs :
* @ cur : the namespace pointer
*
* Free up the structures associated to a namespace
*/
void
xmlFreeNs ( xmlNsPtr cur ) {
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlFreeNs : ns == NULL \n " ) ;
# endif
return ;
}
if ( cur - > href ! = NULL ) xmlFree ( ( char * ) cur - > href ) ;
if ( cur - > prefix ! = NULL ) xmlFree ( ( char * ) cur - > prefix ) ;
xmlFree ( cur ) ;
}
/**
* xmlFreeNsList :
* @ cur : the first namespace pointer
*
* Free up all the structures associated to the chained namespaces .
*/
void
xmlFreeNsList ( xmlNsPtr cur ) {
xmlNsPtr next ;
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlFreeNsList : ns == NULL \n " ) ;
# endif
return ;
}
while ( cur ! = NULL ) {
next = cur - > next ;
xmlFreeNs ( cur ) ;
cur = next ;
}
}
/**
* xmlNewDtd :
* @ doc : the document pointer
* @ name : the DTD name
* @ ExternalID : the external ID
* @ SystemID : the system ID
*
* Creation of a new DTD for the external subset . To create an
* internal subset , use xmlCreateIntSubset ( ) .
*
* Returns a pointer to the new DTD structure
*/
xmlDtdPtr
xmlNewDtd ( xmlDocPtr doc , const xmlChar * name ,
const xmlChar * ExternalID , const xmlChar * SystemID ) {
xmlDtdPtr cur ;
if ( ( doc ! = NULL ) & & ( doc - > extSubset ! = NULL ) ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewDtd(%s): document %s already have a DTD %s \n " ,
/* !!! */ ( char * ) name , doc - > name ,
/* !!! */ ( char * ) doc - > extSubset - > name ) ;
# endif
return ( NULL ) ;
}
/*
* Allocate a new DTD and fill the fields .
*/
cur = ( xmlDtdPtr ) xmlMalloc ( sizeof ( xmlDtd ) ) ;
if ( cur = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewDtd : malloc failed \n " ) ;
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlDtd ) ) ;
cur - > type = XML_DTD_NODE ;
if ( name ! = NULL )
cur - > name = xmlStrdup ( name ) ;
if ( ExternalID ! = NULL )
cur - > ExternalID = xmlStrdup ( ExternalID ) ;
if ( SystemID ! = NULL )
cur - > SystemID = xmlStrdup ( SystemID ) ;
if ( doc ! = NULL )
doc - > extSubset = cur ;
cur - > doc = doc ;
return ( cur ) ;
}
/**
* xmlGetIntSubset :
* @ doc : the document pointer
*
* Get the internal subset of a document
* Returns a pointer to the DTD structure or NULL if not found
*/
xmlDtdPtr
xmlGetIntSubset ( xmlDocPtr doc ) {
xmlNodePtr cur ;
if ( doc = = NULL )
return ( NULL ) ;
cur = doc - > children ;
while ( cur ! = NULL ) {
if ( cur - > type = = XML_DTD_NODE )
return ( ( xmlDtdPtr ) cur ) ;
cur = cur - > next ;
}
return ( ( xmlDtdPtr ) doc - > intSubset ) ;
}
/**
* xmlCreateIntSubset :
* @ doc : the document pointer
* @ name : the DTD name
2001-03-10 15:32:04 +03:00
* @ ExternalID : the external ( PUBLIC ) ID
2001-02-23 20:55:21 +03:00
* @ SystemID : the system ID
*
* Create the internal subset of a document
* Returns a pointer to the new DTD structure
*/
xmlDtdPtr
xmlCreateIntSubset ( xmlDocPtr doc , const xmlChar * name ,
const xmlChar * ExternalID , const xmlChar * SystemID ) {
xmlDtdPtr cur ;
if ( ( doc ! = NULL ) & & ( xmlGetIntSubset ( doc ) ! = NULL ) ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlCreateIntSubset(): document %s already have an internal subset \n " ,
doc - > name ) ;
# endif
return ( NULL ) ;
}
/*
* Allocate a new DTD and fill the fields .
*/
cur = ( xmlDtdPtr ) xmlMalloc ( sizeof ( xmlDtd ) ) ;
if ( cur = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewDtd : malloc failed \n " ) ;
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlDtd ) ) ;
cur - > type = XML_DTD_NODE ;
if ( name ! = NULL )
cur - > name = xmlStrdup ( name ) ;
if ( ExternalID ! = NULL )
cur - > ExternalID = xmlStrdup ( ExternalID ) ;
if ( SystemID ! = NULL )
cur - > SystemID = xmlStrdup ( SystemID ) ;
if ( doc ! = NULL ) {
doc - > intSubset = cur ;
cur - > parent = doc ;
cur - > doc = doc ;
if ( doc - > children = = NULL ) {
doc - > children = ( xmlNodePtr ) cur ;
doc - > last = ( xmlNodePtr ) cur ;
} else {
if ( doc - > type = = XML_HTML_DOCUMENT_NODE ) {
2001-03-10 15:32:04 +03:00
xmlNodePtr prev ;
2001-02-23 20:55:21 +03:00
prev = doc - > children ;
prev - > prev = ( xmlNodePtr ) cur ;
cur - > next = prev ;
doc - > children = ( xmlNodePtr ) cur ;
} else {
2001-03-10 15:32:04 +03:00
xmlNodePtr next ;
next = doc - > children ;
while ( ( next ! = NULL ) & & ( next - > type ! = XML_ELEMENT_NODE ) )
next = next - > next ;
if ( next = = NULL ) {
cur - > prev = doc - > last ;
cur - > prev - > next = ( xmlNodePtr ) cur ;
cur - > next = NULL ;
doc - > last = ( xmlNodePtr ) cur ;
} else {
cur - > next = next ;
cur - > prev = next - > prev ;
if ( cur - > prev = = NULL )
doc - > children = ( xmlNodePtr ) cur ;
else
cur - > prev - > next = ( xmlNodePtr ) cur ;
next - > prev = ( xmlNodePtr ) cur ;
}
2001-02-23 20:55:21 +03:00
}
}
}
return ( cur ) ;
}
/**
* xmlFreeDtd :
* @ cur : the DTD structure to free up
*
* Free a DTD structure .
*/
void
xmlFreeDtd ( xmlDtdPtr cur ) {
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlFreeDtd : DTD == NULL \n " ) ;
# endif
return ;
}
if ( cur - > children ! = NULL ) {
xmlNodePtr next , c = cur - > children ;
/*
* Cleanup all the DTD comments they are not in the Dtd
* indexes .
*/
while ( c ! = NULL ) {
next = c - > next ;
if ( c - > type = = XML_COMMENT_NODE ) {
xmlUnlinkNode ( c ) ;
xmlFreeNode ( c ) ;
}
c = next ;
}
}
if ( cur - > name ! = NULL ) xmlFree ( ( char * ) cur - > name ) ;
if ( cur - > SystemID ! = NULL ) xmlFree ( ( char * ) cur - > SystemID ) ;
if ( cur - > ExternalID ! = NULL ) xmlFree ( ( char * ) cur - > ExternalID ) ;
/* TODO !!! */
if ( cur - > notations ! = NULL )
xmlFreeNotationTable ( ( xmlNotationTablePtr ) cur - > notations ) ;
if ( cur - > elements ! = NULL )
xmlFreeElementTable ( ( xmlElementTablePtr ) cur - > elements ) ;
if ( cur - > attributes ! = NULL )
xmlFreeAttributeTable ( ( xmlAttributeTablePtr ) cur - > attributes ) ;
if ( cur - > entities ! = NULL )
xmlFreeEntitiesTable ( ( xmlEntitiesTablePtr ) cur - > entities ) ;
if ( cur - > pentities ! = NULL )
xmlFreeEntitiesTable ( ( xmlEntitiesTablePtr ) cur - > pentities ) ;
xmlFree ( cur ) ;
}
/**
* xmlNewDoc :
* @ version : xmlChar string giving the version of XML " 1.0 "
*
2001-07-18 23:30:27 +04:00
* Creates a new XML document
*
2001-02-23 20:55:21 +03:00
* Returns a new document
*/
xmlDocPtr
xmlNewDoc ( const xmlChar * version ) {
xmlDocPtr cur ;
if ( version = = NULL )
version = ( const xmlChar * ) " 1.0 " ;
/*
* Allocate a new document and fill the fields .
*/
cur = ( xmlDocPtr ) xmlMalloc ( sizeof ( xmlDoc ) ) ;
if ( cur = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewDoc : malloc failed \n " ) ;
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlDoc ) ) ;
cur - > type = XML_DOCUMENT_NODE ;
cur - > version = xmlStrdup ( version ) ;
cur - > standalone = - 1 ;
cur - > compression = - 1 ; /* not initialized */
cur - > doc = cur ;
2001-04-11 11:50:02 +04:00
cur - > charset = XML_CHAR_ENCODING_UTF8 ;
2001-02-23 20:55:21 +03:00
return ( cur ) ;
}
/**
* xmlFreeDoc :
* @ cur : pointer to the document
* @ :
*
* Free up all the structures used by a document , tree included .
*/
void
xmlFreeDoc ( xmlDocPtr cur ) {
2001-06-19 15:07:54 +04:00
xmlDtdPtr extSubset , intSubset ;
2001-02-23 20:55:21 +03:00
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlFreeDoc : document == NULL \n " ) ;
# endif
return ;
}
2001-05-17 01:05:17 +04:00
/*
* Do this before freeing the children list to avoid ID lookups
*/
if ( cur - > ids ! = NULL ) xmlFreeIDTable ( ( xmlIDTablePtr ) cur - > ids ) ;
cur - > ids = NULL ;
if ( cur - > refs ! = NULL ) xmlFreeRefTable ( ( xmlRefTablePtr ) cur - > refs ) ;
cur - > refs = NULL ;
2001-06-19 15:07:54 +04:00
extSubset = cur - > extSubset ;
intSubset = cur - > intSubset ;
if ( extSubset ! = NULL ) {
2001-05-17 01:05:17 +04:00
xmlUnlinkNode ( ( xmlNodePtr ) cur - > extSubset ) ;
cur - > extSubset = NULL ;
2001-06-19 15:07:54 +04:00
xmlFreeDtd ( extSubset ) ;
2001-05-17 01:05:17 +04:00
}
2001-06-19 15:07:54 +04:00
if ( intSubset ! = NULL ) {
2001-05-17 01:05:17 +04:00
xmlUnlinkNode ( ( xmlNodePtr ) cur - > intSubset ) ;
cur - > intSubset = NULL ;
2001-06-19 15:07:54 +04:00
xmlFreeDtd ( intSubset ) ;
2001-05-17 01:05:17 +04:00
}
if ( cur - > children ! = NULL ) xmlFreeNodeList ( cur - > children ) ;
2001-02-23 20:55:21 +03:00
if ( cur - > version ! = NULL ) xmlFree ( ( char * ) cur - > version ) ;
if ( cur - > name ! = NULL ) xmlFree ( ( char * ) cur - > name ) ;
if ( cur - > encoding ! = NULL ) xmlFree ( ( char * ) cur - > encoding ) ;
if ( cur - > oldNs ! = NULL ) xmlFreeNsList ( cur - > oldNs ) ;
if ( cur - > URL ! = NULL ) xmlFree ( ( char * ) cur - > URL ) ;
xmlFree ( cur ) ;
}
/**
* xmlStringLenGetNodeList :
* @ doc : the document
* @ value : the value of the text
* @ len : the length of the string value
*
* Parse the value string and build the node list associated . Should
* produce a flat tree with only TEXTs and ENTITY_REFs .
* Returns a pointer to the first child
*/
xmlNodePtr
xmlStringLenGetNodeList ( xmlDocPtr doc , const xmlChar * value , int len ) {
xmlNodePtr ret = NULL , last = NULL ;
xmlNodePtr node ;
xmlChar * val ;
const xmlChar * cur = value ;
const xmlChar * q ;
xmlEntityPtr ent ;
if ( value = = NULL ) return ( NULL ) ;
q = cur ;
while ( ( * cur ! = 0 ) & & ( cur - value < len ) ) {
if ( * cur = = ' & ' ) {
/*
* Save the current text .
*/
if ( cur ! = q ) {
if ( ( last ! = NULL ) & & ( last - > type = = XML_TEXT_NODE ) ) {
xmlNodeAddContentLen ( last , q , cur - q ) ;
} else {
node = xmlNewDocTextLen ( doc , q , cur - q ) ;
if ( node = = NULL ) return ( ret ) ;
if ( last = = NULL )
last = ret = node ;
else {
last - > next = node ;
node - > prev = last ;
last = node ;
}
}
}
/*
* Read the entity string
*/
cur + + ;
q = cur ;
while ( ( * cur ! = 0 ) & & ( cur - value < len ) & & ( * cur ! = ' ; ' ) ) cur + + ;
if ( ( * cur = = 0 ) | | ( cur - value > = len ) ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlStringLenGetNodeList: unterminated entity %30s \n " , q ) ;
# endif
return ( ret ) ;
}
if ( cur ! = q ) {
/*
* Predefined entities don ' t generate nodes
*/
val = xmlStrndup ( q , cur - q ) ;
ent = xmlGetDocEntity ( doc , val ) ;
if ( ( ent ! = NULL ) & &
( ent - > etype = = XML_INTERNAL_PREDEFINED_ENTITY ) ) {
if ( last = = NULL ) {
node = xmlNewDocText ( doc , ent - > content ) ;
last = ret = node ;
} else
xmlNodeAddContent ( last , ent - > content ) ;
} else {
/*
* Create a new REFERENCE_REF node
*/
node = xmlNewReference ( doc , val ) ;
if ( node = = NULL ) {
if ( val ! = NULL ) xmlFree ( val ) ;
return ( ret ) ;
}
if ( last = = NULL )
last = ret = node ;
else {
last - > next = node ;
node - > prev = last ;
last = node ;
}
}
xmlFree ( val ) ;
}
cur + + ;
q = cur ;
} else
cur + + ;
}
if ( cur ! = q ) {
/*
* Handle the last piece of text .
*/
if ( ( last ! = NULL ) & & ( last - > type = = XML_TEXT_NODE ) ) {
xmlNodeAddContentLen ( last , q , cur - q ) ;
} else {
node = xmlNewDocTextLen ( doc , q , cur - q ) ;
if ( node = = NULL ) return ( ret ) ;
if ( last = = NULL )
last = ret = node ;
else {
last - > next = node ;
node - > prev = last ;
last = node ;
}
}
}
return ( ret ) ;
}
/**
* xmlStringGetNodeList :
* @ doc : the document
* @ value : the value of the attribute
*
* Parse the value string and build the node list associated . Should
* produce a flat tree with only TEXTs and ENTITY_REFs .
* Returns a pointer to the first child
*/
xmlNodePtr
xmlStringGetNodeList ( xmlDocPtr doc , const xmlChar * value ) {
xmlNodePtr ret = NULL , last = NULL ;
xmlNodePtr node ;
xmlChar * val ;
const xmlChar * cur = value ;
const xmlChar * q ;
xmlEntityPtr ent ;
if ( value = = NULL ) return ( NULL ) ;
q = cur ;
while ( * cur ! = 0 ) {
2001-04-11 15:28:06 +04:00
if ( cur [ 0 ] = = ' & ' ) {
int charval = 0 ;
xmlChar tmp ;
2001-02-23 20:55:21 +03:00
/*
* Save the current text .
*/
if ( cur ! = q ) {
if ( ( last ! = NULL ) & & ( last - > type = = XML_TEXT_NODE ) ) {
xmlNodeAddContentLen ( last , q , cur - q ) ;
} else {
node = xmlNewDocTextLen ( doc , q , cur - q ) ;
if ( node = = NULL ) return ( ret ) ;
if ( last = = NULL )
last = ret = node ;
else {
last - > next = node ;
node - > prev = last ;
last = node ;
}
}
}
q = cur ;
2001-04-11 15:28:06 +04:00
if ( ( cur [ 1 ] = = ' # ' ) & & ( cur [ 2 ] = = ' x ' ) ) {
cur + = 3 ;
tmp = * cur ;
while ( tmp ! = ' ; ' ) { /* Non input consuming loop */
if ( ( tmp > = ' 0 ' ) & & ( tmp < = ' 9 ' ) )
charval = charval * 16 + ( tmp - ' 0 ' ) ;
else if ( ( tmp > = ' a ' ) & & ( tmp < = ' f ' ) )
charval = charval * 16 + ( tmp - ' a ' ) + 10 ;
else if ( ( tmp > = ' A ' ) & & ( tmp < = ' F ' ) )
charval = charval * 16 + ( tmp - ' A ' ) + 10 ;
else {
xmlGenericError ( xmlGenericErrorContext ,
" xmlStringGetNodeList: incharvalid hexadecimal charvalue \n " ) ;
charval = 0 ;
break ;
}
cur + + ;
tmp = * cur ;
}
if ( tmp = = ' ; ' )
cur + + ;
q = cur ;
} else if ( cur [ 1 ] = = ' # ' ) {
cur + = 2 ;
tmp = * cur ;
while ( tmp ! = ' ; ' ) { /* Non input consuming loops */
if ( ( tmp > = ' 0 ' ) & & ( tmp < = ' 9 ' ) )
charval = charval * 10 + ( tmp - ' 0 ' ) ;
else {
xmlGenericError ( xmlGenericErrorContext ,
" xmlStringGetNodeList: incharvalid decimal charvalue \n " ) ;
charval = 0 ;
break ;
}
cur + + ;
tmp = * cur ;
}
if ( tmp = = ' ; ' )
cur + + ;
q = cur ;
} else {
2001-02-23 20:55:21 +03:00
/*
2001-04-11 15:28:06 +04:00
* Read the entity string
2001-02-23 20:55:21 +03:00
*/
2001-04-11 15:28:06 +04:00
cur + + ;
q = cur ;
while ( ( * cur ! = 0 ) & & ( * cur ! = ' ; ' ) ) cur + + ;
if ( * cur = = 0 ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlStringGetNodeList: unterminated entity %30s \n " , q ) ;
# endif
return ( ret ) ;
}
if ( cur ! = q ) {
2001-02-23 20:55:21 +03:00
/*
2001-04-11 15:28:06 +04:00
* Predefined entities don ' t generate nodes
2001-02-23 20:55:21 +03:00
*/
2001-04-11 15:28:06 +04:00
val = xmlStrndup ( q , cur - q ) ;
ent = xmlGetDocEntity ( doc , val ) ;
if ( ( ent ! = NULL ) & &
( ent - > etype = = XML_INTERNAL_PREDEFINED_ENTITY ) ) {
if ( last = = NULL ) {
node = xmlNewDocText ( doc , ent - > content ) ;
last = ret = node ;
} else
xmlNodeAddContent ( last , ent - > content ) ;
} else {
/*
* Create a new REFERENCE_REF node
*/
node = xmlNewReference ( doc , val ) ;
if ( node = = NULL ) {
if ( val ! = NULL ) xmlFree ( val ) ;
return ( ret ) ;
}
if ( last = = NULL ) {
last = ret = node ;
} else {
last = xmlAddNextSibling ( last , node ) ;
}
2001-02-23 20:55:21 +03:00
}
2001-04-11 15:28:06 +04:00
xmlFree ( val ) ;
}
cur + + ;
q = cur ;
}
if ( charval ! = 0 ) {
xmlChar buf [ 10 ] ;
int len ;
len = xmlCopyCharMultiByte ( buf , charval ) ;
buf [ len ] = 0 ;
node = xmlNewDocText ( doc , buf ) ;
if ( node ! = NULL ) {
if ( last = = NULL ) {
2001-02-23 20:55:21 +03:00
last = ret = node ;
2001-04-11 15:28:06 +04:00
} else {
last = xmlAddNextSibling ( last , node ) ;
2001-02-23 20:55:21 +03:00
}
}
2001-04-11 15:28:06 +04:00
charval = 0 ;
2001-02-23 20:55:21 +03:00
}
2001-04-11 15:28:06 +04:00
} else
2001-02-23 20:55:21 +03:00
cur + + ;
}
2001-05-11 21:41:21 +04:00
if ( ( cur ! = q ) | | ( ret = = NULL ) ) {
2001-02-23 20:55:21 +03:00
/*
* Handle the last piece of text .
*/
if ( ( last ! = NULL ) & & ( last - > type = = XML_TEXT_NODE ) ) {
xmlNodeAddContentLen ( last , q , cur - q ) ;
} else {
node = xmlNewDocTextLen ( doc , q , cur - q ) ;
if ( node = = NULL ) return ( ret ) ;
2001-04-11 15:28:06 +04:00
if ( last = = NULL ) {
2001-02-23 20:55:21 +03:00
last = ret = node ;
2001-04-11 15:28:06 +04:00
} else {
last = xmlAddNextSibling ( last , node ) ;
2001-02-23 20:55:21 +03:00
}
}
}
return ( ret ) ;
}
/**
* xmlNodeListGetString :
* @ doc : the document
* @ list : a Node list
* @ inLine : should we replace entity contents or show their external form
*
* Returns the string equivalent to the text contained in the Node list
* made of TEXTs and ENTITY_REFs
* Returns a pointer to the string copy , the calller must free it .
*/
xmlChar *
xmlNodeListGetString ( xmlDocPtr doc , xmlNodePtr list , int inLine ) {
xmlNodePtr node = list ;
xmlChar * ret = NULL ;
xmlEntityPtr ent ;
if ( list = = NULL ) return ( NULL ) ;
while ( node ! = NULL ) {
if ( ( node - > type = = XML_TEXT_NODE ) | |
( node - > type = = XML_CDATA_SECTION_NODE ) ) {
if ( inLine ) {
# ifndef XML_USE_BUFFER_CONTENT
ret = xmlStrcat ( ret , node - > content ) ;
# else
ret = xmlStrcat ( ret , xmlBufferContent ( node - > content ) ) ;
# endif
} else {
xmlChar * buffer ;
# ifndef XML_USE_BUFFER_CONTENT
buffer = xmlEncodeEntitiesReentrant ( doc , node - > content ) ;
# else
buffer = xmlEncodeEntitiesReentrant ( doc ,
xmlBufferContent ( node - > content ) ) ;
# endif
if ( buffer ! = NULL ) {
ret = xmlStrcat ( ret , buffer ) ;
xmlFree ( buffer ) ;
}
}
} else if ( node - > type = = XML_ENTITY_REF_NODE ) {
if ( inLine ) {
ent = xmlGetDocEntity ( doc , node - > name ) ;
if ( ent ! = NULL )
ret = xmlStrcat ( ret , ent - > content ) ;
else {
# ifndef XML_USE_BUFFER_CONTENT
ret = xmlStrcat ( ret , node - > content ) ;
# else
ret = xmlStrcat ( ret , xmlBufferContent ( node - > content ) ) ;
# endif
}
} else {
xmlChar buf [ 2 ] ;
buf [ 0 ] = ' & ' ; buf [ 1 ] = 0 ;
ret = xmlStrncat ( ret , buf , 1 ) ;
ret = xmlStrcat ( ret , node - > name ) ;
buf [ 0 ] = ' ; ' ; buf [ 1 ] = 0 ;
ret = xmlStrncat ( ret , buf , 1 ) ;
}
}
#if 0
else {
xmlGenericError ( xmlGenericErrorContext ,
" xmlGetNodeListString : invalide node type %d \n " ,
node - > type ) ;
}
# endif
node = node - > next ;
}
return ( ret ) ;
}
/**
* xmlNodeListGetRawString :
* @ doc : the document
* @ list : a Node list
* @ inLine : should we replace entity contents or show their external form
*
* Returns the string equivalent to the text contained in the Node list
* made of TEXTs and ENTITY_REFs , contrary to xmlNodeListGetString ( )
* this function doesn ' t do any character encoding handling .
*
* Returns a pointer to the string copy , the calller must free it .
*/
xmlChar *
xmlNodeListGetRawString ( xmlDocPtr doc , xmlNodePtr list , int inLine ) {
xmlNodePtr node = list ;
xmlChar * ret = NULL ;
xmlEntityPtr ent ;
if ( list = = NULL ) return ( NULL ) ;
while ( node ! = NULL ) {
2001-07-12 05:20:08 +04:00
if ( ( node - > type = = XML_TEXT_NODE ) | |
( node - > type = = XML_CDATA_SECTION_NODE ) ) {
2001-02-23 20:55:21 +03:00
if ( inLine ) {
# ifndef XML_USE_BUFFER_CONTENT
ret = xmlStrcat ( ret , node - > content ) ;
# else
ret = xmlStrcat ( ret , xmlBufferContent ( node - > content ) ) ;
# endif
} else {
xmlChar * buffer ;
# ifndef XML_USE_BUFFER_CONTENT
buffer = xmlEncodeSpecialChars ( doc , node - > content ) ;
# else
buffer = xmlEncodeSpecialChars ( doc ,
xmlBufferContent ( node - > content ) ) ;
# endif
if ( buffer ! = NULL ) {
ret = xmlStrcat ( ret , buffer ) ;
xmlFree ( buffer ) ;
}
}
} else if ( node - > type = = XML_ENTITY_REF_NODE ) {
if ( inLine ) {
ent = xmlGetDocEntity ( doc , node - > name ) ;
if ( ent ! = NULL )
ret = xmlStrcat ( ret , ent - > content ) ;
else {
# ifndef XML_USE_BUFFER_CONTENT
ret = xmlStrcat ( ret , node - > content ) ;
# else
ret = xmlStrcat ( ret , xmlBufferContent ( node - > content ) ) ;
# endif
}
} else {
xmlChar buf [ 2 ] ;
buf [ 0 ] = ' & ' ; buf [ 1 ] = 0 ;
ret = xmlStrncat ( ret , buf , 1 ) ;
ret = xmlStrcat ( ret , node - > name ) ;
buf [ 0 ] = ' ; ' ; buf [ 1 ] = 0 ;
ret = xmlStrncat ( ret , buf , 1 ) ;
}
}
#if 0
else {
xmlGenericError ( xmlGenericErrorContext ,
" xmlGetNodeListString : invalide node type %d \n " ,
node - > type ) ;
}
# endif
node = node - > next ;
}
return ( ret ) ;
}
/**
* xmlNewProp :
* @ node : the holding node
* @ name : the name of the attribute
* @ value : the value of the attribute
*
* Create a new property carried by a node .
* Returns a pointer to the attribute
*/
xmlAttrPtr
xmlNewProp ( xmlNodePtr node , const xmlChar * name , const xmlChar * value ) {
xmlAttrPtr cur ;
xmlDocPtr doc = NULL ;
if ( name = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewProp : name == NULL \n " ) ;
# endif
return ( NULL ) ;
}
/*
* Allocate a new property and fill the fields .
*/
cur = ( xmlAttrPtr ) xmlMalloc ( sizeof ( xmlAttr ) ) ;
if ( cur = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewProp : malloc failed \n " ) ;
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlAttr ) ) ;
cur - > type = XML_ATTRIBUTE_NODE ;
cur - > parent = node ;
if ( node ! = NULL ) {
doc = node - > doc ;
cur - > doc = doc ;
}
cur - > name = xmlStrdup ( name ) ;
if ( value ! = NULL ) {
xmlChar * buffer ;
xmlNodePtr tmp ;
buffer = xmlEncodeEntitiesReentrant ( doc , value ) ;
cur - > children = xmlStringGetNodeList ( doc , buffer ) ;
cur - > last = NULL ;
tmp = cur - > children ;
while ( tmp ! = NULL ) {
tmp - > parent = ( xmlNodePtr ) cur ;
tmp - > doc = doc ;
if ( tmp - > next = = NULL )
cur - > last = tmp ;
tmp = tmp - > next ;
}
xmlFree ( buffer ) ;
}
/*
* Add it at the end to preserve parsing order . . .
*/
if ( node ! = NULL ) {
if ( node - > properties = = NULL ) {
node - > properties = cur ;
} else {
xmlAttrPtr prev = node - > properties ;
while ( prev - > next ! = NULL ) prev = prev - > next ;
prev - > next = cur ;
cur - > prev = prev ;
}
}
return ( cur ) ;
}
/**
* xmlNewNsProp :
* @ node : the holding node
* @ ns : the namespace
* @ name : the name of the attribute
* @ value : the value of the attribute
*
* Create a new property tagged with a namespace and carried by a node .
* Returns a pointer to the attribute
*/
xmlAttrPtr
xmlNewNsProp ( xmlNodePtr node , xmlNsPtr ns , const xmlChar * name ,
const xmlChar * value ) {
xmlAttrPtr cur ;
2001-06-07 23:59:42 +04:00
xmlDocPtr doc = NULL ;
2001-02-23 20:55:21 +03:00
if ( name = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewProp : name == NULL \n " ) ;
# endif
return ( NULL ) ;
}
/*
* Allocate a new property and fill the fields .
*/
cur = ( xmlAttrPtr ) xmlMalloc ( sizeof ( xmlAttr ) ) ;
if ( cur = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewProp : malloc failed \n " ) ;
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlAttr ) ) ;
cur - > type = XML_ATTRIBUTE_NODE ;
cur - > parent = node ;
2001-06-07 23:59:42 +04:00
if ( node ! = NULL ) {
doc = node - > doc ;
cur - > doc = doc ;
}
2001-02-23 20:55:21 +03:00
cur - > ns = ns ;
cur - > name = xmlStrdup ( name ) ;
if ( value ! = NULL ) {
xmlChar * buffer ;
xmlNodePtr tmp ;
2001-06-07 23:59:42 +04:00
buffer = xmlEncodeEntitiesReentrant ( doc , value ) ;
cur - > children = xmlStringGetNodeList ( doc , buffer ) ;
2001-02-23 20:55:21 +03:00
cur - > last = NULL ;
tmp = cur - > children ;
while ( tmp ! = NULL ) {
tmp - > parent = ( xmlNodePtr ) cur ;
if ( tmp - > next = = NULL )
cur - > last = tmp ;
tmp = tmp - > next ;
}
xmlFree ( buffer ) ;
}
/*
* Add it at the end to preserve parsing order . . .
*/
if ( node ! = NULL ) {
if ( node - > properties = = NULL ) {
node - > properties = cur ;
} else {
xmlAttrPtr prev = node - > properties ;
while ( prev - > next ! = NULL ) prev = prev - > next ;
prev - > next = cur ;
cur - > prev = prev ;
}
}
return ( cur ) ;
}
/**
* xmlNewDocProp :
* @ doc : the document
* @ name : the name of the attribute
* @ value : the value of the attribute
*
* Create a new property carried by a document .
* Returns a pointer to the attribute
*/
xmlAttrPtr
xmlNewDocProp ( xmlDocPtr doc , const xmlChar * name , const xmlChar * value ) {
xmlAttrPtr cur ;
if ( name = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewProp : name == NULL \n " ) ;
# endif
return ( NULL ) ;
}
/*
* Allocate a new property and fill the fields .
*/
cur = ( xmlAttrPtr ) xmlMalloc ( sizeof ( xmlAttr ) ) ;
if ( cur = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewProp : malloc failed \n " ) ;
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlAttr ) ) ;
cur - > type = XML_ATTRIBUTE_NODE ;
cur - > name = xmlStrdup ( name ) ;
cur - > doc = doc ;
if ( value ! = NULL ) {
xmlNodePtr tmp ;
cur - > children = xmlStringGetNodeList ( doc , value ) ;
cur - > last = NULL ;
tmp = cur - > children ;
while ( tmp ! = NULL ) {
tmp - > parent = ( xmlNodePtr ) cur ;
if ( tmp - > next = = NULL )
cur - > last = tmp ;
tmp = tmp - > next ;
}
}
return ( cur ) ;
}
/**
* xmlFreePropList :
* @ cur : the first property in the list
*
* Free a property and all its siblings , all the children are freed too .
*/
void
xmlFreePropList ( xmlAttrPtr cur ) {
xmlAttrPtr next ;
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlFreePropList : property == NULL \n " ) ;
# endif
return ;
}
while ( cur ! = NULL ) {
next = cur - > next ;
xmlFreeProp ( cur ) ;
cur = next ;
}
}
/**
* xmlFreeProp :
* @ cur : an attribute
*
* Free one attribute , all the content is freed too
*/
void
xmlFreeProp ( xmlAttrPtr cur ) {
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlFreeProp : property == NULL \n " ) ;
# endif
return ;
}
/* Check for ID removal -> leading to invalid references ! */
2001-05-17 01:05:17 +04:00
if ( ( cur - > parent ! = NULL ) & & ( cur - > parent - > doc ! = NULL ) & &
( ( cur - > parent - > doc - > intSubset ! = NULL ) | |
( cur - > parent - > doc - > extSubset ! = NULL ) ) ) {
if ( xmlIsID ( cur - > parent - > doc , cur - > parent , cur ) )
xmlRemoveID ( cur - > parent - > doc , cur ) ;
}
2001-02-23 20:55:21 +03:00
if ( cur - > name ! = NULL ) xmlFree ( ( char * ) cur - > name ) ;
if ( cur - > children ! = NULL ) xmlFreeNodeList ( cur - > children ) ;
xmlFree ( cur ) ;
}
/**
* xmlRemoveProp :
* @ cur : an attribute
*
* Unlink and free one attribute , all the content is freed too
* Note this doesn ' t work for namespace definition attributes
*
* Returns 0 if success and - 1 in case of error .
*/
int
xmlRemoveProp ( xmlAttrPtr cur ) {
xmlAttrPtr tmp ;
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlRemoveProp : cur == NULL \n " ) ;
# endif
return ( - 1 ) ;
}
if ( cur - > parent = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlRemoveProp : cur->parent == NULL \n " ) ;
# endif
return ( - 1 ) ;
}
tmp = cur - > parent - > properties ;
if ( tmp = = cur ) {
cur - > parent - > properties = cur - > next ;
xmlFreeProp ( cur ) ;
return ( 0 ) ;
}
while ( tmp ! = NULL ) {
if ( tmp - > next = = cur ) {
tmp - > next = cur - > next ;
if ( tmp - > next ! = NULL )
tmp - > next - > prev = tmp ;
xmlFreeProp ( cur ) ;
return ( 0 ) ;
}
tmp = tmp - > next ;
}
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlRemoveProp : attribute not owned by its node \n " ) ;
# endif
return ( - 1 ) ;
}
/**
* xmlNewPI :
* @ name : the processing instruction name
* @ content : the PI content
*
* Creation of a processing instruction element .
* Returns a pointer to the new node object .
*/
xmlNodePtr
xmlNewPI ( const xmlChar * name , const xmlChar * content ) {
xmlNodePtr cur ;
if ( name = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewPI : name == NULL \n " ) ;
# endif
return ( NULL ) ;
}
/*
* Allocate a new node and fill the fields .
*/
cur = ( xmlNodePtr ) xmlMalloc ( sizeof ( xmlNode ) ) ;
if ( cur = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewPI : malloc failed \n " ) ;
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlNode ) ) ;
cur - > type = XML_PI_NODE ;
cur - > name = xmlStrdup ( name ) ;
if ( content ! = NULL ) {
# ifndef XML_USE_BUFFER_CONTENT
cur - > content = xmlStrdup ( content ) ;
# else
cur - > content = xmlBufferCreateSize ( 0 ) ;
xmlBufferSetAllocationScheme ( cur - > content ,
xmlGetBufferAllocationScheme ( ) ) ;
xmlBufferAdd ( cur - > content , content , - 1 ) ;
# endif
}
return ( cur ) ;
}
/**
* xmlNewNode :
* @ ns : namespace if any
* @ name : the node name
*
* Creation of a new node element . @ ns is optionnal ( NULL ) .
*
* Returns a pointer to the new node object .
*/
xmlNodePtr
xmlNewNode ( xmlNsPtr ns , const xmlChar * name ) {
xmlNodePtr cur ;
if ( name = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewNode : name == NULL \n " ) ;
# endif
return ( NULL ) ;
}
/*
* Allocate a new node and fill the fields .
*/
cur = ( xmlNodePtr ) xmlMalloc ( sizeof ( xmlNode ) ) ;
if ( cur = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewNode : malloc failed \n " ) ;
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlNode ) ) ;
cur - > type = XML_ELEMENT_NODE ;
cur - > name = xmlStrdup ( name ) ;
cur - > ns = ns ;
return ( cur ) ;
}
/**
* xmlNewDocNode :
* @ doc : the document
* @ ns : namespace if any
* @ name : the node name
* @ content : the XML text content if any
*
* Creation of a new node element within a document . @ ns and @ content
* are optionnal ( NULL ) .
* NOTE : @ content is supposed to be a piece of XML CDATA , so it allow entities
* references , but XML special chars need to be escaped first by using
* xmlEncodeEntitiesReentrant ( ) . Use xmlNewDocRawNode ( ) if you don ' t
* need entities support .
*
* Returns a pointer to the new node object .
*/
xmlNodePtr
xmlNewDocNode ( xmlDocPtr doc , xmlNsPtr ns ,
const xmlChar * name , const xmlChar * content ) {
xmlNodePtr cur ;
cur = xmlNewNode ( ns , name ) ;
if ( cur ! = NULL ) {
cur - > doc = doc ;
if ( content ! = NULL ) {
cur - > children = xmlStringGetNodeList ( doc , content ) ;
UPDATE_LAST_CHILD_AND_PARENT ( cur )
}
}
return ( cur ) ;
}
/**
* xmlNewDocRawNode :
* @ doc : the document
* @ ns : namespace if any
* @ name : the node name
* @ content : the text content if any
*
* Creation of a new node element within a document . @ ns and @ content
* are optionnal ( NULL ) .
*
* Returns a pointer to the new node object .
*/
xmlNodePtr
xmlNewDocRawNode ( xmlDocPtr doc , xmlNsPtr ns ,
const xmlChar * name , const xmlChar * content ) {
xmlNodePtr cur ;
cur = xmlNewNode ( ns , name ) ;
if ( cur ! = NULL ) {
cur - > doc = doc ;
if ( content ! = NULL ) {
cur - > children = xmlNewDocText ( doc , content ) ;
UPDATE_LAST_CHILD_AND_PARENT ( cur )
}
}
return ( cur ) ;
}
/**
* xmlNewDocFragment :
* @ doc : the document owning the fragment
*
* Creation of a new Fragment node .
* Returns a pointer to the new node object .
*/
xmlNodePtr
xmlNewDocFragment ( xmlDocPtr doc ) {
xmlNodePtr cur ;
/*
* Allocate a new DocumentFragment node and fill the fields .
*/
cur = ( xmlNodePtr ) xmlMalloc ( sizeof ( xmlNode ) ) ;
if ( cur = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewDocFragment : malloc failed \n " ) ;
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlNode ) ) ;
cur - > type = XML_DOCUMENT_FRAG_NODE ;
cur - > doc = doc ;
return ( cur ) ;
}
/**
* xmlNewText :
* @ content : the text content
*
* Creation of a new text node .
* Returns a pointer to the new node object .
*/
xmlNodePtr
xmlNewText ( const xmlChar * content ) {
xmlNodePtr cur ;
/*
* Allocate a new node and fill the fields .
*/
cur = ( xmlNodePtr ) xmlMalloc ( sizeof ( xmlNode ) ) ;
if ( cur = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewText : malloc failed \n " ) ;
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlNode ) ) ;
cur - > type = XML_TEXT_NODE ;
cur - > name = xmlStringText ;
if ( content ! = NULL ) {
# ifndef XML_USE_BUFFER_CONTENT
cur - > content = xmlStrdup ( content ) ;
# else
cur - > content = xmlBufferCreateSize ( 0 ) ;
xmlBufferSetAllocationScheme ( cur - > content ,
xmlGetBufferAllocationScheme ( ) ) ;
xmlBufferAdd ( cur - > content , content , - 1 ) ;
# endif
}
return ( cur ) ;
}
/**
* xmlNewTextChild :
* @ parent : the parent node
* @ ns : a namespace if any
* @ name : the name of the child
* @ content : the text content of the child if any .
*
* Creation of a new child element , added at the end of @ parent children list .
* @ ns and @ content parameters are optionnal ( NULL ) . If content is non NULL ,
* a child TEXT node will be created containing the string content .
*
* Returns a pointer to the new node object .
*/
xmlNodePtr
xmlNewTextChild ( xmlNodePtr parent , xmlNsPtr ns ,
const xmlChar * name , const xmlChar * content ) {
xmlNodePtr cur , prev ;
if ( parent = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewTextChild : parent == NULL \n " ) ;
# endif
return ( NULL ) ;
}
if ( name = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewTextChild : name == NULL \n " ) ;
# endif
return ( NULL ) ;
}
/*
* Allocate a new node
*/
if ( ns = = NULL )
cur = xmlNewDocRawNode ( parent - > doc , parent - > ns , name , content ) ;
else
cur = xmlNewDocRawNode ( parent - > doc , ns , name , content ) ;
if ( cur = = NULL ) return ( NULL ) ;
/*
* add the new element at the end of the children list .
*/
cur - > type = XML_ELEMENT_NODE ;
cur - > parent = parent ;
cur - > doc = parent - > doc ;
if ( parent - > children = = NULL ) {
parent - > children = cur ;
parent - > last = cur ;
} else {
prev = parent - > last ;
prev - > next = cur ;
cur - > prev = prev ;
parent - > last = cur ;
}
return ( cur ) ;
}
/**
* xmlNewCharRef :
* @ doc : the document
* @ name : the char ref string , starting with # or " &# ... ; "
*
* Creation of a new character reference node .
* Returns a pointer to the new node object .
*/
xmlNodePtr
xmlNewCharRef ( xmlDocPtr doc , const xmlChar * name ) {
xmlNodePtr cur ;
/*
* Allocate a new node and fill the fields .
*/
cur = ( xmlNodePtr ) xmlMalloc ( sizeof ( xmlNode ) ) ;
if ( cur = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewText : malloc failed \n " ) ;
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlNode ) ) ;
cur - > type = XML_ENTITY_REF_NODE ;
cur - > doc = doc ;
if ( name [ 0 ] = = ' & ' ) {
int len ;
name + + ;
len = xmlStrlen ( name ) ;
if ( name [ len - 1 ] = = ' ; ' )
cur - > name = xmlStrndup ( name , len - 1 ) ;
else
cur - > name = xmlStrndup ( name , len ) ;
} else
cur - > name = xmlStrdup ( name ) ;
return ( cur ) ;
}
/**
* xmlNewReference :
* @ doc : the document
* @ name : the reference name , or the reference string with & and ;
*
* Creation of a new reference node .
* Returns a pointer to the new node object .
*/
xmlNodePtr
xmlNewReference ( xmlDocPtr doc , const xmlChar * name ) {
xmlNodePtr cur ;
xmlEntityPtr ent ;
/*
* Allocate a new node and fill the fields .
*/
cur = ( xmlNodePtr ) xmlMalloc ( sizeof ( xmlNode ) ) ;
if ( cur = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewText : malloc failed \n " ) ;
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlNode ) ) ;
cur - > type = XML_ENTITY_REF_NODE ;
cur - > doc = doc ;
if ( name [ 0 ] = = ' & ' ) {
int len ;
name + + ;
len = xmlStrlen ( name ) ;
if ( name [ len - 1 ] = = ' ; ' )
cur - > name = xmlStrndup ( name , len - 1 ) ;
else
cur - > name = xmlStrndup ( name , len ) ;
} else
cur - > name = xmlStrdup ( name ) ;
ent = xmlGetDocEntity ( doc , cur - > name ) ;
if ( ent ! = NULL ) {
# ifndef XML_USE_BUFFER_CONTENT
cur - > content = ent - > content ;
# else
/*
* CJN 11.18 .99 this might be a problem , since the xmlBuffer gets
* a copy of this pointer . Let ' s hope we don ' t manipulate it
* later
*/
cur - > content = xmlBufferCreateSize ( 0 ) ;
xmlBufferSetAllocationScheme ( cur - > content ,
xmlGetBufferAllocationScheme ( ) ) ;
if ( ent - > content ! = NULL )
xmlBufferAdd ( cur - > content , ent - > content , - 1 ) ;
# endif
/*
* The parent pointer in entity is a Dtd pointer and thus is NOT
* updated . Not sure if this is 100 % correct .
* - George
*/
cur - > children = ( xmlNodePtr ) ent ;
cur - > last = ( xmlNodePtr ) ent ;
}
return ( cur ) ;
}
/**
* xmlNewDocText :
* @ doc : the document
* @ content : the text content
*
* Creation of a new text node within a document .
* Returns a pointer to the new node object .
*/
xmlNodePtr
xmlNewDocText ( xmlDocPtr doc , const xmlChar * content ) {
xmlNodePtr cur ;
cur = xmlNewText ( content ) ;
if ( cur ! = NULL ) cur - > doc = doc ;
return ( cur ) ;
}
/**
* xmlNewTextLen :
* @ content : the text content
* @ len : the text len .
*
2001-10-10 13:45:09 +04:00
* Creation of a new text node with an extra parameter for the content ' s length
2001-02-23 20:55:21 +03:00
* Returns a pointer to the new node object .
*/
xmlNodePtr
xmlNewTextLen ( const xmlChar * content , int len ) {
xmlNodePtr cur ;
/*
* Allocate a new node and fill the fields .
*/
cur = ( xmlNodePtr ) xmlMalloc ( sizeof ( xmlNode ) ) ;
if ( cur = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewText : malloc failed \n " ) ;
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlNode ) ) ;
cur - > type = XML_TEXT_NODE ;
cur - > name = xmlStringText ;
if ( content ! = NULL ) {
# ifndef XML_USE_BUFFER_CONTENT
cur - > content = xmlStrndup ( content , len ) ;
# else
cur - > content = xmlBufferCreateSize ( len ) ;
xmlBufferSetAllocationScheme ( cur - > content ,
xmlGetBufferAllocationScheme ( ) ) ;
xmlBufferAdd ( cur - > content , content , len ) ;
# endif
}
return ( cur ) ;
}
/**
* xmlNewDocTextLen :
* @ doc : the document
* @ content : the text content
* @ len : the text len .
*
2001-10-10 13:45:09 +04:00
* Creation of a new text node with an extra content length parameter . The
2001-02-23 20:55:21 +03:00
* text node pertain to a given document .
* Returns a pointer to the new node object .
*/
xmlNodePtr
xmlNewDocTextLen ( xmlDocPtr doc , const xmlChar * content , int len ) {
xmlNodePtr cur ;
cur = xmlNewTextLen ( content , len ) ;
if ( cur ! = NULL ) cur - > doc = doc ;
return ( cur ) ;
}
/**
* xmlNewComment :
* @ content : the comment content
*
* Creation of a new node containing a comment .
* Returns a pointer to the new node object .
*/
xmlNodePtr
xmlNewComment ( const xmlChar * content ) {
xmlNodePtr cur ;
/*
* Allocate a new node and fill the fields .
*/
cur = ( xmlNodePtr ) xmlMalloc ( sizeof ( xmlNode ) ) ;
if ( cur = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewComment : malloc failed \n " ) ;
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlNode ) ) ;
cur - > type = XML_COMMENT_NODE ;
cur - > name = xmlStringComment ;
if ( content ! = NULL ) {
# ifndef XML_USE_BUFFER_CONTENT
cur - > content = xmlStrdup ( content ) ;
# else
cur - > content = xmlBufferCreateSize ( 0 ) ;
xmlBufferSetAllocationScheme ( cur - > content ,
xmlGetBufferAllocationScheme ( ) ) ;
xmlBufferAdd ( cur - > content , content , - 1 ) ;
# endif
}
return ( cur ) ;
}
/**
* xmlNewCDataBlock :
* @ doc : the document
* @ content : the CData block content content
* @ len : the length of the block
*
* Creation of a new node containing a CData block .
* Returns a pointer to the new node object .
*/
xmlNodePtr
xmlNewCDataBlock ( xmlDocPtr doc , const xmlChar * content , int len ) {
xmlNodePtr cur ;
/*
* Allocate a new node and fill the fields .
*/
cur = ( xmlNodePtr ) xmlMalloc ( sizeof ( xmlNode ) ) ;
if ( cur = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewCDataBlock : malloc failed \n " ) ;
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlNode ) ) ;
cur - > type = XML_CDATA_SECTION_NODE ;
2001-03-24 20:00:36 +03:00
cur - > doc = doc ;
2001-02-23 20:55:21 +03:00
if ( content ! = NULL ) {
# ifndef XML_USE_BUFFER_CONTENT
cur - > content = xmlStrndup ( content , len ) ;
# else
cur - > content = xmlBufferCreateSize ( len ) ;
xmlBufferSetAllocationScheme ( cur - > content ,
xmlGetBufferAllocationScheme ( ) ) ;
xmlBufferAdd ( cur - > content , content , len ) ;
# endif
}
return ( cur ) ;
}
/**
* xmlNewDocComment :
* @ doc : the document
* @ content : the comment content
*
* Creation of a new node containing a commentwithin a document .
* Returns a pointer to the new node object .
*/
xmlNodePtr
xmlNewDocComment ( xmlDocPtr doc , const xmlChar * content ) {
xmlNodePtr cur ;
cur = xmlNewComment ( content ) ;
if ( cur ! = NULL ) cur - > doc = doc ;
return ( cur ) ;
}
/**
* xmlSetTreeDoc :
* @ tree : the top element
* @ doc : the document
*
* update all nodes under the tree to point to the right document
*/
void
xmlSetTreeDoc ( xmlNodePtr tree , xmlDocPtr doc ) {
2001-07-09 14:32:59 +04:00
xmlAttrPtr prop ;
2001-02-23 20:55:21 +03:00
if ( tree = = NULL )
return ;
if ( tree - > type = = XML_ENTITY_DECL )
return ;
if ( tree - > doc ! = doc ) {
2001-07-09 14:32:59 +04:00
prop = tree - > properties ;
while ( prop ! = NULL ) {
prop - > doc = doc ;
xmlSetListDoc ( prop - > children , doc ) ;
prop = prop - > next ;
}
2001-02-23 20:55:21 +03:00
if ( tree - > children ! = NULL )
xmlSetListDoc ( tree - > children , doc ) ;
tree - > doc = doc ;
}
}
/**
* xmlSetListDoc :
* @ tree : the first element
* @ doc : the document
*
* update all nodes in the list to point to the right document
*/
void
xmlSetListDoc ( xmlNodePtr list , xmlDocPtr doc ) {
xmlNodePtr cur ;
if ( list = = NULL )
return ;
cur = list ;
while ( cur ! = NULL ) {
if ( cur - > doc ! = doc )
xmlSetTreeDoc ( cur , doc ) ;
cur = cur - > next ;
}
}
/**
* xmlNewChild :
* @ parent : the parent node
* @ ns : a namespace if any
* @ name : the name of the child
* @ content : the XML content of the child if any .
*
* Creation of a new child element , added at the end of @ parent children list .
* @ ns and @ content parameters are optionnal ( NULL ) . If content is non NULL ,
* a child list containing the TEXTs and ENTITY_REFs node will be created .
* NOTE : @ content is supposed to be a piece of XML CDATA , so it allow entities
* references , but XML special chars need to be escaped first by using
* xmlEncodeEntitiesReentrant ( ) . Use xmlNewTextChild ( ) if entities
* support is not needed .
*
* Returns a pointer to the new node object .
*/
xmlNodePtr
xmlNewChild ( xmlNodePtr parent , xmlNsPtr ns ,
const xmlChar * name , const xmlChar * content ) {
xmlNodePtr cur , prev ;
if ( parent = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewChild : parent == NULL \n " ) ;
# endif
return ( NULL ) ;
}
if ( name = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewChild : name == NULL \n " ) ;
# endif
return ( NULL ) ;
}
/*
* Allocate a new node
*/
if ( ns = = NULL )
cur = xmlNewDocNode ( parent - > doc , parent - > ns , name , content ) ;
else
cur = xmlNewDocNode ( parent - > doc , ns , name , content ) ;
if ( cur = = NULL ) return ( NULL ) ;
/*
* add the new element at the end of the children list .
*/
cur - > type = XML_ELEMENT_NODE ;
cur - > parent = parent ;
cur - > doc = parent - > doc ;
if ( parent - > children = = NULL ) {
parent - > children = cur ;
parent - > last = cur ;
} else {
prev = parent - > last ;
prev - > next = cur ;
cur - > prev = prev ;
parent - > last = cur ;
}
return ( cur ) ;
}
/**
* xmlAddNextSibling :
* @ cur : the child node
* @ elem : the new node
*
* Add a new element @ elem as the next siblings of @ cur
* If the new element was already inserted in a document it is
* first unlinked from its existing context .
* As a result of text merging @ elem may be freed .
*
* Returns the new element or NULL in case of error .
*/
xmlNodePtr
xmlAddNextSibling ( xmlNodePtr cur , xmlNodePtr elem ) {
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlAddNextSibling : cur == NULL \n " ) ;
# endif
return ( NULL ) ;
}
if ( elem = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlAddNextSibling : elem == NULL \n " ) ;
# endif
return ( NULL ) ;
}
xmlUnlinkNode ( elem ) ;
if ( elem - > type = = XML_TEXT_NODE ) {
if ( cur - > type = = XML_TEXT_NODE ) {
# ifndef XML_USE_BUFFER_CONTENT
xmlNodeAddContent ( cur , elem - > content ) ;
# else
xmlNodeAddContent ( cur , xmlBufferContent ( elem - > content ) ) ;
# endif
xmlFreeNode ( elem ) ;
return ( cur ) ;
}
2001-09-01 00:03:19 +04:00
if ( ( cur - > next ! = NULL ) & & ( cur - > next - > type = = XML_TEXT_NODE ) & &
( cur - > name = = cur - > next - > name ) ) {
2001-02-23 20:55:21 +03:00
# ifndef XML_USE_BUFFER_CONTENT
xmlChar * tmp ;
tmp = xmlStrdup ( elem - > content ) ;
tmp = xmlStrcat ( tmp , cur - > next - > content ) ;
xmlNodeSetContent ( cur - > next , tmp ) ;
xmlFree ( tmp ) ;
# else
xmlBufferAddHead ( cur - > next - > content ,
xmlBufferContent ( elem - > content ) ,
xmlBufferLength ( elem - > content ) ) ;
# endif
xmlFreeNode ( elem ) ;
return ( cur - > next ) ;
}
}
if ( elem - > doc ! = cur - > doc ) {
xmlSetTreeDoc ( elem , cur - > doc ) ;
}
elem - > parent = cur - > parent ;
elem - > prev = cur ;
elem - > next = cur - > next ;
cur - > next = elem ;
if ( elem - > next ! = NULL )
elem - > next - > prev = elem ;
if ( ( elem - > parent ! = NULL ) & & ( elem - > parent - > last = = cur ) )
elem - > parent - > last = elem ;
return ( elem ) ;
}
/**
* xmlAddPrevSibling :
* @ cur : the child node
* @ elem : the new node
*
* Add a new element @ elem as the previous siblings of @ cur
* merging adjacent TEXT nodes ( @ elem may be freed )
* If the new element was already inserted in a document it is
* first unlinked from its existing context .
*
* Returns the new element or NULL in case of error .
*/
xmlNodePtr
xmlAddPrevSibling ( xmlNodePtr cur , xmlNodePtr elem ) {
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlAddPrevSibling : cur == NULL \n " ) ;
# endif
return ( NULL ) ;
}
if ( elem = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlAddPrevSibling : elem == NULL \n " ) ;
# endif
return ( NULL ) ;
}
xmlUnlinkNode ( elem ) ;
if ( elem - > type = = XML_TEXT_NODE ) {
if ( cur - > type = = XML_TEXT_NODE ) {
# ifndef XML_USE_BUFFER_CONTENT
xmlChar * tmp ;
tmp = xmlStrdup ( elem - > content ) ;
tmp = xmlStrcat ( tmp , cur - > content ) ;
xmlNodeSetContent ( cur , tmp ) ;
xmlFree ( tmp ) ;
# else
xmlBufferAddHead ( cur - > content , xmlBufferContent ( elem - > content ) ,
xmlBufferLength ( elem - > content ) ) ;
# endif
xmlFreeNode ( elem ) ;
return ( cur ) ;
}
2001-09-01 00:03:19 +04:00
if ( ( cur - > prev ! = NULL ) & & ( cur - > prev - > type = = XML_TEXT_NODE ) & &
( cur - > name = = cur - > prev - > name ) ) {
2001-02-23 20:55:21 +03:00
# ifndef XML_USE_BUFFER_CONTENT
xmlNodeAddContent ( cur - > prev , elem - > content ) ;
# else
xmlNodeAddContent ( cur - > prev , xmlBufferContent ( elem - > content ) ) ;
# endif
xmlFreeNode ( elem ) ;
return ( cur - > prev ) ;
}
}
if ( elem - > doc ! = cur - > doc ) {
xmlSetTreeDoc ( elem , cur - > doc ) ;
}
elem - > parent = cur - > parent ;
elem - > next = cur ;
elem - > prev = cur - > prev ;
cur - > prev = elem ;
if ( elem - > prev ! = NULL )
elem - > prev - > next = elem ;
if ( ( elem - > parent ! = NULL ) & & ( elem - > parent - > children = = cur ) )
elem - > parent - > children = elem ;
return ( elem ) ;
}
/**
* xmlAddSibling :
* @ cur : the child node
* @ elem : the new node
*
* Add a new element @ elem to the list of siblings of @ cur
* merging adjacent TEXT nodes ( @ elem may be freed )
* If the new element was already inserted in a document it is
* first unlinked from its existing context .
*
* Returns the new element or NULL in case of error .
*/
xmlNodePtr
xmlAddSibling ( xmlNodePtr cur , xmlNodePtr elem ) {
xmlNodePtr parent ;
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlAddSibling : cur == NULL \n " ) ;
# endif
return ( NULL ) ;
}
if ( elem = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlAddSibling : elem == NULL \n " ) ;
# endif
return ( NULL ) ;
}
/*
* Constant time is we can rely on the - > parent - > last to find
* the last sibling .
*/
if ( ( cur - > parent ! = NULL ) & &
( cur - > parent - > children ! = NULL ) & &
( cur - > parent - > last ! = NULL ) & &
( cur - > parent - > last - > next = = NULL ) ) {
cur = cur - > parent - > last ;
} else {
while ( cur - > next ! = NULL ) cur = cur - > next ;
}
xmlUnlinkNode ( elem ) ;
if ( ( cur - > type = = XML_TEXT_NODE ) & & ( elem - > type = = XML_TEXT_NODE ) ) {
# ifndef XML_USE_BUFFER_CONTENT
xmlNodeAddContent ( cur , elem - > content ) ;
# else
xmlNodeAddContent ( cur , xmlBufferContent ( elem - > content ) ) ;
# endif
xmlFreeNode ( elem ) ;
return ( cur ) ;
}
if ( elem - > doc ! = cur - > doc ) {
xmlSetTreeDoc ( elem , cur - > doc ) ;
}
parent = cur - > parent ;
elem - > prev = cur ;
elem - > next = NULL ;
elem - > parent = parent ;
cur - > next = elem ;
if ( parent ! = NULL )
parent - > last = elem ;
return ( elem ) ;
}
/**
* xmlAddChildList :
* @ parent : the parent node
* @ cur : the first node in the list
*
* Add a list of node at the end of the child list of the parent
* merging adjacent TEXT nodes ( @ cur may be freed )
*
* Returns the last child or NULL in case of error .
*/
xmlNodePtr
xmlAddChildList ( xmlNodePtr parent , xmlNodePtr cur ) {
xmlNodePtr prev ;
if ( parent = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlAddChild : parent == NULL \n " ) ;
# endif
return ( NULL ) ;
}
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlAddChild : child == NULL \n " ) ;
# endif
return ( NULL ) ;
}
if ( ( cur - > doc ! = NULL ) & & ( parent - > doc ! = NULL ) & &
( cur - > doc ! = parent - > doc ) ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" Elements moved to a different document \n " ) ;
# endif
}
/*
* add the first element at the end of the children list .
*/
if ( parent - > children = = NULL ) {
parent - > children = cur ;
} else {
/*
* If cur and parent - > last both are TEXT nodes , then merge them .
*/
if ( ( cur - > type = = XML_TEXT_NODE ) & &
( parent - > last - > type = = XML_TEXT_NODE ) & &
( cur - > name = = parent - > last - > name ) ) {
# ifndef XML_USE_BUFFER_CONTENT
xmlNodeAddContent ( parent - > last , cur - > content ) ;
# else
xmlNodeAddContent ( parent - > last , xmlBufferContent ( cur - > content ) ) ;
# endif
/*
* if it ' s the only child , nothing more to be done .
*/
if ( cur - > next = = NULL ) {
xmlFreeNode ( cur ) ;
return ( parent - > last ) ;
}
prev = cur ;
cur = cur - > next ;
xmlFreeNode ( prev ) ;
}
prev = parent - > last ;
prev - > next = cur ;
cur - > prev = prev ;
}
while ( cur - > next ! = NULL ) {
cur - > parent = parent ;
if ( cur - > doc ! = parent - > doc ) {
xmlSetTreeDoc ( cur , parent - > doc ) ;
}
cur = cur - > next ;
}
cur - > parent = parent ;
cur - > doc = parent - > doc ; /* the parent may not be linked to a doc ! */
parent - > last = cur ;
return ( cur ) ;
}
/**
* xmlAddChild :
* @ parent : the parent node
* @ cur : the child node
*
* Add a new child element , to @ parent , at the end of the child list
* merging adjacent TEXT nodes ( in which case @ cur is freed )
* Returns the child or NULL in case of error .
*/
xmlNodePtr
xmlAddChild ( xmlNodePtr parent , xmlNodePtr cur ) {
xmlNodePtr prev ;
if ( parent = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlAddChild : parent == NULL \n " ) ;
# endif
return ( NULL ) ;
}
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlAddChild : child == NULL \n " ) ;
# endif
return ( NULL ) ;
}
/*
* If cur is a TEXT node , merge its content with adjacent TEXT nodes
* cur is then freed .
*/
if ( cur - > type = = XML_TEXT_NODE ) {
2001-07-12 05:20:08 +04:00
if ( ( parent - > type = = XML_TEXT_NODE ) & &
2001-02-23 20:55:21 +03:00
( parent - > content ! = NULL ) ) {
# ifndef XML_USE_BUFFER_CONTENT
xmlNodeAddContent ( parent , cur - > content ) ;
# else
xmlNodeAddContent ( parent , xmlBufferContent ( cur - > content ) ) ;
# endif
xmlFreeNode ( cur ) ;
return ( parent ) ;
}
if ( ( parent - > last ! = NULL ) & & ( parent - > last - > type = = XML_TEXT_NODE ) & &
( parent - > last - > name = = cur - > name ) ) {
# ifndef XML_USE_BUFFER_CONTENT
xmlNodeAddContent ( parent - > last , cur - > content ) ;
# else
xmlNodeAddContent ( parent - > last , xmlBufferContent ( cur - > content ) ) ;
# endif
xmlFreeNode ( cur ) ;
return ( parent - > last ) ;
}
}
/*
* add the new element at the end of the children list .
*/
cur - > parent = parent ;
if ( cur - > doc ! = parent - > doc ) {
xmlSetTreeDoc ( cur , parent - > doc ) ;
}
/*
2001-07-12 05:20:08 +04:00
* Coalescing
2001-02-23 20:55:21 +03:00
*/
2001-07-12 05:20:08 +04:00
if ( ( parent - > type = = XML_TEXT_NODE ) & &
2001-02-23 20:55:21 +03:00
( parent - > content ! = NULL ) ) {
# ifndef XML_USE_BUFFER_CONTENT
2001-07-12 05:20:08 +04:00
xmlNodeAddContent ( parent , cur - > content ) ;
2001-02-23 20:55:21 +03:00
# else
2001-07-12 05:20:08 +04:00
xmlNodeAddContent ( parent , xmlBufferContent ( cur - > content ) ) ;
2001-02-23 20:55:21 +03:00
# endif
2001-07-12 05:20:08 +04:00
xmlFreeNode ( cur ) ;
return ( parent ) ;
2001-02-23 20:55:21 +03:00
}
if ( parent - > children = = NULL ) {
parent - > children = cur ;
parent - > last = cur ;
} else {
prev = parent - > last ;
prev - > next = cur ;
cur - > prev = prev ;
parent - > last = cur ;
}
return ( cur ) ;
}
/**
* xmlGetLastChild :
* @ parent : the parent node
*
* Search the last child of a node .
* Returns the last child or NULL if none .
*/
xmlNodePtr
xmlGetLastChild ( xmlNodePtr parent ) {
if ( parent = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlGetLastChild : parent == NULL \n " ) ;
# endif
return ( NULL ) ;
}
return ( parent - > last ) ;
}
/**
* xmlFreeNodeList :
* @ cur : the first node in the list
*
* Free a node and all its siblings , this is a recursive behaviour , all
* the children are freed too .
*/
void
xmlFreeNodeList ( xmlNodePtr cur ) {
xmlNodePtr next ;
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlFreeNodeList : node == NULL \n " ) ;
# endif
return ;
}
while ( cur ! = NULL ) {
next = cur - > next ;
2001-04-30 15:46:40 +04:00
/* unroll to speed up freeing the document */
if ( cur - > type ! = XML_DTD_NODE ) {
if ( ( cur - > children ! = NULL ) & &
( cur - > type ! = XML_ENTITY_REF_NODE ) )
xmlFreeNodeList ( cur - > children ) ;
if ( cur - > properties ! = NULL )
xmlFreePropList ( cur - > properties ) ;
2001-07-12 05:20:08 +04:00
if ( ( cur - > type ! = XML_ELEMENT_NODE ) & &
( cur - > type ! = XML_XINCLUDE_START ) & &
( cur - > type ! = XML_XINCLUDE_END ) & &
( cur - > type ! = XML_ENTITY_REF_NODE ) ) {
2001-04-30 15:46:40 +04:00
# ifndef XML_USE_BUFFER_CONTENT
if ( cur - > content ! = NULL ) xmlFree ( cur - > content ) ;
# else
if ( cur - > content ! = NULL ) xmlBufferFree ( cur - > content ) ;
# endif
2001-07-12 05:20:08 +04:00
}
if ( ( ( cur - > type = = XML_ELEMENT_NODE ) | |
( cur - > type = = XML_XINCLUDE_START ) | |
( cur - > type = = XML_XINCLUDE_END ) ) & &
( cur - > nsDef ! = NULL ) )
xmlFreeNsList ( cur - > nsDef ) ;
2001-06-11 12:09:20 +04:00
/*
* When a node is a text node or a comment , it uses a global static
* variable for the name of the node .
*
* The xmlStrEqual comparisons need to be done when ( happened with
* XML : : libXML and XML : : libXSLT ) the library is included twice
* statically in the binary and a tree allocated by one occurent
* of the lib gets freed by the other occurence , in this case
* the string addresses compare are not sufficient .
*/
2001-04-30 15:46:40 +04:00
if ( ( cur - > name ! = NULL ) & &
( cur - > name ! = xmlStringText ) & &
( cur - > name ! = xmlStringTextNoenc ) & &
2001-06-11 12:09:20 +04:00
( cur - > name ! = xmlStringComment ) ) {
if ( cur - > type = = XML_TEXT_NODE ) {
if ( ( ! xmlStrEqual ( cur - > name , xmlStringText ) ) & &
( ! xmlStrEqual ( cur - > name , xmlStringTextNoenc ) ) )
xmlFree ( ( char * ) cur - > name ) ;
} else if ( cur - > type = = XML_COMMENT_NODE ) {
if ( ! xmlStrEqual ( cur - > name , xmlStringComment ) )
xmlFree ( ( char * ) cur - > name ) ;
} else
xmlFree ( ( char * ) cur - > name ) ;
}
2001-04-30 15:46:40 +04:00
/* TODO : derecursivate this function */
xmlFree ( cur ) ;
}
2001-02-23 20:55:21 +03:00
cur = next ;
}
}
/**
* xmlFreeNode :
* @ cur : the node
*
* Free a node , this is a recursive behaviour , all the children are freed too .
* This doesn ' t unlink the child from the list , use xmlUnlinkNode ( ) first .
*/
void
xmlFreeNode ( xmlNodePtr cur ) {
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlFreeNode : node == NULL \n " ) ;
# endif
return ;
}
2001-04-30 15:46:40 +04:00
/* use xmlFreeDtd for DTD nodes */
2001-02-23 20:55:21 +03:00
if ( cur - > type = = XML_DTD_NODE )
return ;
if ( ( cur - > children ! = NULL ) & &
( cur - > type ! = XML_ENTITY_REF_NODE ) )
xmlFreeNodeList ( cur - > children ) ;
2001-04-30 15:46:40 +04:00
if ( cur - > properties ! = NULL )
xmlFreePropList ( cur - > properties ) ;
2001-07-12 05:20:08 +04:00
if ( ( cur - > type ! = XML_ELEMENT_NODE ) & &
( cur - > content ! = NULL ) & &
( cur - > type ! = XML_ENTITY_REF_NODE ) & &
( cur - > type ! = XML_XINCLUDE_END ) & &
( cur - > type ! = XML_XINCLUDE_START ) ) {
2001-02-23 20:55:21 +03:00
# ifndef XML_USE_BUFFER_CONTENT
2001-07-12 05:20:08 +04:00
xmlFree ( cur - > content ) ;
2001-02-23 20:55:21 +03:00
# else
2001-07-12 05:20:08 +04:00
xmlBufferFree ( cur - > content ) ;
2001-02-23 20:55:21 +03:00
# endif
2001-07-12 05:20:08 +04:00
}
2001-06-09 21:17:51 +04:00
/*
* When a node is a text node or a comment , it uses a global static
* variable for the name of the node .
*
* The xmlStrEqual comparisons need to be done when ( happened with
* XML : : libXML and XML : : libXSLT ) the library is included twice statically
* in the binary and a tree allocated by one occurent of the lib gets
* freed by the other occurence , in this case the string addresses compare
* are not sufficient .
*/
2001-02-23 20:55:21 +03:00
if ( ( cur - > name ! = NULL ) & &
( cur - > name ! = xmlStringText ) & &
( cur - > name ! = xmlStringTextNoenc ) & &
2001-06-09 21:17:51 +04:00
( cur - > name ! = xmlStringComment ) ) {
if ( cur - > type = = XML_TEXT_NODE ) {
if ( ( ! xmlStrEqual ( cur - > name , xmlStringText ) ) & &
( ! xmlStrEqual ( cur - > name , xmlStringTextNoenc ) ) )
xmlFree ( ( char * ) cur - > name ) ;
} else if ( cur - > type = = XML_COMMENT_NODE ) {
if ( ! xmlStrEqual ( cur - > name , xmlStringComment ) )
xmlFree ( ( char * ) cur - > name ) ;
} else
xmlFree ( ( char * ) cur - > name ) ;
}
2001-02-23 20:55:21 +03:00
if ( cur - > nsDef ! = NULL ) xmlFreeNsList ( cur - > nsDef ) ;
xmlFree ( cur ) ;
}
/**
* xmlUnlinkNode :
* @ cur : the node
*
* Unlink a node from it ' s current context , the node is not freed
*/
void
xmlUnlinkNode ( xmlNodePtr cur ) {
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlUnlinkNode : node == NULL \n " ) ;
# endif
return ;
}
2001-12-14 01:21:58 +03:00
if ( cur - > type = = XML_DTD_NODE ) {
xmlDocPtr doc ;
doc = cur - > doc ;
if ( doc - > intSubset = = ( xmlDtdPtr ) cur )
doc - > intSubset = NULL ;
if ( doc - > extSubset = = ( xmlDtdPtr ) cur )
doc - > extSubset = NULL ;
}
2001-02-23 20:55:21 +03:00
if ( ( cur - > parent ! = NULL ) & & ( cur - > parent - > children = = cur ) )
cur - > parent - > children = cur - > next ;
if ( ( cur - > parent ! = NULL ) & & ( cur - > parent - > last = = cur ) )
cur - > parent - > last = cur - > prev ;
if ( cur - > next ! = NULL )
cur - > next - > prev = cur - > prev ;
if ( cur - > prev ! = NULL )
cur - > prev - > next = cur - > next ;
cur - > next = cur - > prev = NULL ;
cur - > parent = NULL ;
}
/**
* xmlReplaceNode :
* @ old : the old node
* @ cur : the node
*
* Unlink the old node from it ' s current context , prune the new one
* at the same place . If cur was already inserted in a document it is
* first unlinked from its existing context .
*
* Returns the old node
*/
xmlNodePtr
xmlReplaceNode ( xmlNodePtr old , xmlNodePtr cur ) {
if ( old = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlReplaceNode : old == NULL \n " ) ;
# endif
return ( NULL ) ;
}
if ( cur = = NULL ) {
xmlUnlinkNode ( old ) ;
return ( old ) ;
}
if ( cur = = old ) {
return ( old ) ;
}
xmlUnlinkNode ( cur ) ;
cur - > doc = old - > doc ;
cur - > parent = old - > parent ;
cur - > next = old - > next ;
if ( cur - > next ! = NULL )
cur - > next - > prev = cur ;
cur - > prev = old - > prev ;
if ( cur - > prev ! = NULL )
cur - > prev - > next = cur ;
if ( cur - > parent ! = NULL ) {
if ( cur - > parent - > children = = old )
cur - > parent - > children = cur ;
if ( cur - > parent - > last = = old )
cur - > parent - > last = cur ;
}
old - > next = old - > prev = NULL ;
old - > parent = NULL ;
return ( old ) ;
}
/************************************************************************
* *
* Copy operations *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlCopyNamespace :
* @ cur : the namespace
*
* Do a copy of the namespace .
*
* Returns : a new xmlNsPtr , or NULL in case of error .
*/
xmlNsPtr
xmlCopyNamespace ( xmlNsPtr cur ) {
xmlNsPtr ret ;
if ( cur = = NULL ) return ( NULL ) ;
switch ( cur - > type ) {
case XML_LOCAL_NAMESPACE :
ret = xmlNewNs ( NULL , cur - > href , cur - > prefix ) ;
break ;
default :
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlCopyNamespace: invalid type %d \n " , cur - > type ) ;
# endif
return ( NULL ) ;
}
return ( ret ) ;
}
/**
* xmlCopyNamespaceList :
* @ cur : the first namespace
*
* Do a copy of an namespace list .
*
* Returns : a new xmlNsPtr , or NULL in case of error .
*/
xmlNsPtr
xmlCopyNamespaceList ( xmlNsPtr cur ) {
xmlNsPtr ret = NULL ;
xmlNsPtr p = NULL , q ;
while ( cur ! = NULL ) {
q = xmlCopyNamespace ( cur ) ;
if ( p = = NULL ) {
ret = p = q ;
} else {
p - > next = q ;
p = q ;
}
cur = cur - > next ;
}
return ( ret ) ;
}
static xmlNodePtr
xmlStaticCopyNodeList ( xmlNodePtr node , xmlDocPtr doc , xmlNodePtr parent ) ;
/**
* xmlCopyProp :
* @ target : the element where the attribute will be grafted
* @ cur : the attribute
*
* Do a copy of the attribute .
*
* Returns : a new xmlAttrPtr , or NULL in case of error .
*/
xmlAttrPtr
xmlCopyProp ( xmlNodePtr target , xmlAttrPtr cur ) {
xmlAttrPtr ret ;
if ( cur = = NULL ) return ( NULL ) ;
if ( target ! = NULL )
ret = xmlNewDocProp ( target - > doc , cur - > name , NULL ) ;
else if ( cur - > parent ! = NULL )
ret = xmlNewDocProp ( cur - > parent - > doc , cur - > name , NULL ) ;
else if ( cur - > children ! = NULL )
ret = xmlNewDocProp ( cur - > children - > doc , cur - > name , NULL ) ;
else
ret = xmlNewDocProp ( NULL , cur - > name , NULL ) ;
if ( ret = = NULL ) return ( NULL ) ;
ret - > parent = target ;
if ( ( cur - > ns ! = NULL ) & & ( target ! = NULL ) ) {
xmlNsPtr ns ;
ns = xmlSearchNs ( target - > doc , target , cur - > ns - > prefix ) ;
ret - > ns = ns ;
} else
ret - > ns = NULL ;
if ( cur - > children ! = NULL ) {
xmlNodePtr tmp ;
ret - > children = xmlStaticCopyNodeList ( cur - > children , ret - > doc , ( xmlNodePtr ) ret ) ;
ret - > last = NULL ;
tmp = ret - > children ;
while ( tmp ! = NULL ) {
/* tmp->parent = (xmlNodePtr)ret; */
if ( tmp - > next = = NULL )
ret - > last = tmp ;
tmp = tmp - > next ;
}
}
return ( ret ) ;
}
/**
* xmlCopyPropList :
* @ target : the element where the attributes will be grafted
* @ cur : the first attribute
*
* Do a copy of an attribute list .
*
* Returns : a new xmlAttrPtr , or NULL in case of error .
*/
xmlAttrPtr
xmlCopyPropList ( xmlNodePtr target , xmlAttrPtr cur ) {
xmlAttrPtr ret = NULL ;
xmlAttrPtr p = NULL , q ;
while ( cur ! = NULL ) {
q = xmlCopyProp ( target , cur ) ;
if ( p = = NULL ) {
ret = p = q ;
} else {
p - > next = q ;
q - > prev = p ;
p = q ;
}
cur = cur - > next ;
}
return ( ret ) ;
}
/*
* NOTE abeut the CopyNode operations !
*
* They are splitted into external and internal parts for one
* tricky reason : namespaces . Doing a direct copy of a node
* say RPM : Copyright without changing the namespace pointer to
* something else can produce stale links . One way to do it is
* to keep a reference counter but this doesn ' t work as soon
* as one move the element or the subtree out of the scope of
* the existing namespace . The actual solution seems to add
* a copy of the namespace at the top of the copied tree if
* not available in the subtree .
* Hence two functions , the public front - end call the inner ones
*/
static xmlNodePtr
xmlStaticCopyNodeList ( xmlNodePtr node , xmlDocPtr doc , xmlNodePtr parent ) ;
static xmlNodePtr
2001-08-29 00:39:49 +04:00
xmlStaticCopyNode ( const xmlNodePtr node , xmlDocPtr doc , xmlNodePtr parent ,
2001-02-23 20:55:21 +03:00
int recursive ) {
xmlNodePtr ret ;
if ( node = = NULL ) return ( NULL ) ;
2001-06-19 22:09:42 +04:00
switch ( node - > 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_XINCLUDE_START :
case XML_XINCLUDE_END :
break ;
case XML_ATTRIBUTE_NODE :
2001-07-26 15:49:41 +04:00
return ( ( xmlNodePtr ) xmlCopyProp ( parent , ( xmlAttrPtr ) node ) ) ;
2001-06-19 22:09:42 +04:00
case XML_NAMESPACE_DECL :
2001-07-26 15:49:41 +04:00
return ( ( xmlNodePtr ) xmlCopyNamespaceList ( ( xmlNsPtr ) node ) ) ;
2001-06-19 22:09:42 +04:00
2001-07-26 15:49:41 +04:00
case XML_DOCUMENT_NODE :
case XML_HTML_DOCUMENT_NODE :
# ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE :
# endif
return ( ( xmlNodePtr ) xmlCopyDoc ( ( xmlDocPtr ) node , recursive ) ) ;
2001-06-19 22:09:42 +04:00
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 :
return ( NULL ) ;
}
2001-04-25 16:59:04 +04:00
2001-02-23 20:55:21 +03:00
/*
* Allocate a new node and fill the fields .
*/
ret = ( xmlNodePtr ) xmlMalloc ( sizeof ( xmlNode ) ) ;
if ( ret = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlStaticCopyNode : malloc failed \n " ) ;
return ( NULL ) ;
}
memset ( ret , 0 , sizeof ( xmlNode ) ) ;
ret - > type = node - > type ;
ret - > doc = doc ;
ret - > parent = parent ;
if ( node - > name = = xmlStringText )
ret - > name = xmlStringText ;
else if ( node - > name = = xmlStringTextNoenc )
ret - > name = xmlStringTextNoenc ;
else if ( node - > name = = xmlStringComment )
ret - > name = xmlStringComment ;
else if ( node - > name ! = NULL )
ret - > name = xmlStrdup ( node - > name ) ;
2001-07-12 05:20:08 +04:00
if ( ( node - > type ! = XML_ELEMENT_NODE ) & &
( node - > content ! = NULL ) & &
( node - > type ! = XML_ENTITY_REF_NODE ) & &
( node - > type ! = XML_XINCLUDE_END ) & &
( node - > type ! = XML_XINCLUDE_START ) ) {
2001-02-23 20:55:21 +03:00
# ifndef XML_USE_BUFFER_CONTENT
ret - > content = xmlStrdup ( node - > content ) ;
# else
ret - > content = xmlBufferCreateSize ( xmlBufferLength ( node - > content ) ) ;
xmlBufferSetAllocationScheme ( ret - > content ,
xmlGetBufferAllocationScheme ( ) ) ;
xmlBufferAdd ( ret - > content ,
xmlBufferContent ( node - > content ) ,
xmlBufferLength ( node - > content ) ) ;
# endif
}
if ( parent ! = NULL )
xmlAddChild ( parent , ret ) ;
if ( ! recursive ) return ( ret ) ;
if ( node - > nsDef ! = NULL )
ret - > nsDef = xmlCopyNamespaceList ( node - > nsDef ) ;
if ( node - > ns ! = NULL ) {
xmlNsPtr ns ;
ns = xmlSearchNs ( doc , ret , node - > ns - > prefix ) ;
if ( ns = = NULL ) {
/*
* Humm , we are copying an element whose namespace is defined
* out of the new tree scope . Search it in the original tree
* and add it at the top of the new tree
*/
ns = xmlSearchNs ( node - > doc , node , node - > ns - > prefix ) ;
if ( ns ! = NULL ) {
xmlNodePtr root = ret ;
while ( root - > parent ! = NULL ) root = root - > parent ;
2001-04-22 16:12:58 +04:00
ret - > ns = xmlNewNs ( root , ns - > href , ns - > prefix ) ;
2001-02-23 20:55:21 +03:00
}
} else {
/*
* reference the existing namespace definition in our own tree .
*/
ret - > ns = ns ;
}
}
if ( node - > properties ! = NULL )
ret - > properties = xmlCopyPropList ( ret , node - > properties ) ;
2001-04-25 16:59:04 +04:00
if ( node - > type = = XML_ENTITY_REF_NODE ) {
if ( ( doc = = NULL ) | | ( node - > doc ! = doc ) ) {
/*
* The copied node will go into a separate document , so
* to havoid dandling references to the ENTITY_DECL node
* we cannot keep the reference . Try to find it in the
* target document .
*/
ret - > children = ( xmlNodePtr ) xmlGetDocEntity ( doc , ret - > name ) ;
} else {
ret - > children = node - > children ;
}
2001-11-14 18:04:32 +03:00
ret - > last = ret - > children ;
} else if ( node - > children ! = NULL ) {
2001-02-23 20:55:21 +03:00
ret - > children = xmlStaticCopyNodeList ( node - > children , doc , ret ) ;
2001-11-14 18:04:32 +03:00
UPDATE_LAST_CHILD_AND_PARENT ( ret )
}
2001-02-23 20:55:21 +03:00
return ( ret ) ;
}
static xmlNodePtr
xmlStaticCopyNodeList ( xmlNodePtr node , xmlDocPtr doc , xmlNodePtr parent ) {
xmlNodePtr ret = NULL ;
xmlNodePtr p = NULL , q ;
while ( node ! = NULL ) {
2001-07-26 15:49:41 +04:00
if ( node - > type = = XML_DTD_NODE ) {
2001-06-09 18:19:02 +04:00
if ( doc = = NULL ) {
node = node - > next ;
continue ;
}
2001-04-25 16:59:04 +04:00
if ( doc - > intSubset = = NULL ) {
q = ( xmlNodePtr ) xmlCopyDtd ( ( xmlDtdPtr ) node ) ;
q - > doc = doc ;
q - > parent = parent ;
doc - > intSubset = ( xmlDtdPtr ) q ;
} else {
q = ( xmlNodePtr ) doc - > intSubset ;
}
} else
q = xmlStaticCopyNode ( node , doc , parent , 1 ) ;
2001-02-23 20:55:21 +03:00
if ( ret = = NULL ) {
q - > prev = NULL ;
ret = p = q ;
} else {
p - > next = q ;
q - > prev = p ;
p = q ;
}
node = node - > next ;
}
return ( ret ) ;
}
/**
* xmlCopyNode :
* @ node : the node
* @ recursive : if 1 do a recursive copy .
*
* Do a copy of the node .
*
* Returns : a new xmlNodePtr , or NULL in case of error .
*/
xmlNodePtr
2001-08-29 00:39:49 +04:00
xmlCopyNode ( const xmlNodePtr node , int recursive ) {
2001-02-23 20:55:21 +03:00
xmlNodePtr ret ;
ret = xmlStaticCopyNode ( node , NULL , NULL , recursive ) ;
return ( ret ) ;
}
2001-04-12 12:55:36 +04:00
/**
* xmlDocCopyNode :
* @ node : the node
* @ recursive : if 1 do a recursive copy .
*
* Do a copy of the node to a given document .
*
* Returns : a new xmlNodePtr , or NULL in case of error .
*/
xmlNodePtr
2001-08-29 00:39:49 +04:00
xmlDocCopyNode ( const xmlNodePtr node , xmlDocPtr doc , int recursive ) {
2001-04-12 12:55:36 +04:00
xmlNodePtr ret ;
ret = xmlStaticCopyNode ( node , doc , NULL , recursive ) ;
return ( ret ) ;
}
2001-02-23 20:55:21 +03:00
/**
* xmlCopyNodeList :
* @ node : the first node in the list .
*
* Do a recursive copy of the node list .
*
* Returns : a new xmlNodePtr , or NULL in case of error .
*/
2001-08-29 00:39:49 +04:00
xmlNodePtr xmlCopyNodeList ( const xmlNodePtr node ) {
2001-02-23 20:55:21 +03:00
xmlNodePtr ret = xmlStaticCopyNodeList ( node , NULL , NULL ) ;
return ( ret ) ;
}
/**
* xmlCopyDtd :
* @ dtd : the dtd
*
* Do a copy of the dtd .
*
* Returns : a new xmlDtdPtr , or NULL in case of error .
*/
xmlDtdPtr
xmlCopyDtd ( xmlDtdPtr dtd ) {
xmlDtdPtr ret ;
if ( dtd = = NULL ) return ( NULL ) ;
ret = xmlNewDtd ( NULL , dtd - > name , dtd - > ExternalID , dtd - > SystemID ) ;
if ( ret = = NULL ) return ( NULL ) ;
if ( dtd - > entities ! = NULL )
ret - > entities = ( void * ) xmlCopyEntitiesTable (
( xmlEntitiesTablePtr ) dtd - > entities ) ;
if ( dtd - > notations ! = NULL )
ret - > notations = ( void * ) xmlCopyNotationTable (
( xmlNotationTablePtr ) dtd - > notations ) ;
if ( dtd - > elements ! = NULL )
ret - > elements = ( void * ) xmlCopyElementTable (
( xmlElementTablePtr ) dtd - > elements ) ;
if ( dtd - > attributes ! = NULL )
ret - > attributes = ( void * ) xmlCopyAttributeTable (
( xmlAttributeTablePtr ) dtd - > attributes ) ;
return ( ret ) ;
}
/**
* xmlCopyDoc :
* @ doc : the document
* @ recursive : if 1 do a recursive copy .
*
* Do a copy of the document info . If recursive , the content tree will
* be copied too as well as Dtd , namespaces and entities .
*
* Returns : a new xmlDocPtr , or NULL in case of error .
*/
xmlDocPtr
xmlCopyDoc ( xmlDocPtr doc , int recursive ) {
xmlDocPtr ret ;
if ( doc = = NULL ) return ( NULL ) ;
ret = xmlNewDoc ( doc - > version ) ;
if ( ret = = NULL ) return ( NULL ) ;
if ( doc - > name ! = NULL )
ret - > name = xmlMemStrdup ( doc - > name ) ;
if ( doc - > encoding ! = NULL )
ret - > encoding = xmlStrdup ( doc - > encoding ) ;
ret - > charset = doc - > charset ;
ret - > compression = doc - > compression ;
ret - > standalone = doc - > standalone ;
if ( ! recursive ) return ( ret ) ;
2001-04-25 16:59:04 +04:00
ret - > last = NULL ;
ret - > children = NULL ;
if ( doc - > intSubset ! = NULL ) {
2001-02-23 20:55:21 +03:00
ret - > intSubset = xmlCopyDtd ( doc - > intSubset ) ;
2001-04-25 16:59:04 +04:00
ret - > intSubset - > doc = ret ;
ret - > intSubset - > parent = ret ;
}
2001-02-23 20:55:21 +03:00
if ( doc - > oldNs ! = NULL )
ret - > oldNs = xmlCopyNamespaceList ( doc - > oldNs ) ;
if ( doc - > children ! = NULL ) {
xmlNodePtr tmp ;
2001-04-25 16:59:04 +04:00
ret - > children = xmlStaticCopyNodeList ( doc - > children , ret ,
( xmlNodePtr ) ret ) ;
2001-02-23 20:55:21 +03:00
ret - > last = NULL ;
tmp = ret - > children ;
while ( tmp ! = NULL ) {
if ( tmp - > next = = NULL )
ret - > last = tmp ;
tmp = tmp - > next ;
}
}
return ( ret ) ;
}
/************************************************************************
* *
* Content access functions *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-26 18:58:08 +03:00
/**
* xmlGetLineNo :
* @ node : valid node
*
* Get line number of node . this requires activation of this option
* before inoking the parser by calling xmlLineNumbersDefault ( 1 )
*
* Returns the line number if sucessfull , - 1 otherwise
*/
long
xmlGetLineNo ( xmlNodePtr node )
{
long result = - 1 ;
if ( ! node )
return result ;
if ( node - > type = = XML_ELEMENT_NODE )
result = ( long ) node - > content ;
else if ( ( node - > prev ! = NULL ) & &
( ( node - > prev - > type = = XML_ELEMENT_NODE ) | |
( node - > prev - > type = = XML_TEXT_NODE ) ) )
result = xmlGetLineNo ( node - > prev ) ;
else if ( ( node - > parent ! = NULL ) & &
( ( node - > parent - > type = = XML_ELEMENT_NODE ) | |
( node - > parent - > type = = XML_TEXT_NODE ) ) )
result = xmlGetLineNo ( node - > parent ) ;
return result ;
}
/**
* xmlGetNodePath :
* @ node : a node
*
* Build a structure based Path for the given node
*
* Returns the new path or NULL in case of error . The caller must free
* the returned string
*/
xmlChar *
xmlGetNodePath ( xmlNodePtr node )
{
xmlNodePtr cur , tmp , next ;
xmlChar * buffer = NULL , * temp ;
size_t buf_len ;
xmlChar * buf ;
char sep ;
const char * name ;
char nametemp [ 100 ] ;
int occur = 0 ;
if ( node = = NULL )
return ( NULL ) ;
buf_len = 500 ;
buffer = ( xmlChar * ) xmlMalloc ( buf_len * sizeof ( xmlChar ) ) ;
if ( buffer = = NULL )
return ( NULL ) ;
buf = ( xmlChar * ) xmlMalloc ( buf_len * sizeof ( xmlChar ) ) ;
if ( buf = = NULL ) {
xmlFree ( buffer ) ;
return ( NULL ) ;
}
buffer [ 0 ] = 0 ;
cur = node ;
do {
name = " " ;
sep = ' ? ' ;
occur = 0 ;
if ( ( cur - > type = = XML_DOCUMENT_NODE ) | |
( cur - > type = = XML_HTML_DOCUMENT_NODE ) ) {
if ( buffer [ 0 ] = = ' / ' )
break ;
sep = ' / ' ;
next = NULL ;
} else if ( cur - > type = = XML_ELEMENT_NODE ) {
sep = ' / ' ;
name = ( const char * ) cur - > name ;
if ( cur - > ns ) {
snprintf ( nametemp , sizeof ( nametemp ) - 1 ,
" %s:%s " , cur - > ns - > prefix , cur - > name ) ;
nametemp [ sizeof ( nametemp ) - 1 ] = 0 ;
name = nametemp ;
}
next = cur - > parent ;
/*
* Thumbler index computation
*/
tmp = cur - > prev ;
while ( tmp ! = NULL ) {
if ( xmlStrEqual ( cur - > name , tmp - > name ) )
occur + + ;
tmp = tmp - > prev ;
}
if ( occur = = 0 ) {
tmp = cur - > next ;
while ( tmp ! = NULL ) {
if ( xmlStrEqual ( cur - > name , tmp - > name ) )
occur + + ;
tmp = tmp - > next ;
}
if ( occur ! = 0 )
occur = 1 ;
} else
occur + + ;
} else if ( cur - > type = = XML_ATTRIBUTE_NODE ) {
sep = ' @ ' ;
name = ( const char * ) ( ( ( xmlAttrPtr ) cur ) - > name ) ;
next = ( ( xmlAttrPtr ) cur ) - > parent ;
} else {
next = cur - > parent ;
}
/*
* Make sure there is enough room
*/
if ( xmlStrlen ( buffer ) + sizeof ( nametemp ) + 20 > buf_len ) {
buf_len =
2 * buf_len + xmlStrlen ( buffer ) + sizeof ( nametemp ) + 20 ;
temp = ( xmlChar * ) xmlRealloc ( buffer , buf_len ) ;
if ( temp = = NULL ) {
xmlFree ( buf ) ;
xmlFree ( buffer ) ;
return ( NULL ) ;
}
buffer = temp ;
temp = ( xmlChar * ) xmlRealloc ( buf , buf_len ) ;
if ( temp = = NULL ) {
xmlFree ( buf ) ;
xmlFree ( buffer ) ;
return ( NULL ) ;
}
buf = temp ;
}
if ( occur = = 0 )
snprintf ( ( char * ) buf , buf_len , " %c%s%s " ,
sep , name , ( char * ) buffer ) ;
else
snprintf ( ( char * ) buf , buf_len , " %c%s[%d]%s " ,
sep , name , occur , ( char * ) buffer ) ;
snprintf ( ( char * ) buffer , buf_len , " %s " , buf ) ;
cur = next ;
} while ( cur ! = NULL ) ;
xmlFree ( buf ) ;
return ( buffer ) ;
}
2001-02-23 20:55:21 +03:00
/**
* xmlDocGetRootElement :
* @ doc : the document
*
* Get the root element of the document ( doc - > children is a list
* containing possibly comments , PIs , etc . . . ) .
*
* Returns the xmlNodePtr for the root or NULL
*/
xmlNodePtr
xmlDocGetRootElement ( xmlDocPtr doc ) {
xmlNodePtr ret ;
if ( doc = = NULL ) return ( NULL ) ;
ret = doc - > children ;
while ( ret ! = NULL ) {
if ( ret - > type = = XML_ELEMENT_NODE )
return ( ret ) ;
ret = ret - > next ;
}
return ( ret ) ;
}
/**
* xmlDocSetRootElement :
* @ doc : the document
* @ root : the new document root element
*
* Set the root element of the document ( doc - > children is a list
* containing possibly comments , PIs , etc . . . ) .
*
* Returns the old root element if any was found
*/
xmlNodePtr
xmlDocSetRootElement ( xmlDocPtr doc , xmlNodePtr root ) {
xmlNodePtr old = NULL ;
if ( doc = = NULL ) return ( NULL ) ;
old = doc - > children ;
while ( old ! = NULL ) {
if ( old - > type = = XML_ELEMENT_NODE )
break ;
old = old - > next ;
}
if ( old = = NULL ) {
if ( doc - > children = = NULL ) {
doc - > children = root ;
doc - > last = root ;
} else {
xmlAddSibling ( doc - > children , root ) ;
}
} else {
xmlReplaceNode ( old , root ) ;
}
return ( old ) ;
}
/**
* xmlNodeSetLang :
* @ cur : the node being changed
* @ lang : the langage description
*
* Set the language of a node , i . e . the values of the xml : lang
* attribute .
*/
void
xmlNodeSetLang ( xmlNodePtr cur , const xmlChar * lang ) {
if ( cur = = NULL ) return ;
switch ( cur - > type ) {
case XML_TEXT_NODE :
case XML_CDATA_SECTION_NODE :
case XML_COMMENT_NODE :
case XML_DOCUMENT_NODE :
case XML_DOCUMENT_TYPE_NODE :
case XML_DOCUMENT_FRAG_NODE :
case XML_NOTATION_NODE :
case XML_HTML_DOCUMENT_NODE :
case XML_DTD_NODE :
case XML_ELEMENT_DECL :
case XML_ATTRIBUTE_DECL :
case XML_ENTITY_DECL :
case XML_PI_NODE :
case XML_ENTITY_REF_NODE :
case XML_ENTITY_NODE :
case XML_NAMESPACE_DECL :
2001-04-23 17:41:34 +04:00
# ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE :
2001-02-23 20:55:21 +03:00
# endif
case XML_XINCLUDE_START :
case XML_XINCLUDE_END :
return ;
case XML_ELEMENT_NODE :
case XML_ATTRIBUTE_NODE :
break ;
}
xmlSetProp ( cur , BAD_CAST " xml:lang " , lang ) ;
}
/**
* xmlNodeGetLang :
* @ cur : the node being checked
*
* Searches the language of a node , i . e . the values of the xml : lang
* attribute or the one carried by the nearest ancestor .
*
* Returns a pointer to the lang value , or NULL if not found
* It ' s up to the caller to free the memory .
*/
xmlChar *
xmlNodeGetLang ( xmlNodePtr cur ) {
xmlChar * lang ;
while ( cur ! = NULL ) {
2001-05-09 14:51:31 +04:00
lang = xmlGetNsProp ( cur , BAD_CAST " lang " , XML_XML_NAMESPACE ) ;
2001-02-23 20:55:21 +03:00
if ( lang ! = NULL )
return ( lang ) ;
cur = cur - > parent ;
}
return ( NULL ) ;
}
/**
* xmlNodeSetSpacePreserve :
* @ cur : the node being changed
* @ val : the xml : space value ( " 0 " : default , 1 : " preserve " )
*
* Set ( or reset ) the space preserving behaviour of a node , i . e . the
* value of the xml : space attribute .
*/
void
xmlNodeSetSpacePreserve ( xmlNodePtr cur , int val ) {
if ( cur = = NULL ) return ;
switch ( cur - > type ) {
case XML_TEXT_NODE :
case XML_CDATA_SECTION_NODE :
case XML_COMMENT_NODE :
case XML_DOCUMENT_NODE :
case XML_DOCUMENT_TYPE_NODE :
case XML_DOCUMENT_FRAG_NODE :
case XML_NOTATION_NODE :
case XML_HTML_DOCUMENT_NODE :
case XML_DTD_NODE :
case XML_ELEMENT_DECL :
case XML_ATTRIBUTE_DECL :
case XML_ENTITY_DECL :
case XML_PI_NODE :
case XML_ENTITY_REF_NODE :
case XML_ENTITY_NODE :
case XML_NAMESPACE_DECL :
case XML_XINCLUDE_START :
case XML_XINCLUDE_END :
2001-04-23 17:41:34 +04:00
# ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE :
2001-02-23 20:55:21 +03:00
# endif
return ;
case XML_ELEMENT_NODE :
case XML_ATTRIBUTE_NODE :
break ;
}
switch ( val ) {
case 0 :
xmlSetProp ( cur , BAD_CAST " xml:space " , BAD_CAST " default " ) ;
break ;
case 1 :
xmlSetProp ( cur , BAD_CAST " xml:space " ,
BAD_CAST " preserve " ) ;
break ;
}
}
/**
* xmlNodeGetSpacePreserve :
* @ cur : the node being checked
*
* Searches the space preserving behaviour of a node , i . e . the values
* of the xml : space attribute or the one carried by the nearest
* ancestor .
*
* Returns - 1 if xml : space is not inheried , 0 if " default " , 1 if " preserve "
*/
int
xmlNodeGetSpacePreserve ( xmlNodePtr cur ) {
xmlChar * space ;
while ( cur ! = NULL ) {
space = xmlGetProp ( cur , BAD_CAST " xml:space " ) ;
if ( space ! = NULL ) {
if ( xmlStrEqual ( space , BAD_CAST " preserve " ) ) {
xmlFree ( space ) ;
return ( 1 ) ;
}
if ( xmlStrEqual ( space , BAD_CAST " default " ) ) {
xmlFree ( space ) ;
return ( 0 ) ;
}
xmlFree ( space ) ;
}
cur = cur - > parent ;
}
return ( - 1 ) ;
}
/**
* xmlNodeSetName :
* @ cur : the node being changed
* @ name : the new tag name
*
* Set ( or reset ) the name of a node .
*/
void
xmlNodeSetName ( xmlNodePtr cur , const xmlChar * name ) {
if ( cur = = NULL ) return ;
if ( name = = NULL ) return ;
switch ( cur - > type ) {
case XML_TEXT_NODE :
case XML_CDATA_SECTION_NODE :
case XML_COMMENT_NODE :
case XML_DOCUMENT_TYPE_NODE :
case XML_DOCUMENT_FRAG_NODE :
case XML_NOTATION_NODE :
case XML_HTML_DOCUMENT_NODE :
case XML_NAMESPACE_DECL :
case XML_XINCLUDE_START :
case XML_XINCLUDE_END :
2001-04-23 17:41:34 +04:00
# ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE :
2001-02-23 20:55:21 +03:00
# endif
return ;
case XML_ELEMENT_NODE :
case XML_ATTRIBUTE_NODE :
case XML_PI_NODE :
case XML_ENTITY_REF_NODE :
case XML_ENTITY_NODE :
case XML_DTD_NODE :
case XML_DOCUMENT_NODE :
case XML_ELEMENT_DECL :
case XML_ATTRIBUTE_DECL :
case XML_ENTITY_DECL :
break ;
}
if ( cur - > name ! = NULL ) xmlFree ( ( xmlChar * ) cur - > name ) ;
cur - > name = xmlStrdup ( name ) ;
}
/**
* xmlNodeSetBase :
* @ cur : the node being changed
* @ uri : the new base URI
*
* Set ( or reset ) the base URI of a node , i . e . the value of the
* xml : base attribute .
*/
void
xmlNodeSetBase ( xmlNodePtr cur , xmlChar * uri ) {
if ( cur = = NULL ) return ;
switch ( cur - > type ) {
case XML_TEXT_NODE :
case XML_CDATA_SECTION_NODE :
case XML_COMMENT_NODE :
case XML_DOCUMENT_NODE :
case XML_DOCUMENT_TYPE_NODE :
case XML_DOCUMENT_FRAG_NODE :
case XML_NOTATION_NODE :
case XML_HTML_DOCUMENT_NODE :
case XML_DTD_NODE :
case XML_ELEMENT_DECL :
case XML_ATTRIBUTE_DECL :
case XML_ENTITY_DECL :
case XML_PI_NODE :
case XML_ENTITY_REF_NODE :
case XML_ENTITY_NODE :
case XML_NAMESPACE_DECL :
case XML_XINCLUDE_START :
case XML_XINCLUDE_END :
2001-04-23 17:41:34 +04:00
# ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE :
2001-02-23 20:55:21 +03:00
# endif
return ;
case XML_ELEMENT_NODE :
case XML_ATTRIBUTE_NODE :
break ;
}
xmlSetProp ( cur , BAD_CAST " xml:base " , uri ) ;
}
/**
* xmlNodeGetBase :
* @ doc : the document the node pertains to
* @ cur : the node being checked
*
* Searches for the BASE URL . The code should work on both XML
* and HTML document even if base mechanisms are completely different .
* It returns the base as defined in RFC 2396 sections
* 5.1 .1 . Base URI within Document Content
* and
* 5.1 .2 . Base URI from the Encapsulating Entity
* However it does not return the document base ( 5.1 .3 ) , use
* xmlDocumentGetBase ( ) for this
*
* Returns a pointer to the base URL , or NULL if not found
* It ' s up to the caller to free the memory .
*/
xmlChar *
xmlNodeGetBase ( xmlDocPtr doc , xmlNodePtr cur ) {
2001-07-09 20:01:19 +04:00
xmlChar * oldbase = NULL ;
xmlChar * base , * newbase ;
2001-02-23 20:55:21 +03:00
if ( ( cur = = NULL ) & & ( doc = = NULL ) )
return ( NULL ) ;
if ( doc = = NULL ) doc = cur - > doc ;
if ( ( doc ! = NULL ) & & ( doc - > type = = XML_HTML_DOCUMENT_NODE ) ) {
cur = doc - > children ;
while ( ( cur ! = NULL ) & & ( cur - > name ! = NULL ) ) {
if ( cur - > type ! = XML_ELEMENT_NODE ) {
cur = cur - > next ;
continue ;
}
if ( ! xmlStrcasecmp ( cur - > name , BAD_CAST " html " ) ) {
cur = cur - > children ;
continue ;
}
if ( ! xmlStrcasecmp ( cur - > name , BAD_CAST " head " ) ) {
cur = cur - > children ;
continue ;
}
if ( ! xmlStrcasecmp ( cur - > name , BAD_CAST " base " ) ) {
return ( xmlGetProp ( cur , BAD_CAST " href " ) ) ;
}
cur = cur - > next ;
}
return ( NULL ) ;
}
while ( cur ! = NULL ) {
if ( cur - > type = = XML_ENTITY_DECL ) {
xmlEntityPtr ent = ( xmlEntityPtr ) cur ;
return ( xmlStrdup ( ent - > URI ) ) ;
}
2001-05-22 20:57:14 +04:00
if ( cur - > type = = XML_ELEMENT_NODE ) {
2001-07-09 20:01:19 +04:00
base = xmlGetNsProp ( cur , BAD_CAST " base " , XML_XML_NAMESPACE ) ;
2001-05-22 20:57:14 +04:00
if ( base ! = NULL ) {
2001-07-09 20:01:19 +04:00
if ( oldbase ! = NULL ) {
newbase = xmlBuildURI ( oldbase , base ) ;
if ( newbase ! = NULL ) {
xmlFree ( oldbase ) ;
xmlFree ( base ) ;
oldbase = newbase ;
} else {
xmlFree ( oldbase ) ;
xmlFree ( base ) ;
return ( NULL ) ;
}
} else {
oldbase = base ;
}
if ( ( ! xmlStrncmp ( oldbase , BAD_CAST " http:// " , 7 ) ) | |
( ! xmlStrncmp ( oldbase , BAD_CAST " ftp:// " , 6 ) ) | |
( ! xmlStrncmp ( oldbase , BAD_CAST " urn: " , 4 ) ) )
return ( oldbase ) ;
2001-05-22 20:57:14 +04:00
}
}
2001-02-23 20:55:21 +03:00
cur = cur - > parent ;
}
2001-07-09 20:01:19 +04:00
if ( ( doc ! = NULL ) & & ( doc - > URL ! = NULL ) ) {
if ( oldbase = = NULL )
return ( xmlStrdup ( doc - > URL ) ) ;
newbase = xmlBuildURI ( oldbase , doc - > URL ) ;
xmlFree ( oldbase ) ;
return ( newbase ) ;
}
return ( oldbase ) ;
2001-02-23 20:55:21 +03:00
}
/**
* xmlNodeGetContent :
* @ cur : the node being read
*
* Read the value of a node , this can be either the text carried
* directly by this node if it ' s a TEXT node or the aggregate string
* of the values carried by this node child ' s ( TEXT and ENTITY_REF ) .
* Entity references are substitued .
* Returns a new xmlChar * or NULL if no content is available .
* It ' s up to the caller to free the memory .
*/
xmlChar *
xmlNodeGetContent ( xmlNodePtr cur ) {
if ( cur = = NULL ) return ( NULL ) ;
switch ( cur - > type ) {
case XML_DOCUMENT_FRAG_NODE :
case XML_ELEMENT_NODE : {
xmlNodePtr tmp = cur ;
xmlBufferPtr buffer ;
xmlChar * ret ;
buffer = xmlBufferCreate ( ) ;
if ( buffer = = NULL )
return ( NULL ) ;
while ( tmp ! = NULL ) {
switch ( tmp - > type ) {
2001-05-30 22:32:34 +04:00
case XML_CDATA_SECTION_NODE :
2001-02-23 20:55:21 +03:00
case XML_TEXT_NODE :
if ( tmp - > content ! = NULL )
# ifndef XML_USE_BUFFER_CONTENT
xmlBufferCat ( buffer , tmp - > content ) ;
# else
xmlBufferCat ( buffer ,
xmlBufferContent ( tmp - > content ) ) ;
# endif
break ;
case XML_ENTITY_REF_NODE : {
xmlEntityPtr ent ;
ent = xmlGetDocEntity ( cur - > doc , tmp - > name ) ;
if ( ent ! = NULL )
xmlBufferCat ( buffer , ent - > content ) ;
}
default :
break ;
}
/*
* Skip to next node
*/
if ( tmp - > children ! = NULL ) {
if ( tmp - > children - > type ! = XML_ENTITY_DECL ) {
tmp = tmp - > children ;
continue ;
}
}
2001-03-07 18:57:53 +03:00
if ( tmp = = cur )
break ;
2001-02-23 20:55:21 +03:00
if ( tmp - > next ! = NULL ) {
tmp = tmp - > next ;
continue ;
}
do {
tmp = tmp - > parent ;
if ( tmp = = NULL )
break ;
2001-03-07 18:57:53 +03:00
if ( tmp = = cur ) {
2001-02-23 20:55:21 +03:00
tmp = NULL ;
break ;
}
if ( tmp - > next ! = NULL ) {
tmp = tmp - > next ;
break ;
}
} while ( tmp ! = NULL ) ;
}
ret = buffer - > content ;
buffer - > content = NULL ;
xmlBufferFree ( buffer ) ;
return ( ret ) ;
}
case XML_ATTRIBUTE_NODE : {
xmlAttrPtr attr = ( xmlAttrPtr ) cur ;
if ( attr - > parent ! = NULL )
return ( xmlNodeListGetString ( attr - > parent - > doc , attr - > children , 1 ) ) ;
else
return ( xmlNodeListGetString ( NULL , attr - > children , 1 ) ) ;
break ;
}
case XML_COMMENT_NODE :
case XML_PI_NODE :
if ( cur - > content ! = NULL )
# ifndef XML_USE_BUFFER_CONTENT
return ( xmlStrdup ( cur - > content ) ) ;
# else
return ( xmlStrdup ( xmlBufferContent ( cur - > content ) ) ) ;
# endif
return ( NULL ) ;
case XML_ENTITY_REF_NODE :
/*
* Locate the entity , and get it ' s content
* @ @ @
*/
return ( NULL ) ;
case XML_ENTITY_NODE :
case XML_DOCUMENT_NODE :
case XML_HTML_DOCUMENT_NODE :
case XML_DOCUMENT_TYPE_NODE :
case XML_NOTATION_NODE :
case XML_DTD_NODE :
case XML_XINCLUDE_START :
case XML_XINCLUDE_END :
2001-04-23 17:41:34 +04:00
# ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE :
2001-02-23 20:55:21 +03:00
# endif
return ( NULL ) ;
case XML_NAMESPACE_DECL :
return ( xmlStrdup ( ( ( xmlNsPtr ) cur ) - > href ) ) ;
case XML_ELEMENT_DECL :
/* TODO !!! */
return ( NULL ) ;
case XML_ATTRIBUTE_DECL :
/* TODO !!! */
return ( NULL ) ;
case XML_ENTITY_DECL :
/* TODO !!! */
return ( NULL ) ;
case XML_CDATA_SECTION_NODE :
case XML_TEXT_NODE :
if ( cur - > content ! = NULL )
# ifndef XML_USE_BUFFER_CONTENT
return ( xmlStrdup ( cur - > content ) ) ;
# else
return ( xmlStrdup ( xmlBufferContent ( cur - > content ) ) ) ;
# endif
return ( NULL ) ;
}
return ( NULL ) ;
}
/**
* xmlNodeSetContent :
* @ cur : the node being modified
* @ content : the new value of the content
*
* Replace the content of a node .
*/
void
xmlNodeSetContent ( xmlNodePtr cur , const xmlChar * content ) {
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNodeSetContent : node == NULL \n " ) ;
# endif
return ;
}
switch ( cur - > type ) {
case XML_DOCUMENT_FRAG_NODE :
case XML_ELEMENT_NODE :
if ( cur - > children ! = NULL ) xmlFreeNodeList ( cur - > children ) ;
cur - > children = xmlStringGetNodeList ( cur - > doc , content ) ;
UPDATE_LAST_CHILD_AND_PARENT ( cur )
break ;
case XML_ATTRIBUTE_NODE :
break ;
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 :
if ( cur - > content ! = NULL ) {
# ifndef XML_USE_BUFFER_CONTENT
xmlFree ( cur - > content ) ;
# else
xmlBufferFree ( cur - > content ) ;
# endif
}
if ( cur - > children ! = NULL ) xmlFreeNodeList ( cur - > children ) ;
cur - > last = cur - > children = NULL ;
if ( content ! = NULL ) {
# ifndef XML_USE_BUFFER_CONTENT
cur - > content = xmlStrdup ( content ) ;
# else
cur - > content = xmlBufferCreateSize ( 0 ) ;
xmlBufferSetAllocationScheme ( cur - > content ,
xmlGetBufferAllocationScheme ( ) ) ;
xmlBufferAdd ( cur - > content , content , - 1 ) ;
# endif
} else
cur - > content = NULL ;
break ;
case XML_DOCUMENT_NODE :
case XML_HTML_DOCUMENT_NODE :
case XML_DOCUMENT_TYPE_NODE :
case XML_XINCLUDE_START :
case XML_XINCLUDE_END :
2001-04-23 17:41:34 +04:00
# ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE :
2001-02-23 20:55:21 +03:00
# endif
break ;
case XML_NOTATION_NODE :
break ;
case XML_DTD_NODE :
break ;
case XML_NAMESPACE_DECL :
break ;
case XML_ELEMENT_DECL :
/* TODO !!! */
break ;
case XML_ATTRIBUTE_DECL :
/* TODO !!! */
break ;
case XML_ENTITY_DECL :
/* TODO !!! */
break ;
}
}
/**
* xmlNodeSetContentLen :
* @ cur : the node being modified
* @ content : the new value of the content
* @ len : the size of @ content
*
* Replace the content of a node .
*/
void
xmlNodeSetContentLen ( xmlNodePtr cur , const xmlChar * content , int len ) {
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNodeSetContentLen : node == NULL \n " ) ;
# endif
return ;
}
switch ( cur - > type ) {
case XML_DOCUMENT_FRAG_NODE :
case XML_ELEMENT_NODE :
if ( cur - > children ! = NULL ) xmlFreeNodeList ( cur - > children ) ;
cur - > children = xmlStringLenGetNodeList ( cur - > doc , content , len ) ;
UPDATE_LAST_CHILD_AND_PARENT ( cur )
break ;
case XML_ATTRIBUTE_NODE :
break ;
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_NOTATION_NODE :
if ( cur - > content ! = NULL ) {
# ifndef XML_USE_BUFFER_CONTENT
xmlFree ( cur - > content ) ;
# else
xmlBufferFree ( cur - > content ) ;
# endif
}
if ( cur - > children ! = NULL ) xmlFreeNodeList ( cur - > children ) ;
cur - > children = cur - > last = NULL ;
if ( content ! = NULL ) {
# ifndef XML_USE_BUFFER_CONTENT
cur - > content = xmlStrndup ( content , len ) ;
# else
cur - > content = xmlBufferCreateSize ( len ) ;
xmlBufferSetAllocationScheme ( cur - > content ,
xmlGetBufferAllocationScheme ( ) ) ;
xmlBufferAdd ( cur - > content , content , len ) ;
# endif
} else
cur - > content = NULL ;
break ;
case XML_DOCUMENT_NODE :
case XML_DTD_NODE :
case XML_HTML_DOCUMENT_NODE :
case XML_DOCUMENT_TYPE_NODE :
case XML_NAMESPACE_DECL :
case XML_XINCLUDE_START :
case XML_XINCLUDE_END :
2001-04-23 17:41:34 +04:00
# ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE :
2001-02-23 20:55:21 +03:00
# endif
break ;
case XML_ELEMENT_DECL :
/* TODO !!! */
break ;
case XML_ATTRIBUTE_DECL :
/* TODO !!! */
break ;
case XML_ENTITY_DECL :
/* TODO !!! */
break ;
}
}
/**
* xmlNodeAddContentLen :
* @ cur : the node being modified
* @ content : extra content
* @ len : the size of @ content
*
* Append the extra substring to the node content .
*/
void
xmlNodeAddContentLen ( xmlNodePtr cur , const xmlChar * content , int len ) {
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNodeAddContentLen : node == NULL \n " ) ;
# endif
return ;
}
if ( len < = 0 ) return ;
switch ( cur - > type ) {
case XML_DOCUMENT_FRAG_NODE :
case XML_ELEMENT_NODE : {
2001-07-12 05:20:08 +04:00
xmlNodePtr last , newNode ;
2001-02-23 20:55:21 +03:00
2001-07-12 05:20:08 +04:00
last = cur - > last ;
2001-02-23 20:55:21 +03:00
newNode = xmlNewTextLen ( content , len ) ;
if ( newNode ! = NULL ) {
xmlAddChild ( cur , newNode ) ;
if ( ( last ! = NULL ) & & ( last - > next = = newNode ) ) {
xmlTextMerge ( last , newNode ) ;
}
}
break ;
}
case XML_ATTRIBUTE_NODE :
break ;
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_NOTATION_NODE :
if ( content ! = NULL ) {
# ifndef XML_USE_BUFFER_CONTENT
cur - > content = xmlStrncat ( cur - > content , content , len ) ;
# else
xmlBufferAdd ( cur - > content , content , len ) ;
# endif
}
case XML_DOCUMENT_NODE :
case XML_DTD_NODE :
case XML_HTML_DOCUMENT_NODE :
case XML_DOCUMENT_TYPE_NODE :
case XML_NAMESPACE_DECL :
case XML_XINCLUDE_START :
case XML_XINCLUDE_END :
2001-04-23 17:41:34 +04:00
# ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE :
2001-02-23 20:55:21 +03:00
# endif
break ;
case XML_ELEMENT_DECL :
case XML_ATTRIBUTE_DECL :
case XML_ENTITY_DECL :
break ;
}
}
/**
* xmlNodeAddContent :
* @ cur : the node being modified
* @ content : extra content
*
* Append the extra substring to the node content .
*/
void
xmlNodeAddContent ( xmlNodePtr cur , const xmlChar * content ) {
int len ;
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNodeAddContent : node == NULL \n " ) ;
# endif
return ;
}
if ( content = = NULL ) return ;
len = xmlStrlen ( content ) ;
xmlNodeAddContentLen ( cur , content , len ) ;
}
/**
* xmlTextMerge :
* @ first : the first text node
* @ second : the second text node being merged
*
* Merge two text nodes into one
* Returns the first text node augmented
*/
xmlNodePtr
xmlTextMerge ( xmlNodePtr first , xmlNodePtr second ) {
if ( first = = NULL ) return ( second ) ;
if ( second = = NULL ) return ( first ) ;
if ( first - > type ! = XML_TEXT_NODE ) return ( first ) ;
if ( second - > type ! = XML_TEXT_NODE ) return ( first ) ;
if ( second - > name ! = first - > name )
return ( first ) ;
# ifndef XML_USE_BUFFER_CONTENT
xmlNodeAddContent ( first , second - > content ) ;
# else
xmlNodeAddContent ( first , xmlBufferContent ( second - > content ) ) ;
# endif
xmlUnlinkNode ( second ) ;
xmlFreeNode ( second ) ;
return ( first ) ;
}
/**
* xmlGetNsList :
* @ doc : the document
* @ node : the current node
*
* Search all the namespace applying to a given element .
* Returns an NULL terminated array of all the xmlNsPtr found
* that need to be freed by the caller or NULL if no
* namespace if defined
*/
xmlNsPtr *
2001-06-30 01:31:07 +04:00
xmlGetNsList ( xmlDocPtr doc ATTRIBUTE_UNUSED , xmlNodePtr node )
{
2001-02-23 20:55:21 +03:00
xmlNsPtr cur ;
xmlNsPtr * ret = NULL ;
int nbns = 0 ;
int maxns = 10 ;
int i ;
while ( node ! = NULL ) {
2001-06-30 01:31:07 +04:00
if ( node - > type = = XML_ELEMENT_NODE ) {
cur = node - > nsDef ;
while ( cur ! = NULL ) {
if ( ret = = NULL ) {
ret =
( xmlNsPtr * ) xmlMalloc ( ( maxns + 1 ) *
sizeof ( xmlNsPtr ) ) ;
if ( ret = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlGetNsList : out of memory! \n " ) ;
return ( NULL ) ;
}
ret [ nbns ] = NULL ;
}
for ( i = 0 ; i < nbns ; i + + ) {
if ( ( cur - > prefix = = ret [ i ] - > prefix ) | |
( xmlStrEqual ( cur - > prefix , ret [ i ] - > prefix ) ) )
break ;
}
if ( i > = nbns ) {
if ( nbns > = maxns ) {
maxns * = 2 ;
ret = ( xmlNsPtr * ) xmlRealloc ( ret ,
( maxns +
1 ) *
sizeof ( xmlNsPtr ) ) ;
if ( ret = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlGetNsList : realloc failed! \n " ) ;
return ( NULL ) ;
}
}
ret [ nbns + + ] = cur ;
ret [ nbns ] = NULL ;
}
cur = cur - > next ;
}
}
node = node - > parent ;
2001-02-23 20:55:21 +03:00
}
2001-06-30 01:31:07 +04:00
return ( ret ) ;
2001-02-23 20:55:21 +03:00
}
/**
* xmlSearchNs :
* @ doc : the document
* @ node : the current node
2001-02-28 00:54:07 +03:00
* @ nameSpace : the namespace prefix
2001-02-23 20:55:21 +03:00
*
* Search a Ns registered under a given name space for a document .
* recurse on the parents until it finds the defined namespace
* or return NULL otherwise .
* @ nameSpace can be NULL , this is a search for the default namespace .
* We don ' t allow to cross entities boundaries . If you don ' t declare
* the namespace within those you will be in troubles ! ! ! A warning
* is generated to cover this case .
*
* Returns the namespace pointer or NULL .
*/
xmlNsPtr
xmlSearchNs ( xmlDocPtr doc , xmlNodePtr node , const xmlChar * nameSpace ) {
xmlNsPtr cur ;
if ( node = = NULL ) return ( NULL ) ;
if ( ( nameSpace ! = NULL ) & &
( xmlStrEqual ( nameSpace , ( const xmlChar * ) " xml " ) ) ) {
if ( doc - > oldNs = = NULL ) {
/*
* Allocate a new Namespace and fill the fields .
*/
doc - > oldNs = ( xmlNsPtr ) xmlMalloc ( sizeof ( xmlNs ) ) ;
if ( doc - > oldNs = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlSearchNsByHref : malloc failed \n " ) ;
return ( NULL ) ;
}
memset ( doc - > oldNs , 0 , sizeof ( xmlNs ) ) ;
doc - > oldNs - > type = XML_LOCAL_NAMESPACE ;
doc - > oldNs - > href = xmlStrdup ( XML_XML_NAMESPACE ) ;
doc - > oldNs - > prefix = xmlStrdup ( ( const xmlChar * ) " xml " ) ;
}
return ( doc - > oldNs ) ;
}
while ( node ! = NULL ) {
if ( ( node - > type = = XML_ENTITY_REF_NODE ) | |
( node - > type = = XML_ENTITY_NODE ) | |
( node - > type = = XML_ENTITY_DECL ) )
return ( NULL ) ;
if ( node - > type = = XML_ELEMENT_NODE ) {
cur = node - > nsDef ;
while ( cur ! = NULL ) {
if ( ( cur - > prefix = = NULL ) & & ( nameSpace = = NULL ) & &
( cur - > href ! = NULL ) )
return ( cur ) ;
if ( ( cur - > prefix ! = NULL ) & & ( nameSpace ! = NULL ) & &
( cur - > href ! = NULL ) & &
( xmlStrEqual ( cur - > prefix , nameSpace ) ) )
return ( cur ) ;
cur = cur - > next ;
}
}
node = node - > parent ;
}
return ( NULL ) ;
}
/**
* xmlSearchNsByHref :
* @ doc : the document
* @ node : the current node
* @ href : the namespace value
*
* Search a Ns aliasing a given URI . Recurse on the parents until it finds
* the defined namespace or return NULL otherwise .
* Returns the namespace pointer or NULL .
*/
xmlNsPtr
xmlSearchNsByHref ( xmlDocPtr doc , xmlNodePtr node , const xmlChar * href ) {
xmlNsPtr cur ;
xmlNodePtr orig = node ;
if ( ( node = = NULL ) | | ( href = = NULL ) ) return ( NULL ) ;
if ( xmlStrEqual ( href , XML_XML_NAMESPACE ) ) {
if ( doc - > oldNs = = NULL ) {
/*
* Allocate a new Namespace and fill the fields .
*/
doc - > oldNs = ( xmlNsPtr ) xmlMalloc ( sizeof ( xmlNs ) ) ;
if ( doc - > oldNs = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlSearchNsByHref : malloc failed \n " ) ;
return ( NULL ) ;
}
memset ( doc - > oldNs , 0 , sizeof ( xmlNs ) ) ;
doc - > oldNs - > type = XML_LOCAL_NAMESPACE ;
doc - > oldNs - > href = xmlStrdup ( XML_XML_NAMESPACE ) ;
doc - > oldNs - > prefix = xmlStrdup ( ( const xmlChar * ) " xml " ) ;
}
return ( doc - > oldNs ) ;
}
while ( node ! = NULL ) {
cur = node - > nsDef ;
while ( cur ! = NULL ) {
if ( ( cur - > href ! = NULL ) & & ( href ! = NULL ) & &
( xmlStrEqual ( cur - > href , href ) ) ) {
/*
* Check that the prefix is not shadowed between orig and node
*/
xmlNodePtr check = orig ;
xmlNsPtr tst ;
while ( check ! = node ) {
tst = check - > nsDef ;
while ( tst ! = NULL ) {
if ( ( tst - > prefix = = NULL ) & & ( cur - > prefix = = NULL ) )
goto shadowed ;
if ( ( tst - > prefix ! = NULL ) & & ( cur - > prefix ! = NULL ) & &
( xmlStrEqual ( tst - > prefix , cur - > prefix ) ) )
goto shadowed ;
tst = tst - > next ;
}
check = check - > parent ;
}
return ( cur ) ;
}
shadowed :
cur = cur - > next ;
}
node = node - > parent ;
}
return ( NULL ) ;
}
/**
* xmlNewReconciliedNs
* @ doc : the document
* @ tree : a node expected to hold the new namespace
* @ ns : the original namespace
*
* This function tries to locate a namespace definition in a tree
* ancestors , or create a new namespace definition node similar to
* @ ns trying to reuse the same prefix . However if the given prefix is
* null ( default namespace ) or reused within the subtree defined by
* @ tree or on one of its ancestors then a new prefix is generated .
* Returns the ( new ) namespace definition or NULL in case of error
*/
xmlNsPtr
xmlNewReconciliedNs ( xmlDocPtr doc , xmlNodePtr tree , xmlNsPtr ns ) {
xmlNsPtr def ;
xmlChar prefix [ 50 ] ;
int counter = 1 ;
if ( tree = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewReconciliedNs : tree == NULL \n " ) ;
# endif
return ( NULL ) ;
}
if ( ns = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewReconciliedNs : ns == NULL \n " ) ;
# endif
return ( NULL ) ;
}
/*
* Search an existing namespace definition inherited .
*/
def = xmlSearchNsByHref ( doc , tree , ns - > href ) ;
if ( def ! = NULL )
return ( def ) ;
/*
* Find a close prefix which is not already in use .
* Let ' s strip namespace prefixes longer than 20 chars !
*/
sprintf ( ( char * ) prefix , " %.20s " , ns - > prefix ) ;
def = xmlSearchNs ( doc , tree , prefix ) ;
while ( def ! = NULL ) {
if ( counter > 1000 ) return ( NULL ) ;
sprintf ( ( char * ) prefix , " %.20s%d " , ns - > prefix , counter + + ) ;
def = xmlSearchNs ( doc , tree , prefix ) ;
}
/*
* Ok , now we are ready to create a new one .
*/
def = xmlNewNs ( tree , ns - > href , prefix ) ;
return ( def ) ;
}
/**
* xmlReconciliateNs
* @ doc : the document
* @ tree : a node defining the subtree to reconciliate
*
* This function checks that all the namespaces declared within the given
* tree are properly declared . This is needed for example after Copy or Cut
* and then paste operations . The subtree may still hold pointers to
* namespace declarations outside the subtree or invalid / masked . As much
* as possible the function try tu reuse the existing namespaces found in
* the new environment . If not possible the new namespaces are redeclared
* on @ tree at the top of the given subtree .
* Returns the number of namespace declarations created or - 1 in case of error .
*/
int
xmlReconciliateNs ( xmlDocPtr doc , xmlNodePtr tree ) {
xmlNsPtr * oldNs = NULL ;
xmlNsPtr * newNs = NULL ;
int sizeCache = 0 ;
int nbCache = 0 ;
xmlNsPtr n ;
xmlNodePtr node = tree ;
xmlAttrPtr attr ;
int ret = 0 , i ;
while ( node ! = NULL ) {
/*
* Reconciliate the node namespace
*/
if ( node - > ns ! = NULL ) {
/*
* initialize the cache if needed
*/
if ( sizeCache = = 0 ) {
sizeCache = 10 ;
oldNs = ( xmlNsPtr * ) xmlMalloc ( sizeCache *
sizeof ( xmlNsPtr ) ) ;
if ( oldNs = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlReconciliateNs : memory pbm \n " ) ;
return ( - 1 ) ;
}
newNs = ( xmlNsPtr * ) xmlMalloc ( sizeCache *
sizeof ( xmlNsPtr ) ) ;
if ( newNs = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlReconciliateNs : memory pbm \n " ) ;
xmlFree ( oldNs ) ;
return ( - 1 ) ;
}
}
for ( i = 0 ; i < nbCache ; i + + ) {
if ( oldNs [ i ] = = node - > ns ) {
node - > ns = newNs [ i ] ;
break ;
}
}
if ( i = = nbCache ) {
/*
* Ok we need to recreate a new namespace definition
*/
n = xmlNewReconciliedNs ( doc , tree , node - > ns ) ;
if ( n ! = NULL ) { /* :-( what if else ??? */
/*
* check if we need to grow the cache buffers .
*/
if ( sizeCache < = nbCache ) {
sizeCache * = 2 ;
oldNs = ( xmlNsPtr * ) xmlRealloc ( oldNs , sizeCache *
sizeof ( xmlNsPtr ) ) ;
if ( oldNs = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlReconciliateNs : memory pbm \n " ) ;
xmlFree ( newNs ) ;
return ( - 1 ) ;
}
newNs = ( xmlNsPtr * ) xmlRealloc ( newNs , sizeCache *
sizeof ( xmlNsPtr ) ) ;
if ( newNs = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlReconciliateNs : memory pbm \n " ) ;
xmlFree ( oldNs ) ;
return ( - 1 ) ;
}
}
newNs [ nbCache ] = n ;
oldNs [ nbCache + + ] = node - > ns ;
node - > ns = n ;
}
}
}
/*
* now check for namespace hold by attributes on the node .
*/
attr = node - > properties ;
while ( attr ! = NULL ) {
if ( attr - > ns ! = NULL ) {
/*
* initialize the cache if needed
*/
if ( sizeCache = = 0 ) {
sizeCache = 10 ;
oldNs = ( xmlNsPtr * ) xmlMalloc ( sizeCache *
sizeof ( xmlNsPtr ) ) ;
if ( oldNs = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlReconciliateNs : memory pbm \n " ) ;
return ( - 1 ) ;
}
newNs = ( xmlNsPtr * ) xmlMalloc ( sizeCache *
sizeof ( xmlNsPtr ) ) ;
if ( newNs = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlReconciliateNs : memory pbm \n " ) ;
xmlFree ( oldNs ) ;
return ( - 1 ) ;
}
}
for ( i = 0 ; i < nbCache ; i + + ) {
if ( oldNs [ i ] = = attr - > ns ) {
node - > ns = newNs [ i ] ;
break ;
}
}
if ( i = = nbCache ) {
/*
* Ok we need to recreate a new namespace definition
*/
n = xmlNewReconciliedNs ( doc , tree , attr - > ns ) ;
if ( n ! = NULL ) { /* :-( what if else ??? */
/*
* check if we need to grow the cache buffers .
*/
if ( sizeCache < = nbCache ) {
sizeCache * = 2 ;
oldNs = ( xmlNsPtr * ) xmlRealloc ( oldNs , sizeCache *
sizeof ( xmlNsPtr ) ) ;
if ( oldNs = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlReconciliateNs : memory pbm \n " ) ;
xmlFree ( newNs ) ;
return ( - 1 ) ;
}
newNs = ( xmlNsPtr * ) xmlRealloc ( newNs , sizeCache *
sizeof ( xmlNsPtr ) ) ;
if ( newNs = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlReconciliateNs : memory pbm \n " ) ;
xmlFree ( oldNs ) ;
return ( - 1 ) ;
}
}
newNs [ nbCache ] = n ;
oldNs [ nbCache + + ] = attr - > ns ;
attr - > ns = n ;
}
}
}
attr = attr - > next ;
}
/*
* Browse the full subtree , deep first
*/
if ( node - > children ! = NULL ) {
/* deep first */
node = node - > children ;
} else if ( ( node ! = tree ) & & ( node - > next ! = NULL ) ) {
/* then siblings */
node = node - > next ;
} else if ( node ! = tree ) {
/* go up to parents->next if needed */
while ( node ! = tree ) {
if ( node - > parent ! = NULL )
node = node - > parent ;
if ( ( node ! = tree ) & & ( node - > next ! = NULL ) ) {
node = node - > next ;
break ;
}
if ( node - > parent = = NULL ) {
node = NULL ;
break ;
}
}
/* exit condition */
if ( node = = tree )
node = NULL ;
}
}
return ( ret ) ;
}
/**
* xmlHasProp :
* @ node : the node
* @ name : the attribute name
*
* Search an attribute associated to a node
* This function also looks in DTD attribute declaration for # FIXED or
* default declaration values unless DTD use has been turned off .
*
* Returns the attribute or the attribute declaration or NULL if
* neither was found .
*/
xmlAttrPtr
xmlHasProp ( xmlNodePtr node , const xmlChar * name ) {
xmlAttrPtr prop ;
xmlDocPtr doc ;
if ( ( node = = NULL ) | | ( name = = NULL ) ) return ( NULL ) ;
/*
* Check on the properties attached to the node
*/
prop = node - > properties ;
while ( prop ! = NULL ) {
if ( xmlStrEqual ( prop - > name , name ) ) {
return ( prop ) ;
}
prop = prop - > next ;
}
if ( ! xmlCheckDTD ) return ( NULL ) ;
/*
* Check if there is a default declaration in the internal
* or external subsets
*/
doc = node - > doc ;
if ( doc ! = NULL ) {
xmlAttributePtr attrDecl ;
if ( doc - > intSubset ! = NULL ) {
attrDecl = xmlGetDtdAttrDesc ( doc - > intSubset , node - > name , name ) ;
if ( ( attrDecl = = NULL ) & & ( doc - > extSubset ! = NULL ) )
attrDecl = xmlGetDtdAttrDesc ( doc - > extSubset , node - > name , name ) ;
if ( attrDecl ! = NULL )
return ( ( xmlAttrPtr ) attrDecl ) ;
}
}
return ( NULL ) ;
}
2001-06-06 14:46:28 +04:00
/**
* xmlHasNsProp :
* @ node : the node
* @ name : the attribute name
2001-06-11 16:09:01 +04:00
* @ nameSpace : the URI of the namespace
2001-06-06 14:46:28 +04:00
*
* Search for an attribute associated to a node
* This attribute has to be anchored in the namespace specified .
* This does the entity substitution .
* This function looks in DTD attribute declaration for # FIXED or
* default declaration values unless DTD use has been turned off .
*
* Returns the attribute or the attribute declaration or NULL
* if neither was found .
*/
xmlAttrPtr
2001-06-11 16:09:01 +04:00
xmlHasNsProp ( xmlNodePtr node , const xmlChar * name , const xmlChar * nameSpace ) {
2001-06-06 14:46:28 +04:00
xmlAttrPtr prop ;
xmlDocPtr doc ;
xmlNsPtr ns ;
if ( node = = NULL )
return ( NULL ) ;
prop = node - > properties ;
2001-06-11 16:09:01 +04:00
if ( nameSpace = = NULL )
2001-06-06 14:46:28 +04:00
return ( xmlHasProp ( node , name ) ) ;
while ( prop ! = NULL ) {
/*
* One need to have
* - same attribute names
* - and the attribute carrying that namespace
* or
* no namespace on the attribute and the element carrying it
*/
if ( ( xmlStrEqual ( prop - > name , name ) ) & &
2001-06-17 18:50:34 +04:00
( ( prop - > ns ! = NULL ) & & ( xmlStrEqual ( prop - > ns - > href , nameSpace ) ) ) ) {
return ( prop ) ;
2001-06-06 14:46:28 +04:00
}
prop = prop - > next ;
}
if ( ! xmlCheckDTD ) return ( NULL ) ;
/*
* Check if there is a default declaration in the internal
* or external subsets
*/
doc = node - > doc ;
if ( doc ! = NULL ) {
if ( doc - > intSubset ! = NULL ) {
xmlAttributePtr attrDecl ;
attrDecl = xmlGetDtdAttrDesc ( doc - > intSubset , node - > name , name ) ;
if ( ( attrDecl = = NULL ) & & ( doc - > extSubset ! = NULL ) )
attrDecl = xmlGetDtdAttrDesc ( doc - > extSubset , node - > name , name ) ;
if ( ( attrDecl ! = NULL ) & & ( attrDecl - > prefix ! = NULL ) ) {
/*
* The DTD declaration only allows a prefix search
*/
ns = xmlSearchNs ( doc , node , attrDecl - > prefix ) ;
2001-06-11 16:09:01 +04:00
if ( ( ns ! = NULL ) & & ( xmlStrEqual ( ns - > href , nameSpace ) ) )
2001-06-06 14:46:28 +04:00
return ( ( xmlAttrPtr ) attrDecl ) ;
}
}
}
return ( NULL ) ;
}
2001-02-23 20:55:21 +03:00
/**
* xmlGetProp :
* @ node : the node
* @ name : the attribute name
*
* Search and get the value of an attribute associated to a node
* This does the entity substitution .
* This function looks in DTD attribute declaration for # FIXED or
* default declaration values unless DTD use has been turned off .
*
* Returns the attribute value or NULL if not found .
* It ' s up to the caller to free the memory .
*/
xmlChar *
xmlGetProp ( xmlNodePtr node , const xmlChar * name ) {
xmlAttrPtr prop ;
xmlDocPtr doc ;
if ( ( node = = NULL ) | | ( name = = NULL ) ) return ( NULL ) ;
/*
* Check on the properties attached to the node
*/
prop = node - > properties ;
while ( prop ! = NULL ) {
if ( xmlStrEqual ( prop - > name , name ) ) {
xmlChar * ret ;
ret = xmlNodeListGetString ( node - > doc , prop - > children , 1 ) ;
if ( ret = = NULL ) return ( xmlStrdup ( ( xmlChar * ) " " ) ) ;
return ( ret ) ;
}
prop = prop - > next ;
}
if ( ! xmlCheckDTD ) return ( NULL ) ;
/*
* Check if there is a default declaration in the internal
* or external subsets
*/
doc = node - > doc ;
if ( doc ! = NULL ) {
xmlAttributePtr attrDecl ;
if ( doc - > intSubset ! = NULL ) {
attrDecl = xmlGetDtdAttrDesc ( doc - > intSubset , node - > name , name ) ;
if ( ( attrDecl = = NULL ) & & ( doc - > extSubset ! = NULL ) )
attrDecl = xmlGetDtdAttrDesc ( doc - > extSubset , node - > name , name ) ;
if ( attrDecl ! = NULL )
return ( xmlStrdup ( attrDecl - > defaultValue ) ) ;
}
}
return ( NULL ) ;
}
/**
* xmlGetNsProp :
* @ node : the node
* @ name : the attribute name
2001-06-11 16:09:01 +04:00
* @ nameSpace : the URI of the namespace
2001-02-23 20:55:21 +03:00
*
* Search and get the value of an attribute associated to a node
* This attribute has to be anchored in the namespace specified .
* This does the entity substitution .
* This function looks in DTD attribute declaration for # FIXED or
* default declaration values unless DTD use has been turned off .
*
* Returns the attribute value or NULL if not found .
* It ' s up to the caller to free the memory .
*/
xmlChar *
2001-06-11 16:09:01 +04:00
xmlGetNsProp ( xmlNodePtr node , const xmlChar * name , const xmlChar * nameSpace ) {
2001-02-23 20:55:21 +03:00
xmlAttrPtr prop ;
xmlDocPtr doc ;
xmlNsPtr ns ;
if ( node = = NULL )
return ( NULL ) ;
prop = node - > properties ;
2001-06-11 16:09:01 +04:00
if ( nameSpace = = NULL )
2001-02-23 20:55:21 +03:00
return ( xmlGetProp ( node , name ) ) ;
while ( prop ! = NULL ) {
/*
* One need to have
* - same attribute names
* - and the attribute carrying that namespace
*/
if ( ( xmlStrEqual ( prop - > name , name ) ) & &
2001-06-07 23:35:47 +04:00
( ( prop - > ns ! = NULL ) & &
2001-06-11 16:09:01 +04:00
( xmlStrEqual ( prop - > ns - > href , nameSpace ) ) ) ) {
2001-02-23 20:55:21 +03:00
xmlChar * ret ;
ret = xmlNodeListGetString ( node - > doc , prop - > children , 1 ) ;
if ( ret = = NULL ) return ( xmlStrdup ( ( xmlChar * ) " " ) ) ;
return ( ret ) ;
}
prop = prop - > next ;
}
if ( ! xmlCheckDTD ) return ( NULL ) ;
/*
* Check if there is a default declaration in the internal
* or external subsets
*/
doc = node - > doc ;
if ( doc ! = NULL ) {
if ( doc - > intSubset ! = NULL ) {
2001-04-30 21:44:45 +04:00
xmlAttributePtr attrDecl ;
2001-02-23 20:55:21 +03:00
attrDecl = xmlGetDtdAttrDesc ( doc - > intSubset , node - > name , name ) ;
if ( ( attrDecl = = NULL ) & & ( doc - > extSubset ! = NULL ) )
attrDecl = xmlGetDtdAttrDesc ( doc - > extSubset , node - > name , name ) ;
if ( ( attrDecl ! = NULL ) & & ( attrDecl - > prefix ! = NULL ) ) {
/*
* The DTD declaration only allows a prefix search
*/
ns = xmlSearchNs ( doc , node , attrDecl - > prefix ) ;
2001-06-11 16:09:01 +04:00
if ( ( ns ! = NULL ) & & ( xmlStrEqual ( ns - > href , nameSpace ) ) )
2001-02-23 20:55:21 +03:00
return ( xmlStrdup ( attrDecl - > defaultValue ) ) ;
}
}
}
return ( NULL ) ;
}
/**
* xmlSetProp :
* @ node : the node
* @ name : the attribute name
* @ value : the attribute value
*
* Set ( or reset ) an attribute carried by a node .
* Returns the attribute pointer .
*/
xmlAttrPtr
xmlSetProp ( xmlNodePtr node , const xmlChar * name , const xmlChar * value ) {
2001-11-25 13:35:25 +03:00
xmlAttrPtr prop ;
xmlDocPtr doc ;
2001-02-23 20:55:21 +03:00
if ( ( node = = NULL ) | | ( name = = NULL ) )
return ( NULL ) ;
doc = node - > doc ;
2001-11-25 13:35:25 +03:00
prop = node - > properties ;
2001-02-23 20:55:21 +03:00
while ( prop ! = NULL ) {
2001-05-11 21:41:21 +04:00
if ( ( xmlStrEqual ( prop - > name , name ) ) & &
( prop - > ns = = NULL ) ) {
2001-11-25 13:35:25 +03:00
xmlNodePtr oldprop = prop - > children ;
2001-02-23 20:55:21 +03:00
prop - > children = NULL ;
prop - > last = NULL ;
if ( value ! = NULL ) {
xmlChar * buffer ;
xmlNodePtr tmp ;
buffer = xmlEncodeEntitiesReentrant ( node - > doc , value ) ;
prop - > children = xmlStringGetNodeList ( node - > doc , buffer ) ;
prop - > last = NULL ;
prop - > doc = doc ;
tmp = prop - > children ;
while ( tmp ! = NULL ) {
tmp - > parent = ( xmlNodePtr ) prop ;
tmp - > doc = doc ;
if ( tmp - > next = = NULL )
prop - > last = tmp ;
tmp = tmp - > next ;
}
xmlFree ( buffer ) ;
2001-05-11 21:41:21 +04:00
}
2001-11-25 13:35:25 +03:00
if ( oldprop ! = NULL )
xmlFreeNodeList ( oldprop ) ;
2001-02-23 20:55:21 +03:00
return ( prop ) ;
}
prop = prop - > next ;
}
prop = xmlNewProp ( node , name , value ) ;
return ( prop ) ;
}
2001-05-11 21:41:21 +04:00
/**
* xmlUnsetProp :
* @ node : the node
* @ name : the attribute name
*
* Remove an attribute carried by a node .
* Returns 0 if successful , - 1 if not found
*/
int
xmlUnsetProp ( xmlNodePtr node , const xmlChar * name ) {
xmlAttrPtr prop = node - > properties , prev = NULL ; ;
if ( ( node = = NULL ) | | ( name = = NULL ) )
return ( - 1 ) ;
while ( prop ! = NULL ) {
if ( ( xmlStrEqual ( prop - > name , name ) ) & &
( prop - > ns = = NULL ) ) {
if ( prev = = NULL )
node - > properties = prop - > next ;
else
prev - > next = prop - > next ;
xmlFreeProp ( prop ) ;
return ( 0 ) ;
}
prev = prop ;
prop = prop - > next ;
}
return ( - 1 ) ;
}
2001-02-23 20:55:21 +03:00
/**
* xmlSetNsProp :
* @ node : the node
* @ ns : the namespace definition
* @ name : the attribute name
* @ value : the attribute value
*
* Set ( or reset ) an attribute carried by a node .
* The ns structure must be in scope , this is not checked .
*
* Returns the attribute pointer .
*/
xmlAttrPtr
xmlSetNsProp ( xmlNodePtr node , xmlNsPtr ns , const xmlChar * name ,
const xmlChar * value ) {
xmlAttrPtr prop ;
if ( ( node = = NULL ) | | ( name = = NULL ) )
return ( NULL ) ;
if ( ns = = NULL )
return ( xmlSetProp ( node , name , value ) ) ;
if ( ns - > href = = NULL )
return ( NULL ) ;
prop = node - > properties ;
while ( prop ! = NULL ) {
/*
* One need to have
* - same attribute names
* - and the attribute carrying that namespace
* or
* no namespace on the attribute and the element carrying it
*/
if ( ( xmlStrEqual ( prop - > name , name ) ) & &
( ( ( prop - > ns = = NULL ) & & ( node - > ns ! = NULL ) & &
( xmlStrEqual ( node - > ns - > href , ns - > href ) ) ) | |
( ( prop - > ns ! = NULL ) & & ( xmlStrEqual ( prop - > ns - > href , ns - > href ) ) ) ) ) {
if ( prop - > children ! = NULL )
xmlFreeNodeList ( prop - > children ) ;
prop - > children = NULL ;
prop - > last = NULL ;
prop - > ns = ns ;
if ( value ! = NULL ) {
xmlChar * buffer ;
xmlNodePtr tmp ;
buffer = xmlEncodeEntitiesReentrant ( node - > doc , value ) ;
prop - > children = xmlStringGetNodeList ( node - > doc , buffer ) ;
prop - > last = NULL ;
tmp = prop - > children ;
while ( tmp ! = NULL ) {
tmp - > parent = ( xmlNodePtr ) prop ;
if ( tmp - > next = = NULL )
prop - > last = tmp ;
tmp = tmp - > next ;
}
xmlFree ( buffer ) ;
}
return ( prop ) ;
}
prop = prop - > next ;
}
prop = xmlNewNsProp ( node , ns , name , value ) ;
return ( prop ) ;
}
2001-05-11 21:41:21 +04:00
/**
* xmlUnsetNsProp :
* @ node : the node
* @ ns : the namespace definition
* @ name : the attribute name
*
* Remove an attribute carried by a node .
* Returns 0 if successful , - 1 if not found
*/
int
xmlUnsetNsProp ( xmlNodePtr node , xmlNsPtr ns , const xmlChar * name ) {
xmlAttrPtr prop = node - > properties , prev = NULL ; ;
if ( ( node = = NULL ) | | ( name = = NULL ) )
return ( - 1 ) ;
if ( ns = = NULL )
return ( xmlUnsetProp ( node , name ) ) ;
if ( ns - > href = = NULL )
return ( - 1 ) ;
while ( prop ! = NULL ) {
if ( ( xmlStrEqual ( prop - > name , name ) ) & &
( ( ( prop - > ns = = NULL ) & & ( node - > ns ! = NULL ) & &
( xmlStrEqual ( node - > ns - > href , ns - > href ) ) ) | |
( ( prop - > ns ! = NULL ) & & ( xmlStrEqual ( prop - > ns - > href , ns - > href ) ) ) ) ) {
if ( prev = = NULL )
node - > properties = prop - > next ;
else
prev - > next = prop - > next ;
xmlFreeProp ( prop ) ;
return ( 0 ) ;
}
prev = prop ;
prop = prop - > next ;
}
return ( - 1 ) ;
}
2001-02-23 20:55:21 +03:00
/**
* xmlNodeIsText :
* @ node : the node
*
* Is this node a Text node ?
* Returns 1 yes , 0 no
*/
int
xmlNodeIsText ( xmlNodePtr node ) {
if ( node = = NULL ) return ( 0 ) ;
if ( node - > type = = XML_TEXT_NODE ) return ( 1 ) ;
return ( 0 ) ;
}
/**
* xmlIsBlankNode :
* @ node : the node
*
* Checks whether this node is an empty or whitespace only
* ( and possibly ignorable ) text - node .
*
* Returns 1 yes , 0 no
*/
int
xmlIsBlankNode ( xmlNodePtr node ) {
const xmlChar * cur ;
if ( node = = NULL ) return ( 0 ) ;
2001-07-12 05:20:08 +04:00
if ( ( node - > type ! = XML_TEXT_NODE ) & &
( node - > type ! = XML_CDATA_SECTION_NODE ) )
return ( 0 ) ;
2001-02-23 20:55:21 +03:00
if ( node - > content = = NULL ) return ( 1 ) ;
# ifndef XML_USE_BUFFER_CONTENT
cur = node - > content ;
# else
cur = xmlBufferContent ( node - > content ) ;
# endif
while ( * cur ! = 0 ) {
if ( ! IS_BLANK ( * cur ) ) return ( 0 ) ;
cur + + ;
}
return ( 1 ) ;
}
/**
* xmlTextConcat :
* @ node : the node
* @ content : the content
2001-10-10 13:45:09 +04:00
* @ len : @ content length
2001-02-23 20:55:21 +03:00
*
* Concat the given string at the end of the existing node content
*/
void
xmlTextConcat ( xmlNodePtr node , const xmlChar * content , int len ) {
if ( node = = NULL ) return ;
if ( ( node - > type ! = XML_TEXT_NODE ) & &
( node - > type ! = XML_CDATA_SECTION_NODE ) ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlTextConcat: node is not text nor cdata \n " ) ;
# endif
return ;
}
# ifndef XML_USE_BUFFER_CONTENT
node - > content = xmlStrncat ( node - > content , content , len ) ;
# else
xmlBufferAdd ( node - > content , content , len ) ;
# endif
}
/************************************************************************
* *
* Output : to a FILE or in memory *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlBufferCreate :
*
* routine to create an XML buffer .
* returns the new structure .
*/
xmlBufferPtr
xmlBufferCreate ( void ) {
xmlBufferPtr ret ;
ret = ( xmlBufferPtr ) xmlMalloc ( sizeof ( xmlBuffer ) ) ;
if ( ret = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlBufferCreate : out of memory! \n " ) ;
return ( NULL ) ;
}
ret - > use = 0 ;
2001-03-10 15:32:04 +03:00
ret - > size = xmlDefaultBufferSize ;
2001-02-23 20:55:21 +03:00
ret - > alloc = xmlBufferAllocScheme ;
ret - > content = ( xmlChar * ) xmlMalloc ( ret - > size * sizeof ( xmlChar ) ) ;
if ( ret - > content = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlBufferCreate : out of memory! \n " ) ;
xmlFree ( ret ) ;
return ( NULL ) ;
}
ret - > content [ 0 ] = 0 ;
return ( ret ) ;
}
/**
* xmlBufferCreateSize :
* @ size : initial size of buffer
*
* routine to create an XML buffer .
* returns the new structure .
*/
xmlBufferPtr
xmlBufferCreateSize ( size_t size ) {
xmlBufferPtr ret ;
ret = ( xmlBufferPtr ) xmlMalloc ( sizeof ( xmlBuffer ) ) ;
if ( ret = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlBufferCreate : out of memory! \n " ) ;
return ( NULL ) ;
}
ret - > use = 0 ;
ret - > alloc = xmlBufferAllocScheme ;
ret - > size = ( size ? size + 2 : 0 ) ; /* +1 for ending null */
if ( ret - > size ) {
ret - > content = ( xmlChar * ) xmlMalloc ( ret - > size * sizeof ( xmlChar ) ) ;
if ( ret - > content = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlBufferCreate : out of memory! \n " ) ;
xmlFree ( ret ) ;
return ( NULL ) ;
}
ret - > content [ 0 ] = 0 ;
} else
ret - > content = NULL ;
return ( ret ) ;
}
/**
* xmlBufferSetAllocationScheme :
* @ buf : the buffer to free
* @ scheme : allocation scheme to use
*
* Sets the allocation scheme for this buffer
*/
void
xmlBufferSetAllocationScheme ( xmlBufferPtr buf ,
xmlBufferAllocationScheme scheme ) {
if ( buf = = NULL ) {
# ifdef DEBUG_BUFFER
xmlGenericError ( xmlGenericErrorContext ,
" xmlBufferSetAllocationScheme: buf == NULL \n " ) ;
# endif
return ;
}
buf - > alloc = scheme ;
}
/**
* xmlBufferFree :
* @ buf : the buffer to free
*
* Frees an XML buffer .
*/
void
xmlBufferFree ( xmlBufferPtr buf ) {
if ( buf = = NULL ) {
# ifdef DEBUG_BUFFER
xmlGenericError ( xmlGenericErrorContext ,
" xmlBufferFree: buf == NULL \n " ) ;
# endif
return ;
}
if ( buf - > content ! = NULL ) {
xmlFree ( buf - > content ) ;
}
xmlFree ( buf ) ;
}
/**
* xmlBufferEmpty :
* @ buf : the buffer
*
* empty a buffer .
*/
void
xmlBufferEmpty ( xmlBufferPtr buf ) {
if ( buf - > content = = NULL ) return ;
buf - > use = 0 ;
2001-03-27 16:47:33 +04:00
memset ( buf - > content , 0 , buf - > size ) ;
2001-02-23 20:55:21 +03:00
}
/**
* xmlBufferShrink :
* @ buf : the buffer to dump
* @ len : the number of xmlChar to remove
*
* Remove the beginning of an XML buffer .
*
* Returns the number of xmlChar removed , or - 1 in case of failure .
*/
int
xmlBufferShrink ( xmlBufferPtr buf , unsigned int len ) {
if ( len = = 0 ) return ( 0 ) ;
if ( len > buf - > use ) return ( - 1 ) ;
buf - > use - = len ;
memmove ( buf - > content , & buf - > content [ len ] , buf - > use * sizeof ( xmlChar ) ) ;
buf - > content [ buf - > use ] = 0 ;
return ( len ) ;
}
/**
* xmlBufferGrow :
* @ buf : the buffer
* @ len : the minimum free size to allocate
*
* Grow the available space of an XML buffer .
*
* Returns the new available space or - 1 in case of error
*/
int
xmlBufferGrow ( xmlBufferPtr buf , unsigned int len ) {
int size ;
xmlChar * newbuf ;
if ( len + buf - > use < buf - > size ) return ( 0 ) ;
size = buf - > use + len + 100 ;
newbuf = ( xmlChar * ) xmlRealloc ( buf - > content , size ) ;
if ( newbuf = = NULL ) return ( - 1 ) ;
buf - > content = newbuf ;
buf - > size = size ;
return ( buf - > size - buf - > use ) ;
}
/**
* xmlBufferDump :
* @ file : the file output
* @ buf : the buffer to dump
*
* Dumps an XML buffer to a FILE * .
* Returns the number of xmlChar written
*/
int
xmlBufferDump ( FILE * file , xmlBufferPtr buf ) {
int ret ;
if ( buf = = NULL ) {
# ifdef DEBUG_BUFFER
xmlGenericError ( xmlGenericErrorContext ,
" xmlBufferDump: buf == NULL \n " ) ;
# endif
return ( 0 ) ;
}
if ( buf - > content = = NULL ) {
# ifdef DEBUG_BUFFER
xmlGenericError ( xmlGenericErrorContext ,
" xmlBufferDump: buf->content == NULL \n " ) ;
# endif
return ( 0 ) ;
}
2001-11-22 21:20:37 +03:00
if ( file = = NULL )
file = stdout ;
2001-02-23 20:55:21 +03:00
ret = fwrite ( buf - > content , sizeof ( xmlChar ) , buf - > use , file ) ;
return ( ret ) ;
}
/**
* xmlBufferContent :
* @ buf : the buffer
*
2001-07-18 23:30:27 +04:00
* Function to extract the content of a buffer
*
2001-02-23 20:55:21 +03:00
* Returns the internal content
*/
2001-07-18 23:30:27 +04:00
const xmlChar *
2001-02-23 20:55:21 +03:00
xmlBufferContent ( const xmlBufferPtr buf )
{
if ( ! buf )
return NULL ;
return buf - > content ;
}
/**
* xmlBufferLength :
* @ buf : the buffer
*
2001-07-18 23:30:27 +04:00
* Function to get the length of a buffer
*
2001-02-23 20:55:21 +03:00
* Returns the length of data in the internal content
*/
int
xmlBufferLength ( const xmlBufferPtr buf )
{
if ( ! buf )
return 0 ;
return buf - > use ;
}
/**
* xmlBufferResize :
* @ buf : the buffer to resize
* @ size : the desired size
*
* Resize a buffer to accomodate minimum size of @ size .
*
* Returns 0 in case of problems , 1 otherwise
*/
int
xmlBufferResize ( xmlBufferPtr buf , unsigned int size )
{
unsigned int newSize ;
xmlChar * rebuf = NULL ;
/*take care of empty case*/
newSize = ( buf - > size ? buf - > size * 2 : size ) ;
/* Don't resize if we don't have to */
if ( size < buf - > size )
return 1 ;
/* figure out new size */
switch ( buf - > alloc ) {
case XML_BUFFER_ALLOC_DOUBLEIT :
while ( size > newSize ) newSize * = 2 ;
break ;
case XML_BUFFER_ALLOC_EXACT :
newSize = size + 10 ;
break ;
default :
newSize = size + 10 ;
break ;
}
if ( buf - > content = = NULL )
rebuf = ( xmlChar * ) xmlMalloc ( newSize * sizeof ( xmlChar ) ) ;
else
rebuf = ( xmlChar * ) xmlRealloc ( buf - > content ,
newSize * sizeof ( xmlChar ) ) ;
if ( rebuf = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlBufferAdd : out of memory! \n " ) ;
return 0 ;
}
buf - > content = rebuf ;
buf - > size = newSize ;
return 1 ;
}
/**
* xmlBufferAdd :
* @ buf : the buffer to dump
* @ str : the xmlChar string
* @ len : the number of xmlChar to add
*
2001-10-10 13:45:09 +04:00
* Add a string range to an XML buffer . if len = = - 1 , the length of
2001-02-23 20:55:21 +03:00
* str is recomputed .
*/
void
xmlBufferAdd ( xmlBufferPtr buf , const xmlChar * str , int len ) {
unsigned int needSize ;
if ( str = = NULL ) {
# ifdef DEBUG_BUFFER
xmlGenericError ( xmlGenericErrorContext ,
" xmlBufferAdd: str == NULL \n " ) ;
# endif
return ;
}
if ( len < - 1 ) {
# ifdef DEBUG_BUFFER
xmlGenericError ( xmlGenericErrorContext ,
" xmlBufferAdd: len < 0 \n " ) ;
# endif
return ;
}
if ( len = = 0 ) return ;
if ( len < 0 )
len = xmlStrlen ( str ) ;
if ( len < = 0 ) return ;
needSize = buf - > use + len + 2 ;
if ( needSize > buf - > size ) {
if ( ! xmlBufferResize ( buf , needSize ) ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlBufferAdd : out of memory! \n " ) ;
return ;
}
}
memmove ( & buf - > content [ buf - > use ] , str , len * sizeof ( xmlChar ) ) ;
buf - > use + = len ;
buf - > content [ buf - > use ] = 0 ;
}
/**
* xmlBufferAddHead :
* @ buf : the buffer
* @ str : the xmlChar string
* @ len : the number of xmlChar to add
*
* Add a string range to the beginning of an XML buffer .
2001-10-10 13:45:09 +04:00
* if len = = - 1 , the length of @ str is recomputed .
2001-02-23 20:55:21 +03:00
*/
void
xmlBufferAddHead ( xmlBufferPtr buf , const xmlChar * str , int len ) {
unsigned int needSize ;
if ( str = = NULL ) {
# ifdef DEBUG_BUFFER
xmlGenericError ( xmlGenericErrorContext ,
" xmlBufferAdd: str == NULL \n " ) ;
# endif
return ;
}
if ( len < - 1 ) {
# ifdef DEBUG_BUFFER
xmlGenericError ( xmlGenericErrorContext ,
" xmlBufferAdd: len < 0 \n " ) ;
# endif
return ;
}
if ( len = = 0 ) return ;
if ( len < 0 )
len = xmlStrlen ( str ) ;
if ( len < = 0 ) return ;
needSize = buf - > use + len + 2 ;
if ( needSize > buf - > size ) {
if ( ! xmlBufferResize ( buf , needSize ) ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlBufferAddHead : out of memory! \n " ) ;
return ;
}
}
memmove ( & buf - > content [ len ] , & buf - > content [ 0 ] , buf - > use * sizeof ( xmlChar ) ) ;
memmove ( & buf - > content [ 0 ] , str , len * sizeof ( xmlChar ) ) ;
buf - > use + = len ;
buf - > content [ buf - > use ] = 0 ;
}
/**
* xmlBufferCat :
* @ buf : the buffer to dump
* @ str : the xmlChar string
*
* Append a zero terminated string to an XML buffer .
*/
void
xmlBufferCat ( xmlBufferPtr buf , const xmlChar * str ) {
if ( str ! = NULL )
xmlBufferAdd ( buf , str , - 1 ) ;
}
/**
* xmlBufferCCat :
* @ buf : the buffer to dump
* @ str : the C char string
*
* Append a zero terminated C string to an XML buffer .
*/
void
xmlBufferCCat ( xmlBufferPtr buf , const char * str ) {
const char * cur ;
if ( str = = NULL ) {
# ifdef DEBUG_BUFFER
xmlGenericError ( xmlGenericErrorContext ,
" xmlBufferAdd: str == NULL \n " ) ;
# endif
return ;
}
for ( cur = str ; * cur ! = 0 ; cur + + ) {
if ( buf - > use + 10 > = buf - > size ) {
if ( ! xmlBufferResize ( buf , buf - > use + 10 ) ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlBufferCCat : out of memory! \n " ) ;
return ;
}
}
buf - > content [ buf - > use + + ] = * cur ;
}
buf - > content [ buf - > use ] = 0 ;
}
2001-07-18 23:30:27 +04:00
/**
* xmlBufferWriteXmlCHAR :
* @ buf : the XML buffer
* @ string : the string to add
*
* For VMS only .
* routine which manages and grows an output buffer . This one adds
* xmlChars at the end of the buffer .
*/
2001-02-23 20:55:21 +03:00
/**
* xmlBufferWriteCHAR :
* @ buf : the XML buffer
* @ string : the string to add
*
* routine which manages and grows an output buffer . This one adds
* xmlChars at the end of the buffer .
*/
void
# ifdef VMS
xmlBufferWriteXmlCHAR
# else
xmlBufferWriteCHAR
# endif
( xmlBufferPtr buf , const xmlChar * string ) {
xmlBufferCat ( buf , string ) ;
}
/**
* xmlBufferWriteChar :
* @ buf : the XML buffer output
* @ string : the string to add
*
* routine which manage and grows an output buffer . This one add
* C chars at the end of the array .
*/
void
xmlBufferWriteChar ( xmlBufferPtr buf , const char * string ) {
xmlBufferCCat ( buf , string ) ;
}
/**
* xmlBufferWriteQuotedString :
* @ buf : the XML buffer output
* @ string : the string to add
*
* routine which manage and grows an output buffer . This one writes
* a quoted or double quoted xmlChar string , checking first if it holds
* quote or double - quotes internally
*/
void
xmlBufferWriteQuotedString ( xmlBufferPtr buf , const xmlChar * string ) {
if ( xmlStrchr ( string , ' " ' ) ) {
if ( xmlStrchr ( string , ' \' ' ) ) {
# ifdef DEBUG_BUFFER
xmlGenericError ( xmlGenericErrorContext ,
" xmlBufferWriteQuotedString: string contains quote and double-quotes ! \n " ) ;
# endif
}
xmlBufferCCat ( buf , " ' " ) ;
xmlBufferCat ( buf , string ) ;
xmlBufferCCat ( buf , " ' " ) ;
} else {
xmlBufferCCat ( buf , " \" " ) ;
xmlBufferCat ( buf , string ) ;
xmlBufferCCat ( buf , " \" " ) ;
}
}
/************************************************************************
* *
* Dumping XML tree content to a simple buffer *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void
xmlNodeDump ( xmlBufferPtr buf , xmlDocPtr doc , xmlNodePtr cur , int level ,
int format ) ;
static void
xmlNodeListDump ( xmlBufferPtr buf , xmlDocPtr doc , xmlNodePtr cur , int level ,
int format ) ;
void
htmlNodeDump ( xmlBufferPtr buf , xmlDocPtr doc , xmlNodePtr cur ) ;
/**
* xmlNsDump :
* @ buf : the XML buffer output
* @ cur : a namespace
*
* Dump a local Namespace definition .
* Should be called in the context of attributes dumps .
*/
static void
xmlNsDump ( xmlBufferPtr buf , xmlNsPtr cur ) {
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNsDump : Ns == NULL \n " ) ;
# endif
return ;
}
if ( cur - > type = = XML_LOCAL_NAMESPACE ) {
/* Within the context of an element attributes */
if ( cur - > prefix ! = NULL ) {
xmlBufferWriteChar ( buf , " xmlns: " ) ;
xmlBufferWriteCHAR ( buf , cur - > prefix ) ;
} else
xmlBufferWriteChar ( buf , " xmlns " ) ;
xmlBufferWriteChar ( buf , " = " ) ;
xmlBufferWriteQuotedString ( buf , cur - > href ) ;
}
}
/**
* xmlNsListDump :
* @ buf : the XML buffer output
* @ cur : the first namespace
*
* Dump a list of local Namespace definitions .
* Should be called in the context of attributes dumps .
*/
static void
xmlNsListDump ( xmlBufferPtr buf , xmlNsPtr cur ) {
while ( cur ! = NULL ) {
xmlNsDump ( buf , cur ) ;
cur = cur - > next ;
}
}
/**
* xmlDtdDump :
* @ buf : the XML buffer output
* @ doc : the document
*
* Dump the XML document DTD , if any .
*/
static void
xmlDtdDump ( xmlBufferPtr buf , xmlDtdPtr dtd ) {
if ( dtd = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlDtdDump : no internal subset \n " ) ;
# endif
return ;
}
xmlBufferWriteChar ( buf , " <!DOCTYPE " ) ;
xmlBufferWriteCHAR ( buf , dtd - > name ) ;
if ( dtd - > ExternalID ! = NULL ) {
xmlBufferWriteChar ( buf , " PUBLIC " ) ;
xmlBufferWriteQuotedString ( buf , dtd - > ExternalID ) ;
xmlBufferWriteChar ( buf , " " ) ;
xmlBufferWriteQuotedString ( buf , dtd - > SystemID ) ;
} else if ( dtd - > SystemID ! = NULL ) {
xmlBufferWriteChar ( buf , " SYSTEM " ) ;
xmlBufferWriteQuotedString ( buf , dtd - > SystemID ) ;
}
if ( ( dtd - > entities = = NULL ) & & ( dtd - > elements = = NULL ) & &
( dtd - > attributes = = NULL ) & & ( dtd - > notations = = NULL ) ) {
xmlBufferWriteChar ( buf , " > " ) ;
return ;
}
xmlBufferWriteChar ( buf , " [ \n " ) ;
xmlNodeListDump ( buf , dtd - > doc , dtd - > children , - 1 , 0 ) ;
#if 0
if ( dtd - > entities ! = NULL )
xmlDumpEntitiesTable ( buf , ( xmlEntitiesTablePtr ) dtd - > entities ) ;
if ( dtd - > notations ! = NULL )
xmlDumpNotationTable ( buf , ( xmlNotationTablePtr ) dtd - > notations ) ;
if ( dtd - > elements ! = NULL )
xmlDumpElementTable ( buf , ( xmlElementTablePtr ) dtd - > elements ) ;
if ( dtd - > attributes ! = NULL )
xmlDumpAttributeTable ( buf , ( xmlAttributeTablePtr ) dtd - > attributes ) ;
# endif
xmlBufferWriteChar ( buf , " ]> " ) ;
}
/**
* xmlAttrDump :
* @ buf : the XML buffer output
* @ doc : the document
* @ cur : the attribute pointer
*
* Dump an XML attribute
*/
static void
xmlAttrDump ( xmlBufferPtr buf , xmlDocPtr doc , xmlAttrPtr cur ) {
xmlChar * value ;
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlAttrDump : property == NULL \n " ) ;
# endif
return ;
}
xmlBufferWriteChar ( buf , " " ) ;
if ( ( cur - > ns ! = NULL ) & & ( cur - > ns - > prefix ! = NULL ) ) {
xmlBufferWriteCHAR ( buf , cur - > ns - > prefix ) ;
xmlBufferWriteChar ( buf , " : " ) ;
}
xmlBufferWriteCHAR ( buf , cur - > name ) ;
value = xmlNodeListGetString ( doc , cur - > children , 0 ) ;
if ( value ! = NULL ) {
xmlBufferWriteChar ( buf , " = " ) ;
xmlBufferWriteQuotedString ( buf , value ) ;
xmlFree ( value ) ;
} else {
xmlBufferWriteChar ( buf , " = \" \" " ) ;
}
}
/**
* xmlAttrListDump :
* @ buf : the XML buffer output
* @ doc : the document
* @ cur : the first attribute pointer
*
* Dump a list of XML attributes
*/
static void
xmlAttrListDump ( xmlBufferPtr buf , xmlDocPtr doc , xmlAttrPtr cur ) {
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlAttrListDump : property == NULL \n " ) ;
# endif
return ;
}
while ( cur ! = NULL ) {
xmlAttrDump ( buf , doc , cur ) ;
cur = cur - > next ;
}
}
/**
* xmlNodeListDump :
* @ buf : the XML buffer output
* @ doc : the document
* @ cur : the first node
* @ level : the imbrication level for indenting
* @ format : is formatting allowed
*
* Dump an XML node list , recursive behaviour , children are printed too .
*/
static void
xmlNodeListDump ( xmlBufferPtr buf , xmlDocPtr doc , xmlNodePtr cur , int level ,
int format ) {
int i ;
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNodeListDump : node == NULL \n " ) ;
# endif
return ;
}
while ( cur ! = NULL ) {
if ( ( format ) & & ( xmlIndentTreeOutput ) & &
( cur - > type = = XML_ELEMENT_NODE ) )
for ( i = 0 ; i < level ; i + + )
xmlBufferWriteChar ( buf , " " ) ;
xmlNodeDump ( buf , doc , cur , level , format ) ;
if ( format ) {
xmlBufferWriteChar ( buf , " \n " ) ;
}
cur = cur - > next ;
}
}
/**
* xmlNodeDump :
* @ buf : the XML buffer output
* @ doc : the document
* @ cur : the current node
* @ level : the imbrication level for indenting
* @ format : is formatting allowed
*
* Dump an XML node , recursive behaviour , children are printed too .
*/
void
xmlNodeDump ( xmlBufferPtr buf , xmlDocPtr doc , xmlNodePtr cur , int level ,
int format ) {
int i ;
xmlNodePtr tmp ;
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNodeDump : node == NULL \n " ) ;
# endif
return ;
}
if ( cur - > type = = XML_XINCLUDE_START )
return ;
if ( cur - > type = = XML_XINCLUDE_END )
return ;
if ( cur - > type = = XML_DTD_NODE ) {
xmlDtdDump ( buf , ( xmlDtdPtr ) cur ) ;
return ;
}
if ( cur - > type = = XML_ELEMENT_DECL ) {
xmlDumpElementDecl ( buf , ( xmlElementPtr ) cur ) ;
return ;
}
2001-10-11 13:12:24 +04:00
if ( cur - > type = = XML_ATTRIBUTE_NODE ) {
xmlAttrDump ( buf , doc , ( xmlAttrPtr ) cur ) ;
return ;
}
2001-02-23 20:55:21 +03:00
if ( cur - > type = = XML_ATTRIBUTE_DECL ) {
xmlDumpAttributeDecl ( buf , ( xmlAttributePtr ) cur ) ;
return ;
}
if ( cur - > type = = XML_ENTITY_DECL ) {
xmlDumpEntityDecl ( buf , ( xmlEntityPtr ) cur ) ;
return ;
}
if ( cur - > type = = XML_TEXT_NODE ) {
if ( cur - > content ! = NULL ) {
if ( ( cur - > name = = xmlStringText ) | |
( cur - > name ! = xmlStringTextNoenc ) ) {
xmlChar * buffer ;
# ifndef XML_USE_BUFFER_CONTENT
buffer = xmlEncodeEntitiesReentrant ( doc , cur - > content ) ;
# else
buffer = xmlEncodeEntitiesReentrant ( doc ,
xmlBufferContent ( cur - > content ) ) ;
# endif
if ( buffer ! = NULL ) {
xmlBufferWriteCHAR ( buf , buffer ) ;
xmlFree ( buffer ) ;
}
} else {
/*
* Disable escaping , needed for XSLT
*/
# ifndef XML_USE_BUFFER_CONTENT
xmlBufferWriteCHAR ( buf , cur - > content ) ;
# else
xmlBufferWriteCHAR ( buf , xmlBufferContent ( cur - > content ) ) ;
# endif
}
}
return ;
}
if ( cur - > type = = XML_PI_NODE ) {
if ( cur - > content ! = NULL ) {
xmlBufferWriteChar ( buf , " <? " ) ;
xmlBufferWriteCHAR ( buf , cur - > name ) ;
if ( cur - > content ! = NULL ) {
xmlBufferWriteChar ( buf , " " ) ;
# ifndef XML_USE_BUFFER_CONTENT
xmlBufferWriteCHAR ( buf , cur - > content ) ;
# else
xmlBufferWriteCHAR ( buf , xmlBufferContent ( cur - > content ) ) ;
# endif
}
xmlBufferWriteChar ( buf , " ?> " ) ;
} else {
xmlBufferWriteChar ( buf , " <? " ) ;
xmlBufferWriteCHAR ( buf , cur - > name ) ;
xmlBufferWriteChar ( buf , " ?> " ) ;
}
return ;
}
if ( cur - > type = = XML_COMMENT_NODE ) {
if ( cur - > content ! = NULL ) {
xmlBufferWriteChar ( buf , " <!-- " ) ;
# ifndef XML_USE_BUFFER_CONTENT
xmlBufferWriteCHAR ( buf , cur - > content ) ;
# else
xmlBufferWriteCHAR ( buf , xmlBufferContent ( cur - > content ) ) ;
# endif
xmlBufferWriteChar ( buf , " --> " ) ;
}
return ;
}
if ( cur - > type = = XML_ENTITY_REF_NODE ) {
xmlBufferWriteChar ( buf , " & " ) ;
xmlBufferWriteCHAR ( buf , cur - > name ) ;
xmlBufferWriteChar ( buf , " ; " ) ;
return ;
}
if ( cur - > type = = XML_CDATA_SECTION_NODE ) {
xmlBufferWriteChar ( buf , " <![CDATA[ " ) ;
if ( cur - > content ! = NULL )
# ifndef XML_USE_BUFFER_CONTENT
xmlBufferWriteCHAR ( buf , cur - > content ) ;
# else
xmlBufferWriteCHAR ( buf , xmlBufferContent ( cur - > content ) ) ;
# endif
xmlBufferWriteChar ( buf , " ]]> " ) ;
return ;
}
if ( format = = 1 ) {
tmp = cur - > children ;
while ( tmp ! = NULL ) {
if ( ( tmp - > type = = XML_TEXT_NODE ) | |
( tmp - > type = = XML_ENTITY_REF_NODE ) ) {
format = 0 ;
break ;
}
tmp = tmp - > next ;
}
}
xmlBufferWriteChar ( buf , " < " ) ;
if ( ( cur - > ns ! = NULL ) & & ( cur - > ns - > prefix ! = NULL ) ) {
xmlBufferWriteCHAR ( buf , cur - > ns - > prefix ) ;
xmlBufferWriteChar ( buf , " : " ) ;
}
xmlBufferWriteCHAR ( buf , cur - > name ) ;
if ( cur - > nsDef )
xmlNsListDump ( buf , cur - > nsDef ) ;
if ( cur - > properties ! = NULL )
xmlAttrListDump ( buf , doc , cur - > properties ) ;
2001-07-12 05:20:08 +04:00
if ( ( ( cur - > type = = XML_ELEMENT_NODE ) | | ( cur - > content = = NULL ) ) & &
( cur - > children = = NULL ) & &
2001-02-23 20:55:21 +03:00
( ! xmlSaveNoEmptyTags ) ) {
xmlBufferWriteChar ( buf , " /> " ) ;
return ;
}
xmlBufferWriteChar ( buf , " > " ) ;
2001-07-12 05:20:08 +04:00
if ( ( cur - > type ! = XML_ELEMENT_NODE ) & & ( cur - > content ! = NULL ) ) {
2001-02-23 20:55:21 +03:00
xmlChar * buffer ;
# ifndef XML_USE_BUFFER_CONTENT
buffer = xmlEncodeEntitiesReentrant ( doc , cur - > content ) ;
# else
buffer = xmlEncodeEntitiesReentrant ( doc ,
xmlBufferContent ( cur - > content ) ) ;
# endif
if ( buffer ! = NULL ) {
xmlBufferWriteCHAR ( buf , buffer ) ;
xmlFree ( buffer ) ;
}
}
if ( cur - > children ! = NULL ) {
if ( format ) xmlBufferWriteChar ( buf , " \n " ) ;
xmlNodeListDump ( buf , doc , cur - > children ,
( level > = 0 ? level + 1 : - 1 ) , format ) ;
if ( ( xmlIndentTreeOutput ) & & ( format ) )
for ( i = 0 ; i < level ; i + + )
xmlBufferWriteChar ( buf , " " ) ;
}
xmlBufferWriteChar ( buf , " </ " ) ;
if ( ( cur - > ns ! = NULL ) & & ( cur - > ns - > prefix ! = NULL ) ) {
xmlBufferWriteCHAR ( buf , cur - > ns - > prefix ) ;
xmlBufferWriteChar ( buf , " : " ) ;
}
xmlBufferWriteCHAR ( buf , cur - > name ) ;
xmlBufferWriteChar ( buf , " > " ) ;
}
/**
* xmlElemDump :
* @ f : the FILE * for the output
* @ doc : the document
* @ cur : the current node
*
* Dump an XML / HTML node , recursive behaviour , children are printed too .
*/
void
xmlElemDump ( FILE * f , xmlDocPtr doc , xmlNodePtr cur ) {
xmlBufferPtr buf ;
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlElemDump : cur == NULL \n " ) ;
# endif
return ;
}
# ifdef DEBUG_TREE
2001-06-22 02:07:42 +04:00
if ( doc = = NULL ) {
2001-02-23 20:55:21 +03:00
xmlGenericError ( xmlGenericErrorContext ,
" xmlElemDump : doc == NULL \n " ) ;
}
2001-06-22 02:07:42 +04:00
# endif
2001-10-11 13:12:24 +04:00
2001-02-23 20:55:21 +03:00
buf = xmlBufferCreate ( ) ;
if ( buf = = NULL ) return ;
if ( ( doc ! = NULL ) & &
( doc - > type = = XML_HTML_DOCUMENT_NODE ) ) {
# ifdef LIBXML_HTML_ENABLED
htmlNodeDump ( buf , doc , cur ) ;
# else
xmlGenericError ( xmlGenericErrorContext ,
" HTML support not compiled in \n " ) ;
# endif /* LIBXML_HTML_ENABLED */
} else
xmlNodeDump ( buf , doc , cur , 0 , 1 ) ;
xmlBufferDump ( f , buf ) ;
xmlBufferFree ( buf ) ;
}
/************************************************************************
* *
* Dumping XML tree content to an I / O output buffer *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void
xmlNodeDumpOutput ( xmlOutputBufferPtr buf , xmlDocPtr doc , xmlNodePtr cur ,
int level , int format , const char * encoding ) ;
static void
xmlNodeListDumpOutput ( xmlOutputBufferPtr buf , xmlDocPtr doc , xmlNodePtr cur ,
int level , int format , const char * encoding ) ;
/**
* xmlNsDumpOutput :
* @ buf : the XML buffer output
* @ cur : a namespace
*
* Dump a local Namespace definition .
* Should be called in the context of attributes dumps .
*/
static void
xmlNsDumpOutput ( xmlOutputBufferPtr buf , xmlNsPtr cur ) {
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNsDump : Ns == NULL \n " ) ;
# endif
return ;
}
if ( ( cur - > type = = XML_LOCAL_NAMESPACE ) & & ( cur - > href ! = NULL ) ) {
/* Within the context of an element attributes */
if ( cur - > prefix ! = NULL ) {
xmlOutputBufferWriteString ( buf , " xmlns: " ) ;
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > prefix ) ;
} else
xmlOutputBufferWriteString ( buf , " xmlns " ) ;
xmlOutputBufferWriteString ( buf , " = " ) ;
xmlBufferWriteQuotedString ( buf - > buffer , cur - > href ) ;
}
}
/**
* xmlNsListDumpOutput :
* @ buf : the XML buffer output
* @ cur : the first namespace
*
* Dump a list of local Namespace definitions .
* Should be called in the context of attributes dumps .
*/
static void
xmlNsListDumpOutput ( xmlOutputBufferPtr buf , xmlNsPtr cur ) {
while ( cur ! = NULL ) {
xmlNsDumpOutput ( buf , cur ) ;
cur = cur - > next ;
}
}
/**
* xmlDtdDumpOutput :
* @ buf : the XML buffer output
* @ doc : the document
* @ encoding : an optional encoding string
*
* Dump the XML document DTD , if any .
*/
static void
xmlDtdDumpOutput ( xmlOutputBufferPtr buf , xmlDtdPtr dtd , const char * encoding ) {
if ( dtd = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlDtdDump : no internal subset \n " ) ;
# endif
return ;
}
xmlOutputBufferWriteString ( buf , " <!DOCTYPE " ) ;
xmlOutputBufferWriteString ( buf , ( const char * ) dtd - > name ) ;
if ( dtd - > ExternalID ! = NULL ) {
xmlOutputBufferWriteString ( buf , " PUBLIC " ) ;
xmlBufferWriteQuotedString ( buf - > buffer , dtd - > ExternalID ) ;
xmlOutputBufferWriteString ( buf , " " ) ;
xmlBufferWriteQuotedString ( buf - > buffer , dtd - > SystemID ) ;
} else if ( dtd - > SystemID ! = NULL ) {
xmlOutputBufferWriteString ( buf , " SYSTEM " ) ;
xmlBufferWriteQuotedString ( buf - > buffer , dtd - > SystemID ) ;
}
if ( ( dtd - > entities = = NULL ) & & ( dtd - > elements = = NULL ) & &
( dtd - > attributes = = NULL ) & & ( dtd - > notations = = NULL ) ) {
xmlOutputBufferWriteString ( buf , " > " ) ;
return ;
}
xmlOutputBufferWriteString ( buf , " [ \n " ) ;
xmlNodeListDumpOutput ( buf , dtd - > doc , dtd - > children , - 1 , 0 , encoding ) ;
xmlOutputBufferWriteString ( buf , " ]> " ) ;
}
/**
* xmlAttrDumpOutput :
* @ buf : the XML buffer output
* @ doc : the document
* @ cur : the attribute pointer
* @ encoding : an optional encoding string
*
* Dump an XML attribute
*/
static void
xmlAttrDumpOutput ( xmlOutputBufferPtr buf , xmlDocPtr doc , xmlAttrPtr cur ,
2001-03-26 20:28:29 +04:00
const char * encoding ATTRIBUTE_UNUSED ) {
2001-02-23 20:55:21 +03:00
xmlChar * value ;
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlAttrDump : property == NULL \n " ) ;
# endif
return ;
}
xmlOutputBufferWriteString ( buf , " " ) ;
if ( ( cur - > ns ! = NULL ) & & ( cur - > ns - > prefix ! = NULL ) ) {
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > ns - > prefix ) ;
xmlOutputBufferWriteString ( buf , " : " ) ;
}
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > name ) ;
value = xmlNodeListGetString ( doc , cur - > children , 0 ) ;
if ( value ) {
xmlOutputBufferWriteString ( buf , " = " ) ;
xmlBufferWriteQuotedString ( buf - > buffer , value ) ;
xmlFree ( value ) ;
} else {
xmlOutputBufferWriteString ( buf , " = \" \" " ) ;
}
}
/**
* xmlAttrListDumpOutput :
* @ buf : the XML buffer output
* @ doc : the document
* @ cur : the first attribute pointer
* @ encoding : an optional encoding string
*
* Dump a list of XML attributes
*/
static void
xmlAttrListDumpOutput ( xmlOutputBufferPtr buf , xmlDocPtr doc ,
xmlAttrPtr cur , const char * encoding ) {
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlAttrListDump : property == NULL \n " ) ;
# endif
return ;
}
while ( cur ! = NULL ) {
xmlAttrDumpOutput ( buf , doc , cur , encoding ) ;
cur = cur - > next ;
}
}
/**
* xmlNodeListDumpOutput :
* @ buf : the XML buffer output
* @ doc : the document
* @ cur : the first node
* @ level : the imbrication level for indenting
* @ format : is formatting allowed
* @ encoding : an optional encoding string
*
* Dump an XML node list , recursive behaviour , children are printed too .
*/
static void
xmlNodeListDumpOutput ( xmlOutputBufferPtr buf , xmlDocPtr doc ,
xmlNodePtr cur , int level , int format , const char * encoding ) {
int i ;
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNodeListDump : node == NULL \n " ) ;
# endif
return ;
}
while ( cur ! = NULL ) {
if ( ( format ) & & ( xmlIndentTreeOutput ) & &
( cur - > type = = XML_ELEMENT_NODE ) )
for ( i = 0 ; i < level ; i + + )
xmlOutputBufferWriteString ( buf , " " ) ;
xmlNodeDumpOutput ( buf , doc , cur , level , format , encoding ) ;
if ( format ) {
xmlOutputBufferWriteString ( buf , " \n " ) ;
}
cur = cur - > next ;
}
}
/**
* xmlNodeDumpOutput :
* @ buf : the XML buffer output
* @ doc : the document
* @ cur : the current node
* @ level : the imbrication level for indenting
* @ format : is formatting allowed
* @ encoding : an optional encoding string
*
* Dump an XML node , recursive behaviour , children are printed too .
*/
void
xmlNodeDumpOutput ( xmlOutputBufferPtr buf , xmlDocPtr doc , xmlNodePtr cur ,
int level , int format , const char * encoding ) {
int i ;
xmlNodePtr tmp ;
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNodeDump : node == NULL \n " ) ;
# endif
return ;
}
if ( cur - > type = = XML_XINCLUDE_START )
return ;
if ( cur - > type = = XML_XINCLUDE_END )
return ;
if ( cur - > type = = XML_DTD_NODE ) {
xmlDtdDumpOutput ( buf , ( xmlDtdPtr ) cur , encoding ) ;
return ;
}
if ( cur - > type = = XML_ELEMENT_DECL ) {
xmlDumpElementDecl ( buf - > buffer , ( xmlElementPtr ) cur ) ;
return ;
}
if ( cur - > type = = XML_ATTRIBUTE_DECL ) {
xmlDumpAttributeDecl ( buf - > buffer , ( xmlAttributePtr ) cur ) ;
return ;
}
if ( cur - > type = = XML_ENTITY_DECL ) {
xmlDumpEntityDecl ( buf - > buffer , ( xmlEntityPtr ) cur ) ;
return ;
}
if ( cur - > type = = XML_TEXT_NODE ) {
if ( cur - > content ! = NULL ) {
if ( ( cur - > name = = xmlStringText ) | |
( cur - > name ! = xmlStringTextNoenc ) ) {
xmlChar * buffer ;
# ifndef XML_USE_BUFFER_CONTENT
if ( encoding = = NULL )
buffer = xmlEncodeEntitiesReentrant ( doc , cur - > content ) ;
else
buffer = xmlEncodeSpecialChars ( doc , cur - > content ) ;
# else
if ( encoding = = NULL )
buffer = xmlEncodeEntitiesReentrant ( doc ,
xmlBufferContent ( cur - > content ) ) ;
else
buffer = xmlEncodeSpecialChars ( doc ,
xmlBufferContent ( cur - > content ) ) ;
# endif
if ( buffer ! = NULL ) {
xmlOutputBufferWriteString ( buf , ( const char * ) buffer ) ;
xmlFree ( buffer ) ;
}
} else {
/*
* Disable escaping , needed for XSLT
*/
# ifndef XML_USE_BUFFER_CONTENT
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > content ) ;
# else
xmlOutputBufferWriteString ( buf , xmlBufferContent ( cur - > content ) ) ;
# endif
}
}
return ;
}
if ( cur - > type = = XML_PI_NODE ) {
if ( cur - > content ! = NULL ) {
xmlOutputBufferWriteString ( buf , " <? " ) ;
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > name ) ;
if ( cur - > content ! = NULL ) {
xmlOutputBufferWriteString ( buf , " " ) ;
# ifndef XML_USE_BUFFER_CONTENT
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > content ) ;
# else
xmlOutputBufferWriteString ( buf , ( const char * ) xmlBufferContent ( cur - > content ) ) ;
# endif
}
xmlOutputBufferWriteString ( buf , " ?> " ) ;
} else {
xmlOutputBufferWriteString ( buf , " <? " ) ;
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > name ) ;
xmlOutputBufferWriteString ( buf , " ?> " ) ;
}
return ;
}
if ( cur - > type = = XML_COMMENT_NODE ) {
if ( cur - > content ! = NULL ) {
xmlOutputBufferWriteString ( buf , " <!-- " ) ;
# ifndef XML_USE_BUFFER_CONTENT
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > content ) ;
# else
xmlOutputBufferWriteString ( buf , ( const char * ) xmlBufferContent ( cur - > content ) ) ;
# endif
xmlOutputBufferWriteString ( buf , " --> " ) ;
}
return ;
}
if ( cur - > type = = XML_ENTITY_REF_NODE ) {
xmlOutputBufferWriteString ( buf , " & " ) ;
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > name ) ;
xmlOutputBufferWriteString ( buf , " ; " ) ;
return ;
}
if ( cur - > type = = XML_CDATA_SECTION_NODE ) {
xmlOutputBufferWriteString ( buf , " <![CDATA[ " ) ;
if ( cur - > content ! = NULL )
# ifndef XML_USE_BUFFER_CONTENT
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > content ) ;
# else
xmlOutputBufferWriteString ( buf , ( const char * ) xmlBufferContent ( cur - > content ) ) ;
# endif
xmlOutputBufferWriteString ( buf , " ]]> " ) ;
return ;
}
if ( format = = 1 ) {
tmp = cur - > children ;
while ( tmp ! = NULL ) {
if ( ( tmp - > type = = XML_TEXT_NODE ) | |
( tmp - > type = = XML_ENTITY_REF_NODE ) ) {
format = 0 ;
break ;
}
tmp = tmp - > next ;
}
}
xmlOutputBufferWriteString ( buf , " < " ) ;
if ( ( cur - > ns ! = NULL ) & & ( cur - > ns - > prefix ! = NULL ) ) {
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > ns - > prefix ) ;
xmlOutputBufferWriteString ( buf , " : " ) ;
}
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > name ) ;
if ( cur - > nsDef )
xmlNsListDumpOutput ( buf , cur - > nsDef ) ;
if ( cur - > properties ! = NULL )
xmlAttrListDumpOutput ( buf , doc , cur - > properties , encoding ) ;
2001-07-12 05:20:08 +04:00
if ( ( ( cur - > type = = XML_ELEMENT_NODE ) | | ( cur - > content = = NULL ) ) & &
( cur - > children = = NULL ) & & ( ! xmlSaveNoEmptyTags ) ) {
2001-02-23 20:55:21 +03:00
xmlOutputBufferWriteString ( buf , " /> " ) ;
return ;
}
xmlOutputBufferWriteString ( buf , " > " ) ;
2001-07-12 05:20:08 +04:00
if ( ( cur - > type ! = XML_ELEMENT_NODE ) & & ( cur - > content ! = NULL ) ) {
2001-02-23 20:55:21 +03:00
xmlChar * buffer ;
# ifndef XML_USE_BUFFER_CONTENT
if ( encoding = = NULL )
buffer = xmlEncodeEntitiesReentrant ( doc , cur - > content ) ;
else
buffer = xmlEncodeSpecialChars ( doc , cur - > content ) ;
# else
if ( encoding = = NULL )
buffer = xmlEncodeEntitiesReentrant ( doc ,
xmlBufferContent ( cur - > content ) ) ;
else
buffer = xmlEncodeSpecialChars ( doc ,
xmlBufferContent ( cur - > content ) ) ;
# endif
if ( buffer ! = NULL ) {
xmlOutputBufferWriteString ( buf , ( const char * ) buffer ) ;
xmlFree ( buffer ) ;
}
}
if ( cur - > children ! = NULL ) {
if ( format ) xmlOutputBufferWriteString ( buf , " \n " ) ;
xmlNodeListDumpOutput ( buf , doc , cur - > children ,
( level > = 0 ? level + 1 : - 1 ) , format , encoding ) ;
if ( ( xmlIndentTreeOutput ) & & ( format ) )
for ( i = 0 ; i < level ; i + + )
xmlOutputBufferWriteString ( buf , " " ) ;
}
xmlOutputBufferWriteString ( buf , " </ " ) ;
if ( ( cur - > ns ! = NULL ) & & ( cur - > ns - > prefix ! = NULL ) ) {
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > ns - > prefix ) ;
xmlOutputBufferWriteString ( buf , " : " ) ;
}
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > name ) ;
xmlOutputBufferWriteString ( buf , " > " ) ;
}
/**
* xmlDocContentDumpOutput :
* @ buf : the XML buffer output
* @ cur : the document
* @ encoding : an optional encoding string
* @ format : should formatting spaces been added
*
* Dump an XML document .
*/
static void
xmlDocContentDumpOutput ( xmlOutputBufferPtr buf , xmlDocPtr cur ,
const char * encoding , int format ) {
xmlOutputBufferWriteString ( buf , " <?xml version= " ) ;
if ( cur - > version ! = NULL )
xmlBufferWriteQuotedString ( buf - > buffer , cur - > version ) ;
else
xmlOutputBufferWriteString ( buf , " \" 1.0 \" " ) ;
if ( encoding = = NULL ) {
if ( cur - > encoding ! = NULL )
encoding = ( const char * ) cur - > encoding ;
else if ( cur - > charset ! = XML_CHAR_ENCODING_UTF8 )
encoding = xmlGetCharEncodingName ( ( xmlCharEncoding ) cur - > charset ) ;
}
if ( encoding ! = NULL ) {
xmlOutputBufferWriteString ( buf , " encoding= " ) ;
xmlBufferWriteQuotedString ( buf - > buffer , ( xmlChar * ) encoding ) ;
}
switch ( cur - > standalone ) {
case 0 :
xmlOutputBufferWriteString ( buf , " standalone= \" no \" " ) ;
break ;
case 1 :
xmlOutputBufferWriteString ( buf , " standalone= \" yes \" " ) ;
break ;
}
xmlOutputBufferWriteString ( buf , " ?> \n " ) ;
if ( cur - > children ! = NULL ) {
xmlNodePtr child = cur - > children ;
while ( child ! = NULL ) {
xmlNodeDumpOutput ( buf , cur , child , 0 , format , encoding ) ;
xmlOutputBufferWriteString ( buf , " \n " ) ;
child = child - > next ;
}
}
}
/************************************************************************
* *
* Saving functions front - ends *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
2001-07-18 23:30:27 +04:00
* xmlDocDumpFormatMemoryEnc :
2001-02-23 20:55:21 +03:00
* @ out_doc : Document to generate XML text from
* @ doc_txt_ptr : Memory pointer for allocated XML text
* @ doc_txt_len : Length of the generated XML text
* @ txt_encoding : Character encoding to use when generating XML text
* @ format : should formatting spaces been added
*
* Dump the current DOM tree into memory using the character encoding specified
* by the caller . Note it is up to the caller of this function to free the
* allocated memory .
*/
void
xmlDocDumpFormatMemoryEnc ( xmlDocPtr out_doc , xmlChar * * doc_txt_ptr ,
2001-03-24 20:00:36 +03:00
int * doc_txt_len , const char * txt_encoding ,
2001-04-10 20:38:06 +04:00
int format ) {
2001-02-23 20:55:21 +03:00
int dummy = 0 ;
xmlCharEncoding doc_charset ;
xmlOutputBufferPtr out_buff = NULL ;
xmlCharEncodingHandlerPtr conv_hdlr = NULL ;
if ( doc_txt_len = = NULL ) {
doc_txt_len = & dummy ; /* Continue, caller just won't get length */
}
if ( doc_txt_ptr = = NULL ) {
* doc_txt_len = 0 ;
xmlGenericError ( xmlGenericErrorContext ,
" xmlDocDumpFormatMemoryEnc: Null return buffer pointer. " ) ;
return ;
}
* doc_txt_ptr = NULL ;
* doc_txt_len = 0 ;
if ( out_doc = = NULL ) {
/* No document, no output */
xmlGenericError ( xmlGenericErrorContext ,
" xmlDocDumpFormatMemoryEnc: Null DOM tree document pointer. \n " ) ;
return ;
}
/*
* Validate the encoding value , if provided .
* This logic is copied from xmlSaveFileEnc .
*/
if ( txt_encoding = = NULL )
txt_encoding = ( const char * ) out_doc - > encoding ;
if ( txt_encoding ! = NULL ) {
doc_charset = xmlParseCharEncoding ( txt_encoding ) ;
if ( out_doc - > charset ! = XML_CHAR_ENCODING_UTF8 ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlDocDumpFormatMemoryEnc: Source document not in UTF8 \n " ) ;
return ;
} else if ( doc_charset ! = XML_CHAR_ENCODING_UTF8 ) {
conv_hdlr = xmlFindCharEncodingHandler ( txt_encoding ) ;
if ( conv_hdlr = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" %s: %s %s '%s' \n " ,
" xmlDocDumpFormatMemoryEnc " ,
" Failed to identify encoding handler for " ,
" character set " ,
txt_encoding ) ;
return ;
}
}
}
if ( ( out_buff = xmlAllocOutputBuffer ( conv_hdlr ) ) = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlDocDumpFormatMemoryEnc: Failed to allocate output buffer. \n " ) ;
return ;
}
2001-04-10 20:38:06 +04:00
xmlDocContentDumpOutput ( out_buff , out_doc , txt_encoding , format ) ;
2001-02-23 20:55:21 +03:00
xmlOutputBufferFlush ( out_buff ) ;
if ( out_buff - > conv ! = NULL ) {
* doc_txt_len = out_buff - > conv - > use ;
* doc_txt_ptr = xmlStrndup ( out_buff - > conv - > content , * doc_txt_len ) ;
} else {
* doc_txt_len = out_buff - > buffer - > use ;
* doc_txt_ptr = xmlStrndup ( out_buff - > buffer - > content , * doc_txt_len ) ;
}
( void ) xmlOutputBufferClose ( out_buff ) ;
if ( ( * doc_txt_ptr = = NULL ) & & ( * doc_txt_len > 0 ) ) {
* doc_txt_len = 0 ;
xmlGenericError ( xmlGenericErrorContext ,
" xmlDocDumpFormatMemoryEnc: %s \n " ,
" Failed to allocate memory for document text representation. " ) ;
}
return ;
}
/**
* xmlDocDumpMemory :
* @ cur : the document
* @ mem : OUT : the memory pointer
2001-10-10 13:45:09 +04:00
* @ size : OUT : the memory length
2001-02-23 20:55:21 +03:00
*
* Dump an XML document in memory and return the xmlChar * and it ' s size .
* It ' s up to the caller to free the memory .
*/
void
xmlDocDumpMemory ( xmlDocPtr cur , xmlChar * * mem , int * size ) {
xmlDocDumpFormatMemoryEnc ( cur , mem , size , NULL , 0 ) ;
}
/**
* xmlDocDumpFormatMemory :
* @ cur : the document
* @ mem : OUT : the memory pointer
2001-10-10 13:45:09 +04:00
* @ size : OUT : the memory length
2001-02-23 20:55:21 +03:00
* @ format : should formatting spaces been added
*
*
* Dump an XML document in memory and return the xmlChar * and it ' s size .
* It ' s up to the caller to free the memory .
*/
void
xmlDocDumpFormatMemory ( xmlDocPtr cur , xmlChar * * mem , int * size , int format ) {
xmlDocDumpFormatMemoryEnc ( cur , mem , size , NULL , format ) ;
}
/**
* xmlDocDumpMemoryEnc :
* @ out_doc : Document to generate XML text from
* @ doc_txt_ptr : Memory pointer for allocated XML text
* @ doc_txt_len : Length of the generated XML text
* @ txt_encoding : Character encoding to use when generating XML text
*
* Dump the current DOM tree into memory using the character encoding specified
* by the caller . Note it is up to the caller of this function to free the
* allocated memory .
*/
void
xmlDocDumpMemoryEnc ( xmlDocPtr out_doc , xmlChar * * doc_txt_ptr ,
int * doc_txt_len , const char * txt_encoding ) {
xmlDocDumpFormatMemoryEnc ( out_doc , doc_txt_ptr , doc_txt_len ,
2001-04-10 20:38:06 +04:00
txt_encoding , 0 ) ;
2001-02-23 20:55:21 +03:00
}
/**
* xmlGetDocCompressMode :
* @ doc : the document
*
* get the compression ratio for a document , ZLIB based
* Returns 0 ( uncompressed ) to 9 ( max compression )
*/
int
xmlGetDocCompressMode ( xmlDocPtr doc ) {
if ( doc = = NULL ) return ( - 1 ) ;
return ( doc - > compression ) ;
}
/**
* xmlSetDocCompressMode :
* @ doc : the document
* @ mode : the compression ratio
*
* set the compression ratio for a document , ZLIB based
* Correct values : 0 ( uncompressed ) to 9 ( max compression )
*/
void
xmlSetDocCompressMode ( xmlDocPtr doc , int mode ) {
if ( doc = = NULL ) return ;
if ( mode < 0 ) doc - > compression = 0 ;
else if ( mode > 9 ) doc - > compression = 9 ;
else doc - > compression = mode ;
}
/**
* xmlGetCompressMode :
*
* get the default compression mode used , ZLIB based .
* Returns 0 ( uncompressed ) to 9 ( max compression )
*/
int
xmlGetCompressMode ( void ) {
return ( xmlCompressMode ) ;
}
/**
* xmlSetCompressMode :
* @ mode : the compression ratio
*
* set the default compression mode used , ZLIB based
* Correct values : 0 ( uncompressed ) to 9 ( max compression )
*/
void
xmlSetCompressMode ( int mode ) {
if ( mode < 0 ) xmlCompressMode = 0 ;
else if ( mode > 9 ) xmlCompressMode = 9 ;
else xmlCompressMode = mode ;
}
/**
* xmlDocDump :
* @ f : the FILE *
* @ cur : the document
*
* Dump an XML document to an open FILE .
*
* returns : the number of byte written or - 1 in case of failure .
*/
int
xmlDocDump ( FILE * f , xmlDocPtr cur ) {
xmlOutputBufferPtr buf ;
const char * encoding ;
xmlCharEncodingHandlerPtr handler = NULL ;
int ret ;
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlDocDump : document == NULL \n " ) ;
# endif
return ( - 1 ) ;
}
encoding = ( const char * ) cur - > encoding ;
if ( encoding ! = NULL ) {
xmlCharEncoding enc ;
enc = xmlParseCharEncoding ( encoding ) ;
if ( cur - > charset ! = XML_CHAR_ENCODING_UTF8 ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlDocDump: document not in UTF8 \n " ) ;
return ( - 1 ) ;
}
if ( enc ! = XML_CHAR_ENCODING_UTF8 ) {
handler = xmlFindCharEncodingHandler ( encoding ) ;
if ( handler = = NULL ) {
xmlFree ( ( char * ) cur - > encoding ) ;
cur - > encoding = NULL ;
}
}
}
buf = xmlOutputBufferCreateFile ( f , handler ) ;
if ( buf = = NULL ) return ( - 1 ) ;
2001-04-10 20:38:06 +04:00
xmlDocContentDumpOutput ( buf , cur , NULL , 0 ) ;
2001-02-23 20:55:21 +03:00
ret = xmlOutputBufferClose ( buf ) ;
return ( ret ) ;
}
/**
* xmlSaveFileTo :
* @ buf : an output I / O buffer
* @ cur : the document
* @ encoding : the encoding if any assuming the i / O layer handles the trancoding
*
* Dump an XML document to an I / O buffer .
*
* returns : the number of byte written or - 1 in case of failure .
*/
int
2001-11-01 17:31:22 +03:00
xmlSaveFileTo ( xmlOutputBufferPtr buf , xmlDocPtr cur , const char * encoding ) {
2001-02-23 20:55:21 +03:00
int ret ;
if ( buf = = NULL ) return ( 0 ) ;
2001-04-10 20:38:06 +04:00
xmlDocContentDumpOutput ( buf , cur , encoding , 0 ) ;
2001-02-23 20:55:21 +03:00
ret = xmlOutputBufferClose ( buf ) ;
return ( ret ) ;
}
2001-04-28 20:55:50 +04:00
/**
* xmlSaveFormatFileTo :
* @ buf : an output I / O buffer
* @ cur : the document
* @ encoding : the encoding if any assuming the i / O layer handles the trancoding
* @ format : should formatting spaces been added
*
* Dump an XML document to an I / O buffer .
*
* returns : the number of byte written or - 1 in case of failure .
*/
int
2001-11-01 17:31:22 +03:00
xmlSaveFormatFileTo ( xmlOutputBufferPtr buf , xmlDocPtr cur , const char * encoding , int format ) {
2001-04-28 20:55:50 +04:00
int ret ;
if ( buf = = NULL ) return ( 0 ) ;
xmlDocContentDumpOutput ( buf , cur , encoding , format ) ;
ret = xmlOutputBufferClose ( buf ) ;
return ( ret ) ;
}
2001-02-23 20:55:21 +03:00
/**
2001-07-23 23:10:52 +04:00
* xmlSaveFormatFileEnc
* @ filename : the filename or URL to output
* @ cur : the document being saved
* @ encoding : the name of the encoding to use or NULL .
* @ format : should formatting spaces be added .
2001-02-23 20:55:21 +03:00
*/
int
2001-07-23 23:10:52 +04:00
xmlSaveFormatFileEnc ( const char * filename , xmlDocPtr cur ,
const char * encoding , int format ) {
2001-02-23 20:55:21 +03:00
xmlOutputBufferPtr buf ;
xmlCharEncodingHandlerPtr handler = NULL ;
2001-05-22 19:08:55 +04:00
xmlCharEncoding enc ;
2001-02-23 20:55:21 +03:00
int ret ;
if ( encoding ! = NULL ) {
enc = xmlParseCharEncoding ( encoding ) ;
if ( cur - > charset ! = XML_CHAR_ENCODING_UTF8 ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlSaveFileEnc: document not in UTF8 \n " ) ;
return ( - 1 ) ;
}
if ( enc ! = XML_CHAR_ENCODING_UTF8 ) {
handler = xmlFindCharEncodingHandler ( encoding ) ;
2001-05-22 19:08:55 +04:00
if ( handler = = NULL )
2001-02-23 20:55:21 +03:00
return ( - 1 ) ;
}
}
2001-07-23 23:10:52 +04:00
# ifdef HAVE_ZLIB_H
if ( cur - > compression < 0 ) cur - > compression = xmlCompressMode ;
# endif
2001-02-23 20:55:21 +03:00
/*
* save the content to a temp buffer .
*/
2001-07-23 23:10:52 +04:00
buf = xmlOutputBufferCreateFilename ( filename , handler , cur - > compression ) ;
2001-02-23 20:55:21 +03:00
if ( buf = = NULL ) return ( - 1 ) ;
2001-07-23 23:10:52 +04:00
xmlDocContentDumpOutput ( buf , cur , encoding , format ) ;
2001-02-23 20:55:21 +03:00
ret = xmlOutputBufferClose ( buf ) ;
return ( ret ) ;
}
2001-07-23 23:10:52 +04:00
/**
* xmlSaveFileEnc :
* @ filename : the filename ( or URL )
* @ cur : the document
* @ encoding : the name of an encoding ( or NULL )
*
* Dump an XML document , converting it to the given encoding
*
* returns : the number of byte written or - 1 in case of failure .
*/
int
xmlSaveFileEnc ( const char * filename , xmlDocPtr cur , const char * encoding ) {
return ( xmlSaveFormatFileEnc ( filename , cur , encoding , 0 ) ) ;
}
2001-02-23 20:55:21 +03:00
/**
2001-04-26 22:59:03 +04:00
* xmlSaveFormatFile :
2001-02-23 20:55:21 +03:00
* @ filename : the filename ( or URL )
* @ cur : the document
2001-04-26 22:59:03 +04:00
* @ format : should formatting spaces been added
2001-02-23 20:55:21 +03:00
*
* Dump an XML document to a file . Will use compression if
* compiled in and enabled . If @ filename is " - " the stdout file is
2001-04-26 22:59:03 +04:00
* used . If format is set then the document will be indented on output .
*
2001-02-23 20:55:21 +03:00
* returns : the number of byte written or - 1 in case of failure .
*/
int
2001-04-26 22:59:03 +04:00
xmlSaveFormatFile ( const char * filename , xmlDocPtr cur , int format ) {
2001-07-23 23:10:52 +04:00
return ( xmlSaveFormatFileEnc ( filename , cur , NULL , format ) ) ;
2001-02-23 20:55:21 +03:00
}
2001-04-26 22:59:03 +04:00
/**
* xmlSaveFile :
* @ filename : the filename ( or URL )
* @ cur : the document
*
* Dump an XML document to a file . Will use compression if
* compiled in and enabled . If @ filename is " - " the stdout file is
* used .
* returns : the number of byte written or - 1 in case of failure .
*/
int
xmlSaveFile ( const char * filename , xmlDocPtr cur ) {
2001-07-23 23:10:52 +04:00
return ( xmlSaveFormatFileEnc ( filename , cur , NULL , 0 ) ) ;
2001-04-26 22:59:03 +04:00
}