2001-02-23 20:55:21 +03:00
/*
2001-12-17 18:30:10 +03:00
* tree . c : implementation of access function for an XML tree .
2001-02-23 20:55:21 +03:00
*
2002-11-21 17:10:52 +03:00
* References :
* XHTML 1.0 W3C REC : http : //www.w3.org/TR/2002/REC-xhtml1-20020801/
*
2001-02-23 20:55:21 +03:00
* See Copyright for the status of this software .
*
2001-06-24 16:13:24 +04:00
* daniel @ veillard . com
2001-02-23 20:55:21 +03:00
*
*/
2002-03-18 22:37:11 +03:00
# define IN_LIBXML
2001-04-21 20:57:29 +04:00
# include "libxml.h"
2001-02-23 20:55:21 +03:00
# include <string.h> /* 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>
2002-11-21 17:10:52 +03:00
# ifdef LIBXML_HTML_ENABLED
# include <libxml/HTMLtree.h>
# endif
2001-02-23 20:55:21 +03:00
2003-04-22 01:36:41 +04:00
int __xmlRegisterCallbacks = 0 ;
2001-03-24 20:00:36 +03:00
xmlNsPtr xmlNewReconciliedNs ( xmlDocPtr doc , xmlNodePtr tree , xmlNsPtr ns ) ;
2003-10-08 03:16:40 +04:00
/************************************************************************
* *
* Tree memory error handler *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlTreeErrMemory :
* @ extra : extra informations
*
* Handle an out of memory condition
*/
static void
xmlTreeErrMemory ( const char * extra )
{
__xmlSimpleError ( XML_FROM_TREE , XML_ERR_NO_MEMORY , NULL , NULL , extra ) ;
}
/**
* xmlTreeErr :
* @ code : the error number
* @ extra : extra informations
*
* Handle an out of memory condition
*/
static void
xmlTreeErr ( int code , xmlNodePtr node , const char * extra )
{
const char * msg = NULL ;
switch ( code ) {
case XML_TREE_INVALID_HEX :
2004-07-30 16:02:58 +04:00
msg = " invalid hexadecimal character value \n " ;
2003-10-08 03:16:40 +04:00
break ;
case XML_TREE_INVALID_DEC :
2004-07-30 16:02:58 +04:00
msg = " invalid decimal character value \n " ;
2003-10-08 03:16:40 +04:00
break ;
case XML_TREE_UNTERMINATED_ENTITY :
2004-07-30 16:02:58 +04:00
msg = " unterminated entity reference %15s \n " ;
2003-10-08 03:16:40 +04:00
break ;
default :
2004-07-30 16:02:58 +04:00
msg = " unexpected error number \n " ;
2003-10-08 03:16:40 +04:00
}
__xmlSimpleError ( XML_FROM_TREE , code , node , msg , extra ) ;
}
2001-03-24 20:00:36 +03:00
/************************************************************************
* *
* 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 */
2002-01-27 00:42:58 +03:00
/************************************************************************
* *
* Functions to move to entities . c once the *
* API freeze is smoothen and they can be made public . *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include <libxml/hash.h>
2003-09-29 22:02:38 +04:00
# ifdef LIBXML_TREE_ENABLED
2002-01-27 00:42:58 +03:00
/**
* xmlGetEntityFromDtd :
* @ dtd : A pointer to the DTD to search
* @ name : The entity name
*
* Do an entity lookup in the DTD entity hash table and
* return the corresponding entity , if found .
*
* Returns A pointer to the entity structure or NULL if not found .
*/
static xmlEntityPtr
xmlGetEntityFromDtd ( xmlDtdPtr dtd , const xmlChar * name ) {
xmlEntitiesTablePtr table ;
if ( ( dtd ! = NULL ) & & ( dtd - > entities ! = NULL ) ) {
table = ( xmlEntitiesTablePtr ) dtd - > entities ;
return ( ( xmlEntityPtr ) xmlHashLookup ( table , name ) ) ;
/* return(xmlGetEntityFromTable(table, name)); */
}
return ( NULL ) ;
}
/**
* xmlGetParameterEntityFromDtd :
* @ dtd : A pointer to the DTD to search
* @ name : The entity name
*
* Do an entity lookup in the DTD pararmeter entity hash table and
* return the corresponding entity , if found .
*
* Returns A pointer to the entity structure or NULL if not found .
*/
static xmlEntityPtr
xmlGetParameterEntityFromDtd ( xmlDtdPtr dtd , const xmlChar * name ) {
xmlEntitiesTablePtr table ;
if ( ( dtd ! = NULL ) & & ( dtd - > pentities ! = NULL ) ) {
table = ( xmlEntitiesTablePtr ) dtd - > pentities ;
return ( ( xmlEntityPtr ) xmlHashLookup ( table , name ) ) ;
/* return(xmlGetEntityFromTable(table, name)); */
}
return ( NULL ) ;
}
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2002-01-27 00:42:58 +03:00
2003-04-07 14:22:39 +04:00
/************************************************************************
* *
* QName handling helper *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlBuildQName :
* @ ncname : the Name
* @ prefix : the prefix
* @ memory : preallocated memory
* @ len : preallocated memory length
*
* Builds the QName @ prefix : @ ncname in @ memory if there is enough space
* and prefix is not NULL nor empty , otherwise allocate a new string .
* If prefix is NULL or empty it returns ncname .
*
* Returns the new string which must be freed by the caller if different from
* @ memory and @ ncname or NULL in case of error
*/
xmlChar *
xmlBuildQName ( const xmlChar * ncname , const xmlChar * prefix ,
xmlChar * memory , int len ) {
int lenn , lenp ;
xmlChar * ret ;
2003-09-12 03:42:01 +04:00
if ( ncname = = NULL ) return ( NULL ) ;
if ( prefix = = NULL ) return ( ( xmlChar * ) ncname ) ;
2003-04-07 14:22:39 +04:00
lenn = strlen ( ( char * ) ncname ) ;
lenp = strlen ( ( char * ) prefix ) ;
if ( ( memory = = NULL ) | | ( len < lenn + lenp + 2 ) ) {
2003-04-19 04:07:51 +04:00
ret = ( xmlChar * ) xmlMallocAtomic ( lenn + lenp + 2 ) ;
2003-10-08 03:16:40 +04:00
if ( ret = = NULL ) {
xmlTreeErrMemory ( " building QName " ) ;
return ( NULL ) ;
}
2003-04-07 14:22:39 +04:00
} else {
ret = memory ;
}
memcpy ( & ret [ 0 ] , prefix , lenp ) ;
ret [ lenp ] = ' : ' ;
memcpy ( & ret [ lenp + 1 ] , ncname , lenn ) ;
ret [ lenn + lenp + 1 ] = 0 ;
return ( ret ) ;
}
/**
* xmlSplitQName2 :
* @ name : the full QName
* @ prefix : a xmlChar * *
*
* parse an XML qualified name string
*
* [ NS 5 ] QName : : = ( Prefix ' : ' ) ? LocalPart
*
* [ NS 6 ] Prefix : : = NCName
*
* [ NS 7 ] LocalPart : : = NCName
*
* Returns NULL if not a QName , otherwise the local part , and prefix
* is updated to get the Prefix if any .
*/
xmlChar *
xmlSplitQName2 ( const xmlChar * name , xmlChar * * prefix ) {
int len = 0 ;
xmlChar * ret = NULL ;
* prefix = NULL ;
2003-04-24 20:06:47 +04:00
if ( name = = NULL ) return ( NULL ) ;
2003-04-07 14:22:39 +04:00
# ifndef XML_XML_NAMESPACE
/* xml: prefix is not really a namespace */
if ( ( name [ 0 ] = = ' x ' ) & & ( name [ 1 ] = = ' m ' ) & &
( name [ 2 ] = = ' l ' ) & & ( name [ 3 ] = = ' : ' ) )
return ( NULL ) ;
# endif
/* nasty but valid */
if ( name [ 0 ] = = ' : ' )
return ( NULL ) ;
/*
* we are not trying to validate but just to cut , and yes it will
* work even if this is as set of UTF - 8 encoded chars
*/
while ( ( name [ len ] ! = 0 ) & & ( name [ len ] ! = ' : ' ) )
len + + ;
if ( name [ len ] = = 0 )
return ( NULL ) ;
* prefix = xmlStrndup ( name , len ) ;
2003-04-24 20:06:47 +04:00
if ( * prefix = = NULL ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " QName split " ) ;
2003-04-24 20:06:47 +04:00
return ( NULL ) ;
}
2003-04-07 14:22:39 +04:00
ret = xmlStrdup ( & name [ len + 1 ] ) ;
2003-04-24 20:06:47 +04:00
if ( ret = = NULL ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " QName split " ) ;
2003-04-24 20:06:47 +04:00
if ( * prefix ! = NULL ) {
xmlFree ( * prefix ) ;
* prefix = NULL ;
}
return ( NULL ) ;
}
2003-04-07 14:22:39 +04:00
return ( ret ) ;
}
2003-08-04 05:06:15 +04:00
/**
* xmlSplitQName3 :
* @ name : the full QName
* @ len : an int *
*
* parse an XML qualified name string , i
*
* returns NULL if it is not a Qualified Name , otherwise , update len
* with the lenght in byte of the prefix and return a pointer
*/
const xmlChar *
xmlSplitQName3 ( const xmlChar * name , int * len ) {
int l = 0 ;
if ( name = = NULL ) return ( NULL ) ;
if ( len = = NULL ) return ( NULL ) ;
/* nasty but valid */
if ( name [ 0 ] = = ' : ' )
return ( NULL ) ;
/*
* we are not trying to validate but just to cut , and yes it will
* work even if this is as set of UTF - 8 encoded chars
*/
while ( ( name [ l ] ! = 0 ) & & ( name [ l ] ! = ' : ' ) )
l + + ;
if ( name [ l ] = = 0 )
return ( NULL ) ;
* len = l ;
return ( & name [ l + 1 ] ) ;
}
2003-02-14 19:54:11 +03:00
/************************************************************************
* *
* Check Name , NCName and QName strings *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define CUR_SCHAR(s, l) xmlStringCurrentChar(NULL, s, &l)
2004-03-04 18:59:36 +03:00
# if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
2003-02-14 19:54:11 +03:00
/**
* xmlValidateNCName :
* @ value : the value to check
* @ space : allow spaces in front and end of the string
*
* Check that a value conforms to the lexical space of NCName
*
* Returns 0 if this validates , a positive error code number otherwise
* and - 1 in case of internal or API error .
*/
int
xmlValidateNCName ( const xmlChar * value , int space ) {
const xmlChar * cur = value ;
int c , l ;
/*
* First quick algorithm for ASCII range
*/
if ( space )
2003-10-18 20:20:14 +04:00
while ( IS_BLANK_CH ( * cur ) ) cur + + ;
2003-02-14 19:54:11 +03:00
if ( ( ( * cur > = ' a ' ) & & ( * cur < = ' z ' ) ) | | ( ( * cur > = ' A ' ) & & ( * cur < = ' Z ' ) ) | |
( * cur = = ' _ ' ) )
cur + + ;
else
goto try_complex ;
while ( ( ( * cur > = ' a ' ) & & ( * cur < = ' z ' ) ) | |
( ( * cur > = ' A ' ) & & ( * cur < = ' Z ' ) ) | |
( ( * cur > = ' 0 ' ) & & ( * cur < = ' 9 ' ) ) | |
( * cur = = ' _ ' ) | | ( * cur = = ' - ' ) | | ( * cur = = ' . ' ) )
cur + + ;
if ( space )
2003-10-18 20:20:14 +04:00
while ( IS_BLANK_CH ( * cur ) ) cur + + ;
2003-02-14 19:54:11 +03:00
if ( * cur = = 0 )
return ( 0 ) ;
try_complex :
/*
* Second check for chars outside the ASCII range
*/
cur = value ;
c = CUR_SCHAR ( cur , l ) ;
if ( space ) {
while ( IS_BLANK ( c ) ) {
cur + = l ;
c = CUR_SCHAR ( cur , l ) ;
}
}
2003-10-18 08:53:14 +04:00
if ( ( ! IS_LETTER ( c ) ) & & ( c ! = ' _ ' ) )
2003-02-14 19:54:11 +03:00
return ( 1 ) ;
cur + = l ;
c = CUR_SCHAR ( cur , l ) ;
2003-10-18 08:53:14 +04:00
while ( IS_LETTER ( c ) | | IS_DIGIT ( c ) | | ( c = = ' . ' ) | |
( c = = ' - ' ) | | ( c = = ' _ ' ) | | IS_COMBINING ( c ) | |
IS_EXTENDER ( c ) ) {
2003-02-14 19:54:11 +03:00
cur + = l ;
c = CUR_SCHAR ( cur , l ) ;
}
if ( space ) {
while ( IS_BLANK ( c ) ) {
cur + = l ;
c = CUR_SCHAR ( cur , l ) ;
}
}
if ( c ! = 0 )
return ( 1 ) ;
return ( 0 ) ;
}
2004-03-04 18:59:36 +03:00
# endif
2003-02-14 19:54:11 +03:00
2004-03-04 18:59:36 +03:00
# if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
2003-02-14 19:54:11 +03:00
/**
* xmlValidateQName :
* @ value : the value to check
* @ space : allow spaces in front and end of the string
*
* Check that a value conforms to the lexical space of QName
*
* Returns 0 if this validates , a positive error code number otherwise
* and - 1 in case of internal or API error .
*/
int
xmlValidateQName ( const xmlChar * value , int space ) {
const xmlChar * cur = value ;
int c , l ;
/*
* First quick algorithm for ASCII range
*/
if ( space )
2003-10-18 20:20:14 +04:00
while ( IS_BLANK_CH ( * cur ) ) cur + + ;
2003-02-14 19:54:11 +03:00
if ( ( ( * cur > = ' a ' ) & & ( * cur < = ' z ' ) ) | | ( ( * cur > = ' A ' ) & & ( * cur < = ' Z ' ) ) | |
( * cur = = ' _ ' ) )
cur + + ;
else
goto try_complex ;
while ( ( ( * cur > = ' a ' ) & & ( * cur < = ' z ' ) ) | |
( ( * cur > = ' A ' ) & & ( * cur < = ' Z ' ) ) | |
( ( * cur > = ' 0 ' ) & & ( * cur < = ' 9 ' ) ) | |
( * cur = = ' _ ' ) | | ( * cur = = ' - ' ) | | ( * cur = = ' . ' ) )
cur + + ;
if ( * cur = = ' : ' ) {
cur + + ;
if ( ( ( * cur > = ' a ' ) & & ( * cur < = ' z ' ) ) | |
( ( * cur > = ' A ' ) & & ( * cur < = ' Z ' ) ) | |
( * cur = = ' _ ' ) )
cur + + ;
else
goto try_complex ;
while ( ( ( * cur > = ' a ' ) & & ( * cur < = ' z ' ) ) | |
( ( * cur > = ' A ' ) & & ( * cur < = ' Z ' ) ) | |
( ( * cur > = ' 0 ' ) & & ( * cur < = ' 9 ' ) ) | |
( * cur = = ' _ ' ) | | ( * cur = = ' - ' ) | | ( * cur = = ' . ' ) )
cur + + ;
}
if ( space )
2003-10-18 20:20:14 +04:00
while ( IS_BLANK_CH ( * cur ) ) cur + + ;
2003-02-14 19:54:11 +03:00
if ( * cur = = 0 )
return ( 0 ) ;
try_complex :
/*
* Second check for chars outside the ASCII range
*/
cur = value ;
c = CUR_SCHAR ( cur , l ) ;
if ( space ) {
while ( IS_BLANK ( c ) ) {
cur + = l ;
c = CUR_SCHAR ( cur , l ) ;
}
}
2003-10-18 08:53:14 +04:00
if ( ( ! IS_LETTER ( c ) ) & & ( c ! = ' _ ' ) )
2003-02-14 19:54:11 +03:00
return ( 1 ) ;
cur + = l ;
c = CUR_SCHAR ( cur , l ) ;
2003-10-18 08:53:14 +04:00
while ( IS_LETTER ( c ) | | IS_DIGIT ( c ) | | ( c = = ' . ' ) | |
( c = = ' - ' ) | | ( c = = ' _ ' ) | | IS_COMBINING ( c ) | |
IS_EXTENDER ( c ) ) {
2003-02-14 19:54:11 +03:00
cur + = l ;
c = CUR_SCHAR ( cur , l ) ;
}
if ( c = = ' : ' ) {
cur + = l ;
c = CUR_SCHAR ( cur , l ) ;
2003-10-18 08:53:14 +04:00
if ( ( ! IS_LETTER ( c ) ) & & ( c ! = ' _ ' ) )
2003-02-14 19:54:11 +03:00
return ( 1 ) ;
cur + = l ;
c = CUR_SCHAR ( cur , l ) ;
2003-10-18 08:53:14 +04:00
while ( IS_LETTER ( c ) | | IS_DIGIT ( c ) | | ( c = = ' . ' ) | |
( c = = ' - ' ) | | ( c = = ' _ ' ) | | IS_COMBINING ( c ) | |
IS_EXTENDER ( c ) ) {
2003-02-14 19:54:11 +03:00
cur + = l ;
c = CUR_SCHAR ( cur , l ) ;
}
}
if ( space ) {
while ( IS_BLANK ( c ) ) {
cur + = l ;
c = CUR_SCHAR ( cur , l ) ;
}
}
if ( c ! = 0 )
return ( 1 ) ;
return ( 0 ) ;
}
/**
* xmlValidateName :
* @ value : the value to check
* @ space : allow spaces in front and end of the string
*
* Check that a value conforms to the lexical space of Name
*
* Returns 0 if this validates , a positive error code number otherwise
* and - 1 in case of internal or API error .
*/
int
xmlValidateName ( const xmlChar * value , int space ) {
const xmlChar * cur = value ;
int c , l ;
/*
* First quick algorithm for ASCII range
*/
if ( space )
2003-10-18 20:20:14 +04:00
while ( IS_BLANK_CH ( * cur ) ) cur + + ;
2003-02-14 19:54:11 +03:00
if ( ( ( * cur > = ' a ' ) & & ( * cur < = ' z ' ) ) | | ( ( * cur > = ' A ' ) & & ( * cur < = ' Z ' ) ) | |
( * cur = = ' _ ' ) | | ( * cur = = ' : ' ) )
cur + + ;
else
goto try_complex ;
while ( ( ( * cur > = ' a ' ) & & ( * cur < = ' z ' ) ) | |
( ( * cur > = ' A ' ) & & ( * cur < = ' Z ' ) ) | |
( ( * cur > = ' 0 ' ) & & ( * cur < = ' 9 ' ) ) | |
( * cur = = ' _ ' ) | | ( * cur = = ' - ' ) | | ( * cur = = ' . ' ) | | ( * cur = = ' : ' ) )
cur + + ;
if ( space )
2003-10-18 20:20:14 +04:00
while ( IS_BLANK_CH ( * cur ) ) cur + + ;
2003-02-14 19:54:11 +03:00
if ( * cur = = 0 )
return ( 0 ) ;
try_complex :
/*
* Second check for chars outside the ASCII range
*/
cur = value ;
c = CUR_SCHAR ( cur , l ) ;
if ( space ) {
while ( IS_BLANK ( c ) ) {
cur + = l ;
c = CUR_SCHAR ( cur , l ) ;
}
}
2003-10-18 08:53:14 +04:00
if ( ( ! IS_LETTER ( c ) ) & & ( c ! = ' _ ' ) & & ( c ! = ' : ' ) )
2003-02-14 19:54:11 +03:00
return ( 1 ) ;
cur + = l ;
c = CUR_SCHAR ( cur , l ) ;
2003-10-18 08:53:14 +04:00
while ( IS_LETTER ( c ) | | IS_DIGIT ( c ) | | ( c = = ' . ' ) | | ( c = = ' : ' ) | |
( c = = ' - ' ) | | ( c = = ' _ ' ) | | IS_COMBINING ( c ) | | IS_EXTENDER ( c ) ) {
2003-02-19 00:12:46 +03:00
cur + = l ;
c = CUR_SCHAR ( cur , l ) ;
}
if ( space ) {
while ( IS_BLANK ( c ) ) {
cur + = l ;
c = CUR_SCHAR ( cur , l ) ;
}
}
if ( c ! = 0 )
return ( 1 ) ;
return ( 0 ) ;
}
/**
* xmlValidateNMToken :
* @ value : the value to check
* @ space : allow spaces in front and end of the string
*
* Check that a value conforms to the lexical space of NMToken
*
* Returns 0 if this validates , a positive error code number otherwise
* and - 1 in case of internal or API error .
*/
int
xmlValidateNMToken ( const xmlChar * value , int space ) {
const xmlChar * cur = value ;
int c , l ;
/*
* First quick algorithm for ASCII range
*/
if ( space )
2003-10-18 20:20:14 +04:00
while ( IS_BLANK_CH ( * cur ) ) cur + + ;
2003-02-19 00:12:46 +03:00
if ( ( ( * cur > = ' a ' ) & & ( * cur < = ' z ' ) ) | |
( ( * cur > = ' A ' ) & & ( * cur < = ' Z ' ) ) | |
( ( * cur > = ' 0 ' ) & & ( * cur < = ' 9 ' ) ) | |
( * cur = = ' _ ' ) | | ( * cur = = ' - ' ) | | ( * cur = = ' . ' ) | | ( * cur = = ' : ' ) )
cur + + ;
else
goto try_complex ;
while ( ( ( * cur > = ' a ' ) & & ( * cur < = ' z ' ) ) | |
( ( * cur > = ' A ' ) & & ( * cur < = ' Z ' ) ) | |
( ( * cur > = ' 0 ' ) & & ( * cur < = ' 9 ' ) ) | |
( * cur = = ' _ ' ) | | ( * cur = = ' - ' ) | | ( * cur = = ' . ' ) | | ( * cur = = ' : ' ) )
cur + + ;
if ( space )
2003-10-18 20:20:14 +04:00
while ( IS_BLANK_CH ( * cur ) ) cur + + ;
2003-02-19 00:12:46 +03:00
if ( * cur = = 0 )
return ( 0 ) ;
try_complex :
/*
* Second check for chars outside the ASCII range
*/
cur = value ;
c = CUR_SCHAR ( cur , l ) ;
if ( space ) {
while ( IS_BLANK ( c ) ) {
cur + = l ;
c = CUR_SCHAR ( cur , l ) ;
}
}
2003-10-18 08:53:14 +04:00
if ( ! ( IS_LETTER ( c ) | | IS_DIGIT ( c ) | | ( c = = ' . ' ) | | ( c = = ' : ' ) | |
( c = = ' - ' ) | | ( c = = ' _ ' ) | | IS_COMBINING ( c ) | | IS_EXTENDER ( c ) ) )
2003-02-19 00:12:46 +03:00
return ( 1 ) ;
cur + = l ;
c = CUR_SCHAR ( cur , l ) ;
2003-10-18 08:53:14 +04:00
while ( IS_LETTER ( c ) | | IS_DIGIT ( c ) | | ( c = = ' . ' ) | | ( c = = ' : ' ) | |
( c = = ' - ' ) | | ( c = = ' _ ' ) | | IS_COMBINING ( c ) | | IS_EXTENDER ( c ) ) {
2003-02-14 19:54:11 +03:00
cur + = l ;
c = CUR_SCHAR ( cur , l ) ;
}
if ( space ) {
while ( IS_BLANK ( c ) ) {
cur + = l ;
c = CUR_SCHAR ( cur , l ) ;
}
}
if ( c ! = 0 )
return ( 1 ) ;
return ( 0 ) ;
}
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2003-02-14 19:54:11 +03:00
2001-02-23 20:55:21 +03:00
/************************************************************************
* *
* 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 .
2001-12-17 18:30:10 +03:00
* Returns a new namespace pointer or NULL
2001-02-23 20:55:21 +03:00
*/
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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " building namespace " ) ;
2001-02-23 20:55:21 +03:00
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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " building DTD " ) ;
2001-02-23 20:55:21 +03:00
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 ;
2003-04-22 01:36:41 +04:00
if ( ( __xmlRegisterCallbacks ) & & ( xmlRegisterNodeDefaultValue ) )
2003-01-01 23:59:38 +03:00
xmlRegisterNodeDefaultValue ( ( xmlNodePtr ) cur ) ;
2001-02-23 20:55:21 +03:00
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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " building internal subset " ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlDtd ) ) ;
cur - > type = XML_DTD_NODE ;
2004-07-31 20:24:01 +04:00
if ( name ! = NULL ) {
cur - > name = xmlStrdup ( name ) ;
if ( cur - > name = = NULL ) {
xmlTreeErrMemory ( " building internal subset " ) ;
xmlFree ( cur ) ;
return ( NULL ) ;
}
}
if ( ExternalID ! = NULL ) {
2001-02-23 20:55:21 +03:00
cur - > ExternalID = xmlStrdup ( ExternalID ) ;
2004-07-31 20:24:01 +04:00
if ( cur - > ExternalID = = NULL ) {
xmlTreeErrMemory ( " building internal subset " ) ;
if ( cur - > name ! = NULL )
xmlFree ( ( char * ) cur - > name ) ;
xmlFree ( cur ) ;
return ( NULL ) ;
}
}
if ( SystemID ! = NULL ) {
2001-02-23 20:55:21 +03:00
cur - > SystemID = xmlStrdup ( SystemID ) ;
2004-07-31 20:24:01 +04:00
if ( cur - > SystemID = = NULL ) {
xmlTreeErrMemory ( " building internal subset " ) ;
if ( cur - > name ! = NULL )
xmlFree ( ( char * ) cur - > name ) ;
if ( cur - > ExternalID ! = NULL )
xmlFree ( ( char * ) cur - > ExternalID ) ;
xmlFree ( cur ) ;
return ( NULL ) ;
}
}
2001-02-23 20:55:21 +03:00
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
}
}
}
2003-01-06 01:37:17 +03:00
2003-04-22 01:36:41 +04:00
if ( ( __xmlRegisterCallbacks ) & & ( xmlRegisterNodeDefaultValue ) )
2003-01-06 01:37:17 +03:00
xmlRegisterNodeDefaultValue ( ( xmlNodePtr ) cur ) ;
2001-02-23 20:55:21 +03:00
return ( cur ) ;
}
2003-09-25 01:23:56 +04:00
/**
* DICT_FREE :
* @ str : a string
*
* Free a string if it is not owned by the " dict " dictionnary in the
* current scope
*/
# define DICT_FREE(str) \
if ( ( str ) & & ( ( ! dict ) | | \
( xmlDictOwns ( dict , ( const xmlChar * ) ( str ) ) = = 0 ) ) ) \
xmlFree ( ( char * ) ( str ) ) ;
2001-02-23 20:55:21 +03:00
/**
* xmlFreeDtd :
* @ cur : the DTD structure to free up
*
* Free a DTD structure .
*/
void
xmlFreeDtd ( xmlDtdPtr cur ) {
2003-09-25 01:23:56 +04:00
xmlDictPtr dict = NULL ;
2001-02-23 20:55:21 +03:00
if ( cur = = NULL ) {
return ;
}
2003-09-25 01:23:56 +04:00
if ( cur - > doc ! = NULL ) dict = cur - > doc - > dict ;
2003-01-01 23:59:38 +03:00
2003-04-22 01:36:41 +04:00
if ( ( __xmlRegisterCallbacks ) & & ( xmlDeregisterNodeDefaultValue ) )
2003-01-01 23:59:38 +03:00
xmlDeregisterNodeDefaultValue ( ( xmlNodePtr ) cur ) ;
2001-02-23 20:55:21 +03:00
if ( cur - > children ! = NULL ) {
xmlNodePtr next , c = cur - > children ;
/*
2004-08-03 20:42:37 +04:00
* Cleanup all nodes which are not part of the specific lists
* of notations , elements , attributes and entities .
2001-02-23 20:55:21 +03:00
*/
while ( c ! = NULL ) {
next = c - > next ;
2004-08-03 20:42:37 +04:00
if ( ( c - > type ! = XML_NOTATION_NODE ) & &
( c - > type ! = XML_ELEMENT_DECL ) & &
( c - > type ! = XML_ATTRIBUTE_DECL ) & &
( c - > type ! = XML_ENTITY_DECL ) ) {
2001-02-23 20:55:21 +03:00
xmlUnlinkNode ( c ) ;
xmlFreeNode ( c ) ;
}
c = next ;
}
}
2003-09-25 01:23:56 +04:00
DICT_FREE ( cur - > name )
DICT_FREE ( cur - > SystemID )
DICT_FREE ( cur - > ExternalID )
2001-02-23 20:55:21 +03:00
/* 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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " building doc " ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlDoc ) ) ;
cur - > type = XML_DOCUMENT_NODE ;
cur - > version = xmlStrdup ( version ) ;
2004-07-31 20:24:01 +04:00
if ( cur - > version = = NULL ) {
xmlTreeErrMemory ( " building doc " ) ;
xmlFree ( cur ) ;
return ( NULL ) ;
}
2001-02-23 20:55:21 +03:00
cur - > standalone = - 1 ;
cur - > compression = - 1 ; /* not initialized */
cur - > doc = cur ;
2003-07-29 20:47:24 +04:00
/*
* The in memory encoding is always UTF8
* This field will never change and would
* be obsolete if not for binary compatibility .
*/
2001-04-11 11:50:02 +04:00
cur - > charset = XML_CHAR_ENCODING_UTF8 ;
2003-01-01 23:59:38 +03:00
2003-04-22 01:36:41 +04:00
if ( ( __xmlRegisterCallbacks ) & & ( xmlRegisterNodeDefaultValue ) )
2003-01-01 23:59:38 +03:00
xmlRegisterNodeDefaultValue ( ( xmlNodePtr ) cur ) ;
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 ;
2003-09-25 01:23:56 +04:00
xmlDictPtr dict = NULL ;
2001-06-19 15:07:54 +04:00
2001-02-23 20:55:21 +03:00
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlFreeDoc : document == NULL \n " ) ;
# endif
return ;
}
2003-09-25 01:23:56 +04:00
if ( cur ! = NULL ) dict = cur - > dict ;
2003-01-01 23:59:38 +03:00
2003-04-22 01:36:41 +04:00
if ( ( __xmlRegisterCallbacks ) & & ( xmlDeregisterNodeDefaultValue ) )
2003-01-01 23:59:38 +03:00
xmlDeregisterNodeDefaultValue ( ( xmlNodePtr ) cur ) ;
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 ;
2002-03-18 21:36:20 +03:00
if ( intSubset = = extSubset )
extSubset = NULL ;
2001-06-19 15:07:54 +04:00
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 - > oldNs ! = NULL ) xmlFreeNsList ( cur - > oldNs ) ;
2003-09-25 01:23:56 +04:00
DICT_FREE ( cur - > version )
DICT_FREE ( cur - > name )
DICT_FREE ( cur - > encoding )
DICT_FREE ( cur - > URL )
2001-02-23 20:55:21 +03:00
xmlFree ( cur ) ;
2003-09-25 01:23:56 +04:00
if ( dict ) xmlDictFree ( dict ) ;
2001-02-23 20:55:21 +03:00
}
/**
* 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 ;
2003-09-10 14:51:05 +04:00
const xmlChar * cur = value , * end = cur + len ;
2001-02-23 20:55:21 +03:00
const xmlChar * q ;
xmlEntityPtr ent ;
if ( value = = NULL ) return ( NULL ) ;
q = cur ;
2003-09-10 14:51:05 +04:00
while ( ( cur < end ) & & ( * cur ! = 0 ) ) {
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 ;
2003-09-10 14:51:05 +04:00
if ( ( cur + 2 < end ) & & ( cur [ 1 ] = = ' # ' ) & & ( cur [ 2 ] = = ' x ' ) ) {
cur + = 3 ;
if ( cur < end )
tmp = * cur ;
else
tmp = 0 ;
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 {
2003-10-08 03:16:40 +04:00
xmlTreeErr ( XML_TREE_INVALID_HEX , ( xmlNodePtr ) doc ,
NULL ) ;
2003-09-10 14:51:05 +04:00
charval = 0 ;
break ;
}
cur + + ;
if ( cur < end )
tmp = * cur ;
else
tmp = 0 ;
}
if ( tmp = = ' ; ' )
cur + + ;
q = cur ;
} else if ( ( cur + 1 < end ) & & ( cur [ 1 ] = = ' # ' ) ) {
cur + = 2 ;
if ( cur < end )
tmp = * cur ;
else
tmp = 0 ;
while ( tmp ! = ' ; ' ) { /* Non input consuming loops */
if ( ( tmp > = ' 0 ' ) & & ( tmp < = ' 9 ' ) )
charval = charval * 10 + ( tmp - ' 0 ' ) ;
else {
2003-10-08 03:16:40 +04:00
xmlTreeErr ( XML_TREE_INVALID_DEC , ( xmlNodePtr ) doc ,
NULL ) ;
2003-09-10 14:51:05 +04:00
charval = 0 ;
break ;
}
cur + + ;
if ( cur < end )
tmp = * cur ;
else
tmp = 0 ;
}
if ( tmp = = ' ; ' )
cur + + ;
q = cur ;
} else {
2001-02-23 20:55:21 +03:00
/*
2003-09-10 14:51:05 +04:00
* Read the entity string
2001-02-23 20:55:21 +03:00
*/
2003-09-10 14:51:05 +04:00
cur + + ;
q = cur ;
while ( ( cur < end ) & & ( * cur ! = 0 ) & & ( * cur ! = ' ; ' ) ) cur + + ;
if ( ( cur > = end ) | | ( * cur = = 0 ) ) {
2003-10-08 03:16:40 +04:00
xmlTreeErr ( XML_TREE_UNTERMINATED_ENTITY , ( xmlNodePtr ) doc ,
( const char * ) q ) ;
2003-09-10 14:51:05 +04:00
return ( ret ) ;
}
if ( cur ! = q ) {
2001-02-23 20:55:21 +03:00
/*
2003-09-10 14:51:05 +04:00
* Predefined entities don ' t generate nodes
2001-02-23 20:55:21 +03:00
*/
2003-09-10 14:51:05 +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 if ( last - > type ! = XML_TEXT_NODE ) {
node = xmlNewDocText ( doc , ent - > content ) ;
last = xmlAddNextSibling ( last , 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 ) ;
}
2002-04-18 20:39:10 +04:00
else if ( ( ent ! = NULL ) & & ( ent - > children = = NULL ) ) {
2003-09-10 14:51:05 +04:00
xmlNodePtr temp ;
ent - > children = xmlStringGetNodeList ( doc ,
( const xmlChar * ) node - > content ) ;
ent - > owner = 1 ;
temp = ent - > children ;
while ( temp ) {
temp - > parent = ( xmlNodePtr ) ent ;
temp = temp - > next ;
}
2002-04-18 20:39:10 +04:00
}
2003-09-10 14:51:05 +04:00
if ( last = = NULL ) {
last = ret = node ;
} else {
last = xmlAddNextSibling ( last , node ) ;
}
}
xmlFree ( val ) ;
}
cur + + ;
q = cur ;
}
if ( charval ! = 0 ) {
xmlChar buf [ 10 ] ;
int l ;
l = xmlCopyCharMultiByte ( buf , charval ) ;
buf [ l ] = 0 ;
node = xmlNewDocText ( doc , buf ) ;
if ( node ! = NULL ) {
if ( last = = NULL ) {
2001-02-23 20:55:21 +03:00
last = ret = node ;
2003-09-10 14:51:05 +04:00
} else {
last = xmlAddNextSibling ( last , node ) ;
2001-02-23 20:55:21 +03:00
}
}
2003-09-10 14:51:05 +04:00
charval = 0 ;
2001-02-23 20:55:21 +03:00
}
2003-09-10 14:51:05 +04:00
} else
2001-02-23 20:55:21 +03:00
cur + + ;
}
2003-09-10 14:51:05 +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 ) ;
2003-09-10 14:51:05 +04:00
if ( last = = NULL ) {
2001-02-23 20:55:21 +03:00
last = ret = node ;
2003-09-10 14:51:05 +04:00
} else {
last = xmlAddNextSibling ( last , node ) ;
2001-02-23 20:55:21 +03:00
}
}
}
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 {
2003-10-08 03:16:40 +04:00
xmlTreeErr ( XML_TREE_INVALID_HEX , ( xmlNodePtr ) doc ,
NULL ) ;
2001-04-11 15:28:06 +04:00
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 {
2003-10-08 03:16:40 +04:00
xmlTreeErr ( XML_TREE_INVALID_DEC , ( xmlNodePtr ) doc ,
NULL ) ;
2001-04-11 15:28:06 +04:00
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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErr ( XML_TREE_UNTERMINATED_ENTITY ,
( xmlNodePtr ) doc , ( const char * ) q ) ;
2001-04-11 15:28:06 +04:00
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 ;
2002-01-07 02:05:13 +03:00
} else if ( last - > type ! = XML_TEXT_NODE ) {
node = xmlNewDocText ( doc , ent - > content ) ;
last = xmlAddNextSibling ( last , node ) ;
2001-04-11 15:28:06 +04:00
} 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 ) ;
}
2002-04-18 20:39:10 +04:00
else if ( ( ent ! = NULL ) & & ( ent - > children = = NULL ) ) {
xmlNodePtr temp ;
ent - > children = xmlStringGetNodeList ( doc ,
( const xmlChar * ) node - > content ) ;
2002-12-30 03:01:08 +03:00
ent - > owner = 1 ;
2002-04-18 20:39:10 +04:00
temp = ent - > children ;
while ( temp ) {
temp - > parent = ( xmlNodePtr ) ent ;
temp = temp - > next ;
}
}
2001-04-11 15:28:06 +04:00
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
*
2002-12-11 17:23:49 +03:00
* Build the string equivalent to the text contained in the Node list
2001-02-23 20:55:21 +03:00
* made of TEXTs and ENTITY_REFs
2002-12-11 17:23:49 +03:00
*
2002-09-26 02:25:35 +04:00
* Returns a pointer to the string copy , the caller must free it with xmlFree ( ) .
2001-02-23 20:55:21 +03:00
*/
xmlChar *
2002-04-20 10:41:40 +04:00
xmlNodeListGetString ( xmlDocPtr doc , xmlNodePtr list , int inLine )
{
2001-02-23 20:55:21 +03:00
xmlNodePtr node = list ;
xmlChar * ret = NULL ;
xmlEntityPtr ent ;
2002-04-20 10:41:40 +04:00
if ( list = = NULL )
return ( NULL ) ;
2001-02-23 20:55:21 +03:00
while ( node ! = NULL ) {
if ( ( node - > type = = XML_TEXT_NODE ) | |
2002-04-20 10:41:40 +04:00
( node - > type = = XML_CDATA_SECTION_NODE ) ) {
if ( inLine ) {
ret = xmlStrcat ( ret , node - > content ) ;
} else {
xmlChar * buffer ;
2001-02-23 20:55:21 +03:00
2002-04-20 10:41:40 +04:00
buffer = xmlEncodeEntitiesReentrant ( doc , node - > content ) ;
if ( buffer ! = NULL ) {
ret = xmlStrcat ( ret , buffer ) ;
xmlFree ( buffer ) ;
}
2001-02-23 20:55:21 +03:00
}
2002-04-20 10:41:40 +04:00
} else if ( node - > type = = XML_ENTITY_REF_NODE ) {
if ( inLine ) {
ent = xmlGetDocEntity ( doc , node - > name ) ;
if ( ent ! = NULL ) {
xmlChar * buffer ;
/* an entity content can be any "well balanced chunk",
* i . e . the result of the content [ 43 ] production :
* http : //www.w3.org/TR/REC-xml#NT-content.
* So it can contain text , CDATA section or nested
* entity reference nodes ( among others ) .
* - > we recursive call xmlNodeListGetString ( )
* which handles these types */
buffer = xmlNodeListGetString ( doc , ent - > children , 1 ) ;
if ( buffer ! = NULL ) {
ret = xmlStrcat ( ret , buffer ) ;
xmlFree ( buffer ) ;
}
} else {
ret = xmlStrcat ( ret , node - > content ) ;
}
2001-02-23 20:55:21 +03:00
} else {
2002-04-20 10:41:40 +04:00
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 ) ;
}
}
2001-02-23 20:55:21 +03:00
#if 0
2002-04-20 10:41:40 +04:00
else {
xmlGenericError ( xmlGenericErrorContext ,
" xmlGetNodeListString : invalid node type %d \n " ,
node - > type ) ;
}
2001-02-23 20:55:21 +03:00
# endif
2002-04-20 10:41:40 +04:00
node = node - > next ;
2001-02-23 20:55:21 +03:00
}
2002-04-20 10:41:40 +04:00
return ( ret ) ;
2001-02-23 20:55:21 +03:00
}
2003-09-29 22:02:38 +04:00
# ifdef LIBXML_TREE_ENABLED
2001-02-23 20:55:21 +03:00
/**
* xmlNodeListGetRawString :
* @ doc : the document
* @ list : a Node list
* @ inLine : should we replace entity contents or show their external form
*
2002-12-11 17:23:49 +03:00
* Builds the string equivalent to the text contained in the Node list
2001-02-23 20:55:21 +03:00
* made of TEXTs and ENTITY_REFs , contrary to xmlNodeListGetString ( )
* this function doesn ' t do any character encoding handling .
*
2002-09-26 02:25:35 +04:00
* Returns a pointer to the string copy , the caller must free it with xmlFree ( ) .
2001-02-23 20:55:21 +03:00
*/
xmlChar *
2002-04-20 10:41:40 +04:00
xmlNodeListGetRawString ( xmlDocPtr doc , xmlNodePtr list , int inLine )
{
2001-02-23 20:55:21 +03:00
xmlNodePtr node = list ;
xmlChar * ret = NULL ;
xmlEntityPtr ent ;
2002-04-20 10:41:40 +04:00
if ( list = = NULL )
return ( NULL ) ;
2001-02-23 20:55:21 +03:00
while ( node ! = NULL ) {
2001-07-12 05:20:08 +04:00
if ( ( node - > type = = XML_TEXT_NODE ) | |
2002-04-20 10:41:40 +04:00
( node - > type = = XML_CDATA_SECTION_NODE ) ) {
if ( inLine ) {
ret = xmlStrcat ( ret , node - > content ) ;
} else {
xmlChar * buffer ;
2001-02-23 20:55:21 +03:00
2002-04-20 10:41:40 +04:00
buffer = xmlEncodeSpecialChars ( doc , node - > content ) ;
if ( buffer ! = NULL ) {
ret = xmlStrcat ( ret , buffer ) ;
xmlFree ( buffer ) ;
}
2001-02-23 20:55:21 +03:00
}
2002-04-20 10:41:40 +04:00
} else if ( node - > type = = XML_ENTITY_REF_NODE ) {
if ( inLine ) {
ent = xmlGetDocEntity ( doc , node - > name ) ;
if ( ent ! = NULL ) {
xmlChar * buffer ;
/* an entity content can be any "well balanced chunk",
* i . e . the result of the content [ 43 ] production :
* http : //www.w3.org/TR/REC-xml#NT-content.
* So it can contain text , CDATA section or nested
* entity reference nodes ( among others ) .
* - > we recursive call xmlNodeListGetRawString ( )
* which handles these types */
buffer =
xmlNodeListGetRawString ( doc , ent - > children , 1 ) ;
if ( buffer ! = NULL ) {
ret = xmlStrcat ( ret , buffer ) ;
xmlFree ( buffer ) ;
}
} else {
ret = xmlStrcat ( ret , node - > content ) ;
}
2001-02-23 20:55:21 +03:00
} else {
2002-04-20 10:41:40 +04:00
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 ) ;
}
}
2001-02-23 20:55:21 +03:00
#if 0
2002-04-20 10:41:40 +04:00
else {
xmlGenericError ( xmlGenericErrorContext ,
" xmlGetNodeListString : invalid node type %d \n " ,
node - > type ) ;
}
2001-02-23 20:55:21 +03:00
# endif
2002-04-20 10:41:40 +04:00
node = node - > next ;
2001-02-23 20:55:21 +03:00
}
2002-04-20 10:41:40 +04:00
return ( ret ) ;
2001-02-23 20:55:21 +03:00
}
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2001-02-23 20:55:21 +03:00
2004-03-04 18:59:36 +03:00
# if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED)
2001-02-23 20:55:21 +03:00
/**
* 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 ) ;
}
2003-02-24 20:17:58 +03:00
if ( ( node ! = NULL ) & & ( node - > type ! = XML_ELEMENT_NODE ) )
return ( NULL ) ;
2001-02-23 20:55:21 +03:00
/*
* Allocate a new property and fill the fields .
*/
cur = ( xmlAttrPtr ) xmlMalloc ( sizeof ( xmlAttr ) ) ;
if ( cur = = NULL ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " building attribute " ) ;
2001-02-23 20:55:21 +03:00
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 ;
}
}
2003-01-01 23:59:38 +03:00
2003-04-22 01:36:41 +04:00
if ( ( __xmlRegisterCallbacks ) & & ( xmlRegisterNodeDefaultValue ) )
2003-01-01 23:59:38 +03:00
xmlRegisterNodeDefaultValue ( ( xmlNodePtr ) cur ) ;
2001-02-23 20:55:21 +03:00
return ( cur ) ;
}
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2001-02-23 20:55:21 +03:00
/**
* 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 ,
2001-12-17 18:30:10 +03:00
" xmlNewNsProp : name == NULL \n " ) ;
2001-02-23 20:55:21 +03:00
# endif
return ( NULL ) ;
}
/*
* Allocate a new property and fill the fields .
*/
cur = ( xmlAttrPtr ) xmlMalloc ( sizeof ( xmlAttr ) ) ;
if ( cur = = NULL ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " building attribute " ) ;
2001-02-23 20:55:21 +03:00
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 ;
}
}
2003-01-01 23:59:38 +03:00
2003-04-22 01:36:41 +04:00
if ( ( __xmlRegisterCallbacks ) & & ( xmlRegisterNodeDefaultValue ) )
2003-01-01 23:59:38 +03:00
xmlRegisterNodeDefaultValue ( ( xmlNodePtr ) cur ) ;
2001-02-23 20:55:21 +03:00
return ( cur ) ;
}
2002-05-29 12:21:33 +04:00
/**
* xmlNewNsPropEatName :
* @ 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
xmlNewNsPropEatName ( xmlNodePtr node , xmlNsPtr ns , xmlChar * name ,
const xmlChar * value ) {
xmlAttrPtr cur ;
xmlDocPtr doc = NULL ;
if ( name = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNewNsPropEatName : name == NULL \n " ) ;
# endif
return ( NULL ) ;
}
/*
* Allocate a new property and fill the fields .
*/
cur = ( xmlAttrPtr ) xmlMalloc ( sizeof ( xmlAttr ) ) ;
if ( cur = = NULL ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " building attribute " ) ;
2002-05-29 12:21:33 +04:00
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 - > ns = ns ;
cur - > name = 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 ;
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 ;
}
}
2003-01-06 01:37:17 +03:00
2003-04-22 01:36:41 +04:00
if ( ( __xmlRegisterCallbacks ) & & ( xmlRegisterNodeDefaultValue ) )
2003-01-06 01:37:17 +03:00
xmlRegisterNodeDefaultValue ( ( xmlNodePtr ) cur ) ;
2002-05-29 12:21:33 +04:00
return ( cur ) ;
}
2001-02-23 20:55:21 +03:00
/**
* 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 ,
2001-12-17 18:30:10 +03:00
" xmlNewDocProp : name == NULL \n " ) ;
2001-02-23 20:55:21 +03:00
# endif
return ( NULL ) ;
}
/*
* Allocate a new property and fill the fields .
*/
cur = ( xmlAttrPtr ) xmlMalloc ( sizeof ( xmlAttr ) ) ;
if ( cur = = NULL ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " building attribute " ) ;
2001-02-23 20:55:21 +03:00
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 ;
}
}
2003-01-01 23:59:38 +03:00
2003-04-22 01:36:41 +04:00
if ( ( __xmlRegisterCallbacks ) & & ( xmlRegisterNodeDefaultValue ) )
2003-01-01 23:59:38 +03:00
xmlRegisterNodeDefaultValue ( ( xmlNodePtr ) cur ) ;
2001-02-23 20:55:21 +03:00
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 ;
2003-09-25 01:23:56 +04:00
if ( cur = = NULL ) return ;
2001-02-23 20:55:21 +03:00
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 ) {
2003-09-25 01:23:56 +04:00
xmlDictPtr dict = NULL ;
if ( cur = = NULL ) return ;
if ( cur - > doc ! = NULL ) dict = cur - > doc - > dict ;
2003-01-01 23:59:38 +03:00
2003-04-22 01:36:41 +04:00
if ( ( __xmlRegisterCallbacks ) & & ( xmlDeregisterNodeDefaultValue ) )
2003-01-01 23:59:38 +03:00
xmlDeregisterNodeDefaultValue ( ( xmlNodePtr ) cur ) ;
2001-02-23 20:55:21 +03:00
/* 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 - > children ! = NULL ) xmlFreeNodeList ( cur - > children ) ;
2003-09-25 01:23:56 +04:00
DICT_FREE ( cur - > name )
2001-02-23 20:55:21 +03:00
xmlFree ( cur ) ;
}
2003-09-29 22:02:38 +04:00
# ifdef LIBXML_TREE_ENABLED
2001-02-23 20:55:21 +03:00
/**
* 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 ) ;
}
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2001-02-23 20:55:21 +03:00
/**
* 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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " building PI " ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlNode ) ) ;
cur - > type = XML_PI_NODE ;
cur - > name = xmlStrdup ( name ) ;
if ( content ! = NULL ) {
cur - > content = xmlStrdup ( content ) ;
}
2003-01-01 23:59:38 +03:00
2003-04-22 01:36:41 +04:00
if ( ( __xmlRegisterCallbacks ) & & ( xmlRegisterNodeDefaultValue ) )
2003-01-01 23:59:38 +03:00
xmlRegisterNodeDefaultValue ( ( xmlNodePtr ) cur ) ;
2001-02-23 20:55:21 +03:00
return ( cur ) ;
}
/**
* xmlNewNode :
* @ ns : namespace if any
* @ name : the node name
*
2001-12-17 18:30:10 +03:00
* Creation of a new node element . @ ns is optional ( NULL ) .
2001-02-23 20:55:21 +03:00
*
2003-11-14 10:13:16 +03:00
* Returns a pointer to the new node object . Uses xmlStrdup ( ) to make
* copy of @ name .
2001-02-23 20:55:21 +03:00
*/
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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " building node " ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlNode ) ) ;
cur - > type = XML_ELEMENT_NODE ;
cur - > name = xmlStrdup ( name ) ;
cur - > ns = ns ;
2003-01-01 23:59:38 +03:00
2003-04-22 01:36:41 +04:00
if ( ( __xmlRegisterCallbacks ) & & ( xmlRegisterNodeDefaultValue ) )
2003-01-01 23:59:38 +03:00
xmlRegisterNodeDefaultValue ( cur ) ;
2001-02-23 20:55:21 +03:00
return ( cur ) ;
}
2002-05-29 12:21:33 +04:00
/**
* xmlNewNodeEatName :
* @ ns : namespace if any
* @ name : the node name
*
* Creation of a new node element . @ ns is optional ( NULL ) .
*
2003-11-14 10:13:16 +03:00
* Returns a pointer to the new node object , with pointer @ name as
* new node ' s name . Use xmlNewNode ( ) if a copy of @ name string is
* is needed as new node ' s name .
2002-05-29 12:21:33 +04:00
*/
xmlNodePtr
xmlNewNodeEatName ( xmlNsPtr ns , 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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " building node " ) ;
2002-05-29 12:21:33 +04:00
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlNode ) ) ;
cur - > type = XML_ELEMENT_NODE ;
cur - > name = name ;
cur - > ns = ns ;
2003-01-06 01:37:17 +03:00
2003-04-22 01:36:41 +04:00
if ( ( __xmlRegisterCallbacks ) & & ( xmlRegisterNodeDefaultValue ) )
2003-01-06 01:37:17 +03:00
xmlRegisterNodeDefaultValue ( ( xmlNodePtr ) cur ) ;
2002-05-29 12:21:33 +04:00
return ( cur ) ;
}
2001-02-23 20:55:21 +03:00
/**
* 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
2001-12-17 18:30:10 +03:00
* are optional ( NULL ) .
2001-02-23 20:55:21 +03:00
* 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 )
}
}
2003-01-01 23:59:38 +03:00
2001-02-23 20:55:21 +03:00
return ( cur ) ;
}
2002-05-29 12:21:33 +04:00
/**
* xmlNewDocNodeEatName :
* @ 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 optional ( 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
xmlNewDocNodeEatName ( xmlDocPtr doc , xmlNsPtr ns ,
xmlChar * name , const xmlChar * content ) {
xmlNodePtr cur ;
cur = xmlNewNodeEatName ( ns , name ) ;
if ( cur ! = NULL ) {
cur - > doc = doc ;
if ( content ! = NULL ) {
cur - > children = xmlStringGetNodeList ( doc , content ) ;
UPDATE_LAST_CHILD_AND_PARENT ( cur )
}
}
return ( cur ) ;
}
2003-09-29 22:02:38 +04:00
# ifdef LIBXML_TREE_ENABLED
2001-02-23 20:55:21 +03:00
/**
* 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
2001-12-17 18:30:10 +03:00
* are optional ( NULL ) .
2001-02-23 20:55:21 +03:00
*
* 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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " building fragment " ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlNode ) ) ;
cur - > type = XML_DOCUMENT_FRAG_NODE ;
cur - > doc = doc ;
2003-01-01 23:59:38 +03:00
2003-04-22 01:36:41 +04:00
if ( ( __xmlRegisterCallbacks ) & & ( xmlRegisterNodeDefaultValue ) )
2003-01-01 23:59:38 +03:00
xmlRegisterNodeDefaultValue ( cur ) ;
2001-02-23 20:55:21 +03:00
return ( cur ) ;
}
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2001-02-23 20:55:21 +03:00
/**
* 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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " building text " ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlNode ) ) ;
cur - > type = XML_TEXT_NODE ;
cur - > name = xmlStringText ;
if ( content ! = NULL ) {
cur - > content = xmlStrdup ( content ) ;
}
2003-01-01 23:59:38 +03:00
2003-04-22 01:36:41 +04:00
if ( ( __xmlRegisterCallbacks ) & & ( xmlRegisterNodeDefaultValue ) )
2003-01-01 23:59:38 +03:00
xmlRegisterNodeDefaultValue ( cur ) ;
2001-02-23 20:55:21 +03:00
return ( cur ) ;
}
2003-09-29 22:02:38 +04:00
# ifdef LIBXML_TREE_ENABLED
2001-02-23 20:55:21 +03:00
/**
* 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 .
2003-12-21 02:43:28 +03:00
* @ ns and @ content parameters are optional ( NULL ) . If @ ns is NULL , the newly
* created element inherits the namespace of @ parent . If @ content is non NULL ,
2003-11-14 10:13:16 +03:00
* a child TEXT node will be created containing the string @ content .
2003-12-17 06:45:01 +03:00
* NOTE : Use xmlNewChild ( ) if @ content will contain entities that need to be
* preserved . Use this function , xmlNewTextChild ( ) , if you need to ensure that
* reserved XML chars that might appear in @ content , such as the ampersand ,
* greater - than or less - than signs , are automatically replaced by their XML
* escaped entity representations .
2001-02-23 20:55:21 +03:00
*
* 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
*/
2003-11-01 20:04:58 +03:00
if ( parent - > type = = XML_ELEMENT_NODE ) {
if ( ns = = NULL )
cur = xmlNewDocRawNode ( parent - > doc , parent - > ns , name , content ) ;
else
cur = xmlNewDocRawNode ( parent - > doc , ns , name , content ) ;
} else if ( ( parent - > type = = XML_DOCUMENT_NODE ) | |
( parent - > type = = XML_HTML_DOCUMENT_NODE ) ) {
if ( ns = = NULL )
cur = xmlNewDocRawNode ( ( xmlDocPtr ) parent , NULL , name , content ) ;
else
cur = xmlNewDocRawNode ( ( xmlDocPtr ) parent , ns , name , content ) ;
} else if ( parent - > type = = XML_DOCUMENT_FRAG_NODE ) {
cur = xmlNewDocRawNode ( parent - > doc , ns , name , content ) ;
} else {
return ( NULL ) ;
}
2001-02-23 20:55:21 +03:00
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 ) ;
}
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2001-02-23 20:55:21 +03:00
/**
* 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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " building character reference " ) ;
2001-02-23 20:55:21 +03:00
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 ) ;
2003-01-01 23:59:38 +03:00
2003-04-22 01:36:41 +04:00
if ( ( __xmlRegisterCallbacks ) & & ( xmlRegisterNodeDefaultValue ) )
2003-01-01 23:59:38 +03:00
xmlRegisterNodeDefaultValue ( cur ) ;
2001-02-23 20:55:21 +03:00
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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " building reference " ) ;
2001-02-23 20:55:21 +03:00
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 ) {
cur - > content = ent - > content ;
/*
2001-12-31 19:16:02 +03:00
* The parent pointer in entity is a DTD pointer and thus is NOT
2001-02-23 20:55:21 +03:00
* updated . Not sure if this is 100 % correct .
* - George
*/
cur - > children = ( xmlNodePtr ) ent ;
cur - > last = ( xmlNodePtr ) ent ;
}
2003-01-01 23:59:38 +03:00
2003-04-22 01:36:41 +04:00
if ( ( __xmlRegisterCallbacks ) & & ( xmlRegisterNodeDefaultValue ) )
2003-01-01 23:59:38 +03:00
xmlRegisterNodeDefaultValue ( cur ) ;
2001-02-23 20:55:21 +03:00
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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " building text " ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlNode ) ) ;
cur - > type = XML_TEXT_NODE ;
cur - > name = xmlStringText ;
if ( content ! = NULL ) {
cur - > content = xmlStrndup ( content , len ) ;
}
2003-01-01 23:59:38 +03:00
2003-04-22 01:36:41 +04:00
if ( ( __xmlRegisterCallbacks ) & & ( xmlRegisterNodeDefaultValue ) )
2003-01-01 23:59:38 +03:00
xmlRegisterNodeDefaultValue ( cur ) ;
2001-02-23 20:55:21 +03:00
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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " building comment " ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlNode ) ) ;
cur - > type = XML_COMMENT_NODE ;
cur - > name = xmlStringComment ;
if ( content ! = NULL ) {
cur - > content = xmlStrdup ( content ) ;
}
2003-01-01 23:59:38 +03:00
2003-04-22 01:36:41 +04:00
if ( ( __xmlRegisterCallbacks ) & & ( xmlRegisterNodeDefaultValue ) )
2003-01-01 23:59:38 +03:00
xmlRegisterNodeDefaultValue ( cur ) ;
2001-02-23 20:55:21 +03:00
return ( cur ) ;
}
/**
* xmlNewCDataBlock :
* @ doc : the document
2001-12-17 18:30:10 +03:00
* @ content : the CDATA block content content
2001-02-23 20:55:21 +03:00
* @ len : the length of the block
*
2001-12-17 18:30:10 +03:00
* Creation of a new node containing a CDATA block .
2001-02-23 20:55:21 +03:00
* 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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " building CDATA " ) ;
2001-02-23 20:55:21 +03:00
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 ) {
cur - > content = xmlStrndup ( content , len ) ;
}
2003-01-01 23:59:38 +03:00
2003-04-22 01:36:41 +04:00
if ( ( __xmlRegisterCallbacks ) & & ( xmlRegisterNodeDefaultValue ) )
2003-01-01 23:59:38 +03:00
xmlRegisterNodeDefaultValue ( cur ) ;
2001-02-23 20:55:21 +03:00
return ( cur ) ;
}
/**
* xmlNewDocComment :
* @ doc : the document
* @ content : the comment content
*
2001-12-17 18:30:10 +03:00
* Creation of a new node containing a comment within a document .
2001-02-23 20:55:21 +03:00
* 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 - > doc ! = doc ) {
2002-01-24 18:02:46 +03:00
if ( tree - > type = = XML_ELEMENT_NODE ) {
prop = tree - > properties ;
while ( prop ! = NULL ) {
prop - > doc = doc ;
xmlSetListDoc ( prop - > children , doc ) ;
prop = prop - > next ;
}
2001-07-09 14:32:59 +04:00
}
2001-02-23 20:55:21 +03:00
if ( tree - > children ! = NULL )
xmlSetListDoc ( tree - > children , doc ) ;
tree - > doc = doc ;
}
}
/**
* xmlSetListDoc :
2001-12-17 18:30:10 +03:00
* @ list : the first element
2001-02-23 20:55:21 +03:00
* @ 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 ;
}
}
2004-03-04 18:59:36 +03:00
# if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
2001-02-23 20:55:21 +03:00
/**
* 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 .
2003-12-21 02:43:28 +03:00
* @ ns and @ content parameters are optional ( NULL ) . If @ ns is NULL , the newly
* created element inherits the namespace of @ parent . If @ content is non NULL ,
2001-02-23 20:55:21 +03:00
* a child list containing the TEXTs and ENTITY_REFs node will be created .
2003-12-17 06:45:01 +03:00
* NOTE : @ content is supposed to be a piece of XML CDATA , so it allows entity
* references . XML special chars must be escaped first by using
* xmlEncodeEntitiesReentrant ( ) , or xmlNewTextChild ( ) should be used .
2001-02-23 20:55:21 +03:00
*
* 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
*/
2002-02-04 03:17:01 +03:00
if ( parent - > type = = XML_ELEMENT_NODE ) {
if ( ns = = NULL )
cur = xmlNewDocNode ( parent - > doc , parent - > ns , name , content ) ;
else
cur = xmlNewDocNode ( parent - > doc , ns , name , content ) ;
} else if ( ( parent - > type = = XML_DOCUMENT_NODE ) | |
( parent - > type = = XML_HTML_DOCUMENT_NODE ) ) {
if ( ns = = NULL )
cur = xmlNewDocNode ( ( xmlDocPtr ) parent , NULL , name , content ) ;
else
cur = xmlNewDocNode ( ( xmlDocPtr ) parent , ns , name , content ) ;
2002-10-28 21:52:57 +03:00
} else if ( parent - > type = = XML_DOCUMENT_FRAG_NODE ) {
cur = xmlNewDocNode ( parent - > doc , ns , name , content ) ;
2002-02-04 03:17:01 +03:00
} else {
return ( NULL ) ;
}
2001-02-23 20:55:21 +03:00
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 ) ;
}
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2001-02-23 20:55:21 +03:00
/**
* xmlAddNextSibling :
* @ cur : the child node
* @ elem : the new node
*
2002-01-24 19:05:41 +03:00
* Add a new node @ elem as the next sibling of @ cur
* If the new node was already inserted in a document it is
2001-02-23 20:55:21 +03:00
* first unlinked from its existing context .
* As a result of text merging @ elem may be freed .
2002-01-24 19:05:41 +03:00
* If the new node is ATTRIBUTE , it is added into properties instead of children .
* If there is an attribute with equal name , it is first destroyed .
2001-02-23 20:55:21 +03:00
*
2002-01-24 19:05:41 +03:00
* Returns the new node or NULL in case of error .
2001-02-23 20:55:21 +03:00
*/
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 ) {
xmlNodeAddContent ( cur , elem - > content ) ;
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
xmlChar * tmp ;
tmp = xmlStrdup ( elem - > content ) ;
tmp = xmlStrcat ( tmp , cur - > next - > content ) ;
xmlNodeSetContent ( cur - > next , tmp ) ;
xmlFree ( tmp ) ;
xmlFreeNode ( elem ) ;
return ( cur - > next ) ;
}
2002-01-24 19:05:41 +03:00
} else if ( elem - > type = = XML_ATTRIBUTE_NODE ) {
/* check if an attribute with the same name exists */
xmlAttrPtr attr ;
if ( elem - > ns = = NULL )
attr = xmlHasProp ( cur - > parent , elem - > name ) ;
else
attr = xmlHasNsProp ( cur - > parent , elem - > name , elem - > ns - > href ) ;
if ( ( attr ! = NULL ) & & ( attr ! = ( xmlAttrPtr ) elem ) ) {
/* different instance, destroy it (attributes must be unique) */
xmlFreeProp ( attr ) ;
}
2001-02-23 20:55:21 +03:00
}
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 ;
2002-01-24 19:05:41 +03:00
if ( ( elem - > parent ! = NULL ) & & ( elem - > parent - > last = = cur ) & & ( elem - > type ! = XML_ATTRIBUTE_NODE ) )
2001-02-23 20:55:21 +03:00
elem - > parent - > last = elem ;
return ( elem ) ;
}
2004-03-04 18:59:36 +03:00
# if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED)
2001-02-23 20:55:21 +03:00
/**
* xmlAddPrevSibling :
* @ cur : the child node
* @ elem : the new node
*
2002-01-24 19:05:41 +03:00
* Add a new node @ elem as the previous sibling of @ cur
2001-02-23 20:55:21 +03:00
* merging adjacent TEXT nodes ( @ elem may be freed )
2002-01-24 19:05:41 +03:00
* If the new node was already inserted in a document it is
2001-02-23 20:55:21 +03:00
* first unlinked from its existing context .
2002-01-24 19:05:41 +03:00
* If the new node is ATTRIBUTE , it is added into properties instead of children .
* If there is an attribute with equal name , it is first destroyed .
2001-02-23 20:55:21 +03:00
*
2002-01-24 19:05:41 +03:00
* Returns the new node or NULL in case of error .
2001-02-23 20:55:21 +03:00
*/
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 ) {
xmlChar * tmp ;
tmp = xmlStrdup ( elem - > content ) ;
tmp = xmlStrcat ( tmp , cur - > content ) ;
xmlNodeSetContent ( cur , tmp ) ;
xmlFree ( tmp ) ;
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
xmlNodeAddContent ( cur - > prev , elem - > content ) ;
xmlFreeNode ( elem ) ;
return ( cur - > prev ) ;
}
2002-01-24 19:05:41 +03:00
} else if ( elem - > type = = XML_ATTRIBUTE_NODE ) {
/* check if an attribute with the same name exists */
xmlAttrPtr attr ;
if ( elem - > ns = = NULL )
attr = xmlHasProp ( cur - > parent , elem - > name ) ;
else
attr = xmlHasNsProp ( cur - > parent , elem - > name , elem - > ns - > href ) ;
if ( ( attr ! = NULL ) & & ( attr ! = ( xmlAttrPtr ) elem ) ) {
/* different instance, destroy it (attributes must be unique) */
xmlFreeProp ( attr ) ;
}
2001-02-23 20:55:21 +03:00
}
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 ;
2002-01-24 19:05:41 +03:00
if ( elem - > parent ! = NULL ) {
if ( elem - > type = = XML_ATTRIBUTE_NODE ) {
if ( elem - > parent - > properties = = ( xmlAttrPtr ) cur ) {
elem - > parent - > properties = ( xmlAttrPtr ) elem ;
}
} else {
if ( elem - > parent - > children = = cur ) {
elem - > parent - > children = elem ;
}
}
}
2001-02-23 20:55:21 +03:00
return ( elem ) ;
}
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2001-02-23 20:55:21 +03:00
/**
* 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 ) ;
2003-10-29 15:53:27 +03:00
if ( ( cur - > type = = XML_TEXT_NODE ) & & ( elem - > type = = XML_TEXT_NODE ) & &
( cur - > name = = elem - > name ) ) {
2001-02-23 20:55:21 +03:00
xmlNodeAddContent ( cur , elem - > content ) ;
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 ,
2001-12-17 18:30:10 +03:00
" xmlAddChildList : parent == NULL \n " ) ;
2001-02-23 20:55:21 +03:00
# endif
return ( NULL ) ;
}
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
2001-12-17 18:30:10 +03:00
" xmlAddChildList : child == NULL \n " ) ;
2001-02-23 20:55:21 +03:00
# 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 .
*/
2003-01-01 23:59:38 +03:00
2001-02-23 20:55:21 +03:00
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 ) ) {
2003-01-01 23:59:38 +03:00
xmlNodeAddContent ( parent - > last , cur - > content ) ;
2001-02-23 20:55:21 +03:00
/*
* 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
*
2002-01-24 19:05:41 +03:00
* Add a new node to @ parent , at the end of the child ( or property ) list
2001-02-23 20:55:21 +03:00
* merging adjacent TEXT nodes ( in which case @ cur is freed )
2002-01-24 19:05:41 +03:00
* If the new node is ATTRIBUTE , it is added into properties instead of children .
* If there is an attribute with equal name , it is first destroyed .
*
2001-02-23 20:55:21 +03:00
* 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 ) & &
2003-01-01 23:59:38 +03:00
( parent - > content ! = NULL ) & &
2003-10-29 15:53:27 +03:00
( parent - > name = = cur - > name ) & &
2003-01-01 23:59:38 +03:00
( parent ! = cur ) ) {
2001-02-23 20:55:21 +03:00
xmlNodeAddContent ( parent , cur - > content ) ;
xmlFreeNode ( cur ) ;
return ( parent ) ;
}
if ( ( parent - > last ! = NULL ) & & ( parent - > last - > type = = XML_TEXT_NODE ) & &
2003-01-01 23:59:38 +03:00
( parent - > last - > name = = cur - > name ) & &
( parent - > last ! = cur ) ) {
2001-02-23 20:55:21 +03:00
xmlNodeAddContent ( parent - > last , cur - > content ) ;
xmlFreeNode ( cur ) ;
return ( parent - > last ) ;
}
}
/*
* add the new element at the end of the children list .
*/
2003-01-01 23:59:38 +03:00
prev = cur - > parent ;
2001-02-23 20:55:21 +03:00
cur - > parent = parent ;
if ( cur - > doc ! = parent - > doc ) {
xmlSetTreeDoc ( cur , parent - > doc ) ;
}
2003-01-01 23:59:38 +03:00
/* this check prevents a loop on tree-traversions if a developer
* tries to add a node to its parent multiple times
*/
if ( prev = = parent )
return ( cur ) ;
2001-02-23 20:55:21 +03:00
/*
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 ) & &
2003-01-01 23:59:38 +03:00
( parent - > content ! = NULL ) & &
( parent ! = cur ) ) {
2001-07-12 05:20:08 +04:00
xmlNodeAddContent ( parent , cur - > content ) ;
xmlFreeNode ( cur ) ;
return ( parent ) ;
2001-02-23 20:55:21 +03:00
}
2002-01-24 19:05:41 +03:00
if ( cur - > type = = XML_ATTRIBUTE_NODE ) {
if ( parent - > properties = = NULL ) {
parent - > properties = ( xmlAttrPtr ) cur ;
} else {
/* check if an attribute with the same name exists */
xmlAttrPtr lastattr ;
if ( cur - > ns = = NULL )
lastattr = xmlHasProp ( parent , cur - > name ) ;
else
lastattr = xmlHasNsProp ( parent , cur - > name , cur - > ns - > href ) ;
if ( ( lastattr ! = NULL ) & & ( lastattr ! = ( xmlAttrPtr ) cur ) ) {
/* different instance, destroy it (attributes must be unique) */
xmlFreeProp ( lastattr ) ;
}
/* find the end */
lastattr = parent - > properties ;
while ( lastattr - > next ! = NULL ) {
lastattr = lastattr - > next ;
}
lastattr - > next = ( xmlAttrPtr ) cur ;
( ( xmlAttrPtr ) cur ) - > prev = lastattr ;
}
2001-02-23 20:55:21 +03:00
} else {
2002-01-24 19:05:41 +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 ;
}
2001-02-23 20:55:21 +03:00
}
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 ;
2003-09-25 01:23:56 +04:00
xmlDictPtr dict = NULL ;
if ( cur = = NULL ) return ;
2002-01-14 20:11:53 +03:00
if ( cur - > type = = XML_NAMESPACE_DECL ) {
xmlFreeNsList ( ( xmlNsPtr ) cur ) ;
return ;
}
2003-03-24 21:39:54 +03:00
if ( ( cur - > type = = XML_DOCUMENT_NODE ) | |
# ifdef LIBXML_DOCB_ENABLED
( cur - > type = = XML_DOCB_DOCUMENT_NODE ) | |
# endif
2003-03-28 00:25:38 +03:00
( cur - > type = = XML_HTML_DOCUMENT_NODE ) ) {
2003-03-24 21:39:54 +03:00
xmlFreeDoc ( ( xmlDocPtr ) cur ) ;
return ;
}
2003-09-25 01:23:56 +04:00
if ( cur - > doc ! = NULL ) dict = cur - > doc - > dict ;
2001-02-23 20:55:21 +03:00
while ( cur ! = NULL ) {
next = cur - > next ;
2001-04-30 15:46:40 +04:00
if ( cur - > type ! = XML_DTD_NODE ) {
2003-01-01 23:59:38 +03:00
2003-04-22 01:36:41 +04:00
if ( ( __xmlRegisterCallbacks ) & & ( xmlDeregisterNodeDefaultValue ) )
2003-01-01 23:59:38 +03:00
xmlDeregisterNodeDefaultValue ( cur ) ;
2001-04-30 15:46:40 +04:00
if ( ( cur - > children ! = NULL ) & &
( cur - > type ! = XML_ENTITY_REF_NODE ) )
xmlFreeNodeList ( cur - > children ) ;
2002-12-10 18:19:08 +03:00
if ( ( ( cur - > type = = XML_ELEMENT_NODE ) | |
( cur - > type = = XML_XINCLUDE_START ) | |
( cur - > type = = XML_XINCLUDE_END ) ) & &
2002-12-09 17:13:43 +03:00
( cur - > properties ! = NULL ) )
2001-04-30 15:46:40 +04:00
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 ) ) {
2003-09-25 01:23:56 +04:00
DICT_FREE ( cur - > content )
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 .
2003-09-25 01:23:56 +04:00
* Otherwise the node name might come from the document ' s
* dictionnary
2001-06-11 12:09:20 +04:00
*/
2001-04-30 15:46:40 +04:00
if ( ( cur - > name ! = NULL ) & &
2003-09-25 01:23:56 +04:00
( cur - > type ! = XML_TEXT_NODE ) & &
( cur - > type ! = XML_COMMENT_NODE ) )
DICT_FREE ( cur - > name )
2001-04-30 15:46:40 +04:00
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 ) {
2003-09-25 01:23:56 +04:00
xmlDictPtr dict = NULL ;
if ( cur = = NULL ) return ;
2003-01-01 23:59:38 +03:00
2001-04-30 15:46:40 +04:00
/* use xmlFreeDtd for DTD nodes */
2002-01-14 20:11:53 +03:00
if ( cur - > type = = XML_DTD_NODE ) {
xmlFreeDtd ( ( xmlDtdPtr ) cur ) ;
2001-02-23 20:55:21 +03:00
return ;
2002-01-14 20:11:53 +03:00
}
if ( cur - > type = = XML_NAMESPACE_DECL ) {
xmlFreeNs ( ( xmlNsPtr ) cur ) ;
return ;
}
2002-11-07 17:18:03 +03:00
if ( cur - > type = = XML_ATTRIBUTE_NODE ) {
xmlFreeProp ( ( xmlAttrPtr ) cur ) ;
return ;
}
2003-01-01 23:59:38 +03:00
2003-04-22 01:36:41 +04:00
if ( ( __xmlRegisterCallbacks ) & & ( xmlDeregisterNodeDefaultValue ) )
2003-01-01 23:59:38 +03:00
xmlDeregisterNodeDefaultValue ( cur ) ;
2003-09-25 01:23:56 +04:00
if ( cur - > doc ! = NULL ) dict = cur - > doc - > dict ;
2001-02-23 20:55:21 +03:00
if ( ( cur - > children ! = NULL ) & &
( cur - > type ! = XML_ENTITY_REF_NODE ) )
xmlFreeNodeList ( cur - > children ) ;
2002-12-10 18:19:08 +03:00
if ( ( ( cur - > type = = XML_ELEMENT_NODE ) | |
( cur - > type = = XML_XINCLUDE_START ) | |
( cur - > type = = XML_XINCLUDE_END ) ) & &
( cur - > properties ! = NULL ) )
2001-04-30 15:46:40 +04:00
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 ) ) {
2003-09-25 01:23:56 +04:00
DICT_FREE ( cur - > content )
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 .
2003-09-25 01:23:56 +04:00
* Otherwise the node name might come from the document ' s dictionnary
2001-06-09 21:17:51 +04:00
*/
2001-02-23 20:55:21 +03:00
if ( ( cur - > name ! = NULL ) & &
2003-09-25 01:23:56 +04:00
( cur - > type ! = XML_TEXT_NODE ) & &
( cur - > type ! = XML_COMMENT_NODE ) )
DICT_FREE ( cur - > name )
2001-06-09 21:17:51 +04:00
2002-12-09 17:13:43 +03:00
if ( ( ( cur - > type = = XML_ELEMENT_NODE ) | |
( cur - > type = = XML_XINCLUDE_START ) | |
( cur - > type = = XML_XINCLUDE_END ) ) & &
( cur - > nsDef ! = NULL ) )
xmlFreeNsList ( cur - > nsDef ) ;
2001-02-23 20:55:21 +03:00
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 ;
2003-05-01 12:03:46 +04:00
if ( doc ! = NULL ) {
if ( doc - > intSubset = = ( xmlDtdPtr ) cur )
doc - > intSubset = NULL ;
if ( doc - > extSubset = = ( xmlDtdPtr ) cur )
doc - > extSubset = NULL ;
}
2001-12-14 01:21:58 +03:00
}
2002-01-23 00:40:13 +03:00
if ( cur - > parent ! = NULL ) {
xmlNodePtr parent ;
parent = cur - > parent ;
if ( cur - > type = = XML_ATTRIBUTE_NODE ) {
if ( parent - > properties = = ( xmlAttrPtr ) cur )
parent - > properties = ( ( xmlAttrPtr ) cur ) - > next ;
} else {
if ( parent - > children = = cur )
parent - > children = cur - > next ;
if ( parent - > last = = cur )
parent - > last = cur - > prev ;
}
cur - > parent = NULL ;
}
2001-02-23 20:55:21 +03:00
if ( cur - > next ! = NULL )
cur - > next - > prev = cur - > prev ;
if ( cur - > prev ! = NULL )
cur - > prev - > next = cur - > next ;
cur - > next = cur - > prev = NULL ;
}
2004-03-04 18:59:36 +03:00
# if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)
2001-02-23 20:55:21 +03:00
/**
* xmlReplaceNode :
* @ old : the old node
* @ cur : the node
*
2003-11-14 10:13:16 +03:00
* Unlink the old node from its current context , prune the new one
2001-12-17 18:30:10 +03:00
* at the same place . If @ cur was already inserted in a document it is
2001-02-23 20:55:21 +03:00
* first unlinked from its existing context .
*
2001-12-17 18:30:10 +03:00
* Returns the @ old node
2001-02-23 20:55:21 +03:00
*/
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 ) ;
}
2002-01-23 00:40:13 +03:00
if ( ( old - > type = = XML_ATTRIBUTE_NODE ) & & ( cur - > type ! = XML_ATTRIBUTE_NODE ) ) {
2002-01-24 19:05:41 +03:00
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlReplaceNode : Trying to replace attribute node with other node type \n " ) ;
# endif
return ( old ) ;
}
if ( ( cur - > type = = XML_ATTRIBUTE_NODE ) & & ( old - > type ! = XML_ATTRIBUTE_NODE ) ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlReplaceNode : Trying to replace a non-attribute node with attribute node \n " ) ;
2002-01-23 00:40:13 +03:00
# endif
return ( old ) ;
}
2001-02-23 20:55:21 +03:00
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 ) {
2002-01-23 00:40:13 +03:00
if ( cur - > type = = XML_ATTRIBUTE_NODE ) {
if ( cur - > parent - > properties = = ( xmlAttrPtr ) old )
cur - > parent - > properties = ( ( xmlAttrPtr ) cur ) ;
} else {
if ( cur - > parent - > children = = old )
cur - > parent - > children = cur ;
if ( cur - > parent - > last = = old )
cur - > parent - > last = cur ;
}
2001-02-23 20:55:21 +03:00
}
old - > next = old - > prev = NULL ;
old - > parent = NULL ;
return ( old ) ;
}
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2001-02-23 20:55:21 +03:00
/************************************************************************
* *
* Copy operations *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlCopyNamespace :
* @ cur : the namespace
*
* Do a copy of the namespace .
*
2001-12-17 18:30:10 +03:00
* Returns : a new # xmlNsPtr , or NULL in case of error .
2001-02-23 20:55:21 +03:00
*/
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 .
*
2001-12-17 18:30:10 +03:00
* Returns : a new # xmlNsPtr , or NULL in case of error .
2001-02-23 20:55:21 +03:00
*/
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 .
*
2001-12-17 18:30:10 +03:00
* Returns : a new # xmlAttrPtr , or NULL in case of error .
2001-02-23 20:55:21 +03:00
*/
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 ;
2002-03-03 17:13:46 +03:00
2001-02-23 20:55:21 +03:00
if ( ( cur - > ns ! = NULL ) & & ( target ! = NULL ) ) {
2002-01-13 17:10:10 +03:00
xmlNsPtr ns ;
2003-09-29 22:02:38 +04:00
2002-03-03 17:13:46 +03:00
ns = xmlSearchNs ( target - > doc , target , cur - > 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 ( cur - > doc , cur - > parent , cur - > ns - > prefix ) ;
if ( ns ! = NULL ) {
xmlNodePtr root = target ;
xmlNodePtr pred = NULL ;
while ( root - > parent ! = NULL ) {
pred = root ;
root = root - > parent ;
}
if ( root = = ( xmlNodePtr ) target - > doc ) {
/* correct possibly cycling above the document elt */
root = pred ;
}
ret - > ns = xmlNewNs ( root , ns - > href , ns - > prefix ) ;
}
} else {
/*
* we have to find something appropriate here since
* we cant be sure , that the namespce we found is identified
* by the prefix
*/
2002-03-04 20:09:44 +03:00
if ( xmlStrEqual ( ns - > href , cur - > ns - > href ) ) {
2002-03-03 17:13:46 +03:00
/* this is the nice case */
ret - > ns = ns ;
} else {
/*
* we are in trouble : we need a new reconcilied namespace .
* This is expensive
*/
ret - > ns = xmlNewReconciliedNs ( target - > doc , target , cur - > ns ) ;
}
}
2001-02-23 20:55:21 +03:00
} 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 ;
}
}
2002-02-10 14:57:22 +03:00
/*
* Try to handle IDs
*/
2002-03-08 18:46:57 +03:00
if ( ( target ! = NULL ) & & ( cur ! = NULL ) & &
( target - > doc ! = NULL ) & & ( cur - > doc ! = NULL ) & &
2002-02-10 14:57:22 +03:00
( cur - > doc - > ids ! = NULL ) & & ( cur - > parent ! = NULL ) ) {
if ( xmlIsID ( cur - > doc , cur - > parent , cur ) ) {
xmlChar * id ;
id = xmlNodeListGetString ( cur - > doc , cur - > children , 1 ) ;
if ( id ! = NULL ) {
xmlAddID ( NULL , target - > doc , id , ret ) ;
xmlFree ( id ) ;
}
}
}
2001-02-23 20:55:21 +03:00
return ( ret ) ;
}
/**
* xmlCopyPropList :
* @ target : the element where the attributes will be grafted
* @ cur : the first attribute
*
* Do a copy of an attribute list .
*
2001-12-17 18:30:10 +03:00
* Returns : a new # xmlAttrPtr , or NULL in case of error .
2001-02-23 20:55:21 +03:00
*/
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 ) ;
}
/*
2001-12-17 18:30:10 +03:00
* NOTE about the CopyNode operations !
2001-02-23 20:55:21 +03:00
*
2001-12-17 18:30:10 +03:00
* They are split into external and internal parts for one
2001-02-23 20:55:21 +03:00
* 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
2004-03-09 19:19:02 +03:00
* The argument " recursive " normally indicates a recursive copy
* of the node with values 0 ( no ) and 1 ( yes ) . For XInclude ,
* however , we allow a value of 2 to indicate copy properties and
* namespace info , but don ' t recurse on children .
2001-02-23 20:55:21 +03:00
*/
static xmlNodePtr
2001-08-29 00:39:49 +04:00
xmlStaticCopyNode ( const xmlNodePtr node , xmlDocPtr doc , xmlNodePtr parent ,
2004-03-09 19:19:02 +03:00
int extended ) {
2001-02-23 20:55:21 +03:00
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 :
2002-09-05 15:12:45 +04:00
case XML_DOCUMENT_FRAG_NODE :
2001-06-19 22:09:42 +04:00
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
2003-09-29 22:02:38 +04:00
# ifdef LIBXML_TREE_ENABLED
2004-03-09 19:19:02 +03:00
return ( ( xmlNodePtr ) xmlCopyDoc ( ( xmlDocPtr ) node , extended ) ) ;
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2001-06-19 22:09:42 +04:00
case XML_DOCUMENT_TYPE_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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " copying node " ) ;
2001-02-23 20:55:21 +03:00
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
ret - > content = xmlStrdup ( node - > content ) ;
2002-01-13 17:10:10 +03:00
} else {
if ( node - > type = = XML_ELEMENT_NODE )
2003-10-21 04:05:38 +04:00
ret - > line = node - > line ;
2001-02-23 20:55:21 +03:00
}
2002-01-13 19:15:43 +03:00
if ( parent ! = NULL ) {
xmlNodePtr tmp ;
2003-01-06 01:37:17 +03:00
/*
* this is a tricky part for the node register thing :
* in case ret does get coalesced in xmlAddChild
* the deregister - node callback is called ; so we register ret now already
*/
2003-04-22 01:36:41 +04:00
if ( ( __xmlRegisterCallbacks ) & & ( xmlRegisterNodeDefaultValue ) )
2003-01-06 01:37:17 +03:00
xmlRegisterNodeDefaultValue ( ( xmlNodePtr ) ret ) ;
2002-01-13 19:15:43 +03:00
tmp = xmlAddChild ( parent , ret ) ;
/* node could have coalesced */
if ( tmp ! = ret )
return ( tmp ) ;
}
2001-02-23 20:55:21 +03:00
2004-03-09 19:19:02 +03:00
if ( ! extended )
2003-01-06 01:37:17 +03:00
goto out ;
2001-02-23 20:55:21 +03:00
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
2001-12-17 18:30:10 +03:00
* to avoid dangling references to the ENTITY_DECL node
2001-04-25 16:59:04 +04:00
* 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 ;
2004-03-09 19:19:02 +03:00
} else if ( ( node - > children ! = NULL ) & & ( extended ! = 2 ) ) {
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 )
}
2003-01-06 01:37:17 +03:00
out :
/* if parent != NULL we already registered the node above */
2004-07-30 16:02:58 +04:00
if ( ( parent = = NULL ) & &
( ( __xmlRegisterCallbacks ) & & ( xmlRegisterNodeDefaultValue ) ) )
2003-01-06 01:37:17 +03:00
xmlRegisterNodeDefaultValue ( ( xmlNodePtr ) 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 ) {
2003-09-29 22:02:38 +04:00
# ifdef LIBXML_TREE_ENABLED
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 ;
2002-01-27 00:42:58 +03:00
xmlAddChild ( parent , q ) ;
2001-04-25 16:59:04 +04:00
} else {
q = ( xmlNodePtr ) doc - > intSubset ;
2002-01-27 00:42:58 +03:00
xmlAddChild ( parent , q ) ;
2001-04-25 16:59:04 +04:00
}
} else
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2001-04-25 16:59:04 +04:00
q = xmlStaticCopyNode ( node , doc , parent , 1 ) ;
2001-02-23 20:55:21 +03:00
if ( ret = = NULL ) {
q - > prev = NULL ;
ret = p = q ;
2002-01-13 19:15:43 +03:00
} else if ( p ! = q ) {
/* the test is required if xmlStaticCopyNode coalesced 2 text nodes */
2001-02-23 20:55:21 +03:00
p - > next = q ;
q - > prev = p ;
p = q ;
}
node = node - > next ;
}
return ( ret ) ;
}
/**
* xmlCopyNode :
* @ node : the node
2004-03-09 19:19:02 +03:00
* @ extended : if 1 do a recursive copy ( properties , namespaces and children
* when applicable )
* if 2 copy properties and namespaces ( when applicable )
2001-02-23 20:55:21 +03:00
*
* Do a copy of the node .
*
2001-12-17 18:30:10 +03:00
* Returns : a new # xmlNodePtr , or NULL in case of error .
2001-02-23 20:55:21 +03:00
*/
xmlNodePtr
2004-03-09 19:19:02 +03:00
xmlCopyNode ( const xmlNodePtr node , int extended ) {
2001-02-23 20:55:21 +03:00
xmlNodePtr ret ;
2004-03-09 19:19:02 +03:00
ret = xmlStaticCopyNode ( node , NULL , NULL , extended ) ;
2001-02-23 20:55:21 +03:00
return ( ret ) ;
}
2001-04-12 12:55:36 +04:00
/**
* xmlDocCopyNode :
* @ node : the node
2001-12-17 18:30:10 +03:00
* @ doc : the document
2004-03-09 19:19:02 +03:00
* @ extended : if 1 do a recursive copy ( properties , namespaces and children
* when applicable )
* if 2 copy properties and namespaces ( when applicable )
2001-04-12 12:55:36 +04:00
*
* Do a copy of the node to a given document .
*
2001-12-17 18:30:10 +03:00
* Returns : a new # xmlNodePtr , or NULL in case of error .
2001-04-12 12:55:36 +04:00
*/
xmlNodePtr
2004-03-09 19:19:02 +03:00
xmlDocCopyNode ( const xmlNodePtr node , xmlDocPtr doc , int extended ) {
2001-04-12 12:55:36 +04:00
xmlNodePtr ret ;
2004-03-09 19:19:02 +03:00
ret = xmlStaticCopyNode ( node , doc , NULL , extended ) ;
2001-04-12 12:55:36 +04:00
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 .
*
2001-12-17 18:30:10 +03:00
* Returns : a new # xmlNodePtr , or NULL in case of error .
2001-02-23 20:55:21 +03:00
*/
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 ) ;
}
2004-03-04 18:59:36 +03:00
# if defined(LIBXML_TREE_ENABLED)
2001-02-23 20:55:21 +03:00
/**
* xmlCopyDtd :
* @ dtd : the dtd
*
* Do a copy of the dtd .
*
2001-12-17 18:30:10 +03:00
* Returns : a new # xmlDtdPtr , or NULL in case of error .
2001-02-23 20:55:21 +03:00
*/
xmlDtdPtr
xmlCopyDtd ( xmlDtdPtr dtd ) {
xmlDtdPtr ret ;
2002-01-27 00:42:58 +03:00
xmlNodePtr cur , p = NULL , q ;
2001-02-23 20:55:21 +03:00
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 ) ;
2002-01-27 00:42:58 +03:00
if ( dtd - > pentities ! = NULL )
ret - > pentities = ( void * ) xmlCopyEntitiesTable (
( xmlEntitiesTablePtr ) dtd - > pentities ) ;
cur = dtd - > children ;
while ( cur ! = NULL ) {
q = NULL ;
if ( cur - > type = = XML_ENTITY_DECL ) {
xmlEntityPtr tmp = ( xmlEntityPtr ) cur ;
switch ( tmp - > etype ) {
case XML_INTERNAL_GENERAL_ENTITY :
case XML_EXTERNAL_GENERAL_PARSED_ENTITY :
case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY :
q = ( xmlNodePtr ) xmlGetEntityFromDtd ( ret , tmp - > name ) ;
break ;
case XML_INTERNAL_PARAMETER_ENTITY :
case XML_EXTERNAL_PARAMETER_ENTITY :
q = ( xmlNodePtr )
xmlGetParameterEntityFromDtd ( ret , tmp - > name ) ;
break ;
case XML_INTERNAL_PREDEFINED_ENTITY :
break ;
}
} else if ( cur - > type = = XML_ELEMENT_DECL ) {
xmlElementPtr tmp = ( xmlElementPtr ) cur ;
q = ( xmlNodePtr )
xmlGetDtdQElementDesc ( ret , tmp - > name , tmp - > prefix ) ;
} else if ( cur - > type = = XML_ATTRIBUTE_DECL ) {
xmlAttributePtr tmp = ( xmlAttributePtr ) cur ;
q = ( xmlNodePtr )
xmlGetDtdQAttrDesc ( ret , tmp - > elem , tmp - > name , tmp - > prefix ) ;
} else if ( cur - > type = = XML_COMMENT_NODE ) {
q = xmlCopyNode ( cur , 0 ) ;
}
if ( q = = NULL ) {
cur = cur - > next ;
continue ;
}
if ( p = = NULL )
ret - > children = q ;
else
p - > next = q ;
q - > prev = p ;
q - > parent = ( xmlNodePtr ) ret ;
q - > next = NULL ;
ret - > last = q ;
p = q ;
cur = cur - > next ;
}
2001-02-23 20:55:21 +03:00
return ( ret ) ;
}
2004-03-04 18:59:36 +03:00
# endif
2001-02-23 20:55:21 +03:00
2004-03-04 18:59:36 +03:00
# if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
2001-02-23 20:55:21 +03:00
/**
* xmlCopyDoc :
* @ doc : the document
2004-03-09 19:19:02 +03:00
* @ recursive : if not zero do a recursive copy .
2001-02-23 20:55:21 +03:00
*
* Do a copy of the document info . If recursive , the content tree will
2001-12-31 19:16:02 +03:00
* be copied too as well as DTD , namespaces and entities .
2001-02-23 20:55:21 +03:00
*
2001-12-17 18:30:10 +03:00
* Returns : a new # xmlDocPtr , or NULL in case of error .
2001-02-23 20:55:21 +03:00
*/
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 ;
2004-03-04 18:59:36 +03:00
# ifdef LIBXML_TREE_ENABLED
2001-04-25 16:59:04 +04:00
if ( doc - > intSubset ! = NULL ) {
2001-02-23 20:55:21 +03:00
ret - > intSubset = xmlCopyDtd ( doc - > intSubset ) ;
2002-01-27 00:42:58 +03:00
xmlSetTreeDoc ( ( xmlNodePtr ) ret - > intSubset , ret ) ;
2001-04-25 16:59:04 +04:00
ret - > intSubset - > parent = ret ;
}
2004-03-04 18:59:36 +03:00
# endif
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 ) ;
}
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2001-02-23 20:55:21 +03:00
/************************************************************************
* *
* Content access functions *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-26 18:58:08 +03:00
/**
* xmlGetLineNo :
2002-12-10 18:19:08 +03:00
* @ node : valid node
2001-11-26 18:58:08 +03:00
*
2003-11-14 10:13:16 +03:00
* Get line number of @ node . This requires activation of this option
2001-12-17 18:30:10 +03:00
* before invoking the parser by calling xmlLineNumbersDefault ( 1 )
2001-11-26 18:58:08 +03:00
*
2001-12-17 18:30:10 +03:00
* Returns the line number if successful , - 1 otherwise
2001-11-26 18:58:08 +03:00
*/
long
xmlGetLineNo ( xmlNodePtr node )
{
long result = - 1 ;
if ( ! node )
return result ;
if ( node - > type = = XML_ELEMENT_NODE )
2003-10-21 04:05:38 +04:00
result = ( long ) node - > line ;
2001-11-26 18:58:08 +03:00
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 ;
}
2004-03-04 18:59:36 +03:00
# if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED)
2001-11-26 18:58:08 +03:00
/**
* 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 ;
2002-10-14 19:39:04 +04:00
const char * sep ;
2001-11-26 18:58:08 +03:00
const char * name ;
char nametemp [ 100 ] ;
int occur = 0 ;
if ( node = = NULL )
return ( NULL ) ;
buf_len = 500 ;
2003-04-19 04:07:51 +04:00
buffer = ( xmlChar * ) xmlMallocAtomic ( buf_len * sizeof ( xmlChar ) ) ;
2003-10-08 03:16:40 +04:00
if ( buffer = = NULL ) {
xmlTreeErrMemory ( " getting node path " ) ;
2001-11-26 18:58:08 +03:00
return ( NULL ) ;
2003-10-08 03:16:40 +04:00
}
2003-04-19 04:07:51 +04:00
buf = ( xmlChar * ) xmlMallocAtomic ( buf_len * sizeof ( xmlChar ) ) ;
2001-11-26 18:58:08 +03:00
if ( buf = = NULL ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " getting node path " ) ;
2001-11-26 18:58:08 +03:00
xmlFree ( buffer ) ;
return ( NULL ) ;
}
buffer [ 0 ] = 0 ;
cur = node ;
do {
name = " " ;
2002-10-08 12:26:11 +04:00
sep = " ? " ;
2001-11-26 18:58:08 +03:00
occur = 0 ;
if ( ( cur - > type = = XML_DOCUMENT_NODE ) | |
( cur - > type = = XML_HTML_DOCUMENT_NODE ) ) {
if ( buffer [ 0 ] = = ' / ' )
break ;
2002-10-08 12:26:11 +04:00
sep = " / " ;
2001-11-26 18:58:08 +03:00
next = NULL ;
} else if ( cur - > type = = XML_ELEMENT_NODE ) {
2002-10-08 12:26:11 +04:00
sep = " / " ;
2001-11-26 18:58:08 +03:00
name = ( const char * ) cur - > name ;
if ( cur - > ns ) {
2003-12-23 06:45:17 +03:00
if ( cur - > ns - > prefix ! = NULL )
snprintf ( nametemp , sizeof ( nametemp ) - 1 ,
2001-11-26 18:58:08 +03:00
" %s:%s " , cur - > ns - > prefix , cur - > name ) ;
2003-12-23 06:45:17 +03:00
else
snprintf ( nametemp , sizeof ( nametemp ) - 1 ,
" %s " , cur - > name ) ;
2001-11-26 18:58:08 +03:00
nametemp [ sizeof ( nametemp ) - 1 ] = 0 ;
name = nametemp ;
}
next = cur - > parent ;
/*
* Thumbler index computation
2003-04-07 14:22:39 +04:00
* TODO : the ocurence test seems bogus for namespaced names
2001-11-26 18:58:08 +03:00
*/
tmp = cur - > prev ;
while ( tmp ! = NULL ) {
2002-09-18 03:04:40 +04:00
if ( ( tmp - > type = = XML_ELEMENT_NODE ) & &
( xmlStrEqual ( cur - > name , tmp - > name ) ) )
2001-11-26 18:58:08 +03:00
occur + + ;
tmp = tmp - > prev ;
}
if ( occur = = 0 ) {
tmp = cur - > next ;
2002-11-12 15:36:52 +03:00
while ( tmp ! = NULL & & occur = = 0 ) {
if ( ( tmp - > type = = XML_ELEMENT_NODE ) & &
( xmlStrEqual ( cur - > name , tmp - > name ) ) )
2001-11-26 18:58:08 +03:00
occur + + ;
tmp = tmp - > next ;
}
if ( occur ! = 0 )
occur = 1 ;
} else
occur + + ;
2002-11-12 15:36:52 +03:00
} else if ( cur - > type = = XML_COMMENT_NODE ) {
sep = " / " ;
name = " comment() " ;
next = cur - > parent ;
/*
* Thumbler index computation
*/
tmp = cur - > prev ;
while ( tmp ! = NULL ) {
if ( tmp - > type = = XML_COMMENT_NODE )
occur + + ;
tmp = tmp - > prev ;
}
if ( occur = = 0 ) {
tmp = cur - > next ;
while ( tmp ! = NULL & & occur = = 0 ) {
if ( tmp - > type = = XML_COMMENT_NODE )
occur + + ;
tmp = tmp - > next ;
}
if ( occur ! = 0 )
occur = 1 ;
} else
occur + + ;
} else if ( ( cur - > type = = XML_TEXT_NODE ) | |
( cur - > type = = XML_CDATA_SECTION_NODE ) ) {
sep = " / " ;
name = " text() " ;
next = cur - > parent ;
/*
* Thumbler index computation
*/
tmp = cur - > prev ;
while ( tmp ! = NULL ) {
if ( ( cur - > type = = XML_TEXT_NODE ) | |
( cur - > type = = XML_CDATA_SECTION_NODE ) )
occur + + ;
tmp = tmp - > prev ;
}
if ( occur = = 0 ) {
tmp = cur - > next ;
while ( tmp ! = NULL & & occur = = 0 ) {
2004-08-15 01:46:31 +04:00
if ( ( tmp - > type = = XML_TEXT_NODE ) | |
( tmp - > type = = XML_CDATA_SECTION_NODE ) )
2002-11-12 15:36:52 +03:00
occur + + ;
tmp = tmp - > next ;
}
if ( occur ! = 0 )
occur = 1 ;
} else
occur + + ;
} else if ( cur - > type = = XML_PI_NODE ) {
sep = " / " ;
snprintf ( nametemp , sizeof ( nametemp ) - 1 ,
" processing-instruction('%s') " , cur - > name ) ;
nametemp [ sizeof ( nametemp ) - 1 ] = 0 ;
name = nametemp ;
next = cur - > parent ;
/*
* Thumbler index computation
*/
tmp = cur - > prev ;
while ( tmp ! = NULL ) {
if ( ( tmp - > type = = XML_PI_NODE ) & &
( xmlStrEqual ( cur - > name , tmp - > name ) ) )
occur + + ;
tmp = tmp - > prev ;
}
if ( occur = = 0 ) {
tmp = cur - > next ;
while ( tmp ! = NULL & & occur = = 0 ) {
if ( ( tmp - > type = = XML_PI_NODE ) & &
( xmlStrEqual ( cur - > name , tmp - > name ) ) )
occur + + ;
tmp = tmp - > next ;
}
if ( occur ! = 0 )
occur = 1 ;
} else
occur + + ;
2001-11-26 18:58:08 +03:00
} else if ( cur - > type = = XML_ATTRIBUTE_NODE ) {
2002-10-08 12:26:11 +04:00
sep = " /@ " ;
2001-11-26 18:58:08 +03:00
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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " getting node path " ) ;
2001-11-26 18:58:08 +03:00
xmlFree ( buf ) ;
xmlFree ( buffer ) ;
return ( NULL ) ;
}
buffer = temp ;
temp = ( xmlChar * ) xmlRealloc ( buf , buf_len ) ;
if ( temp = = NULL ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " getting node path " ) ;
2001-11-26 18:58:08 +03:00
xmlFree ( buf ) ;
xmlFree ( buffer ) ;
return ( NULL ) ;
}
buf = temp ;
}
if ( occur = = 0 )
2002-10-08 12:26:11 +04:00
snprintf ( ( char * ) buf , buf_len , " %s%s%s " ,
2001-11-26 18:58:08 +03:00
sep , name , ( char * ) buffer ) ;
else
2002-10-08 12:26:11 +04:00
snprintf ( ( char * ) buf , buf_len , " %s%s[%d]%s " ,
2001-11-26 18:58:08 +03:00
sep , name , occur , ( char * ) buffer ) ;
snprintf ( ( char * ) buffer , buf_len , " %s " , buf ) ;
cur = next ;
} while ( cur ! = NULL ) ;
xmlFree ( buf ) ;
return ( buffer ) ;
}
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2001-11-26 18:58:08 +03:00
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 . . . ) .
*
2001-12-17 18:30:10 +03:00
* Returns the # xmlNodePtr for the root or NULL
2001-02-23 20:55:21 +03:00
*/
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 ) ;
}
2004-03-04 18:59:36 +03:00
# if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED)
2001-02-23 20:55:21 +03:00
/**
* 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 ) ;
2002-02-08 16:28:40 +03:00
if ( root = = NULL )
return ( NULL ) ;
xmlUnlinkNode ( root ) ;
root - > doc = doc ;
root - > parent = ( xmlNodePtr ) doc ;
2001-02-23 20:55:21 +03:00
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 ) ;
}
2004-03-04 18:59:36 +03:00
# endif
2001-02-23 20:55:21 +03:00
2004-03-04 18:59:36 +03:00
# if defined(LIBXML_TREE_ENABLED)
2001-02-23 20:55:21 +03:00
/**
* xmlNodeSetLang :
* @ cur : the node being changed
2001-12-17 18:30:10 +03:00
* @ lang : the language description
2001-02-23 20:55:21 +03:00
*
* Set the language of a node , i . e . the values of the xml : lang
* attribute .
*/
void
xmlNodeSetLang ( xmlNodePtr cur , const xmlChar * lang ) {
2002-01-17 11:46:58 +03:00
xmlNsPtr ns ;
2001-02-23 20:55:21 +03:00
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 ;
}
2002-01-17 11:46:58 +03:00
ns = xmlSearchNsByHref ( cur - > doc , cur , XML_XML_NAMESPACE ) ;
if ( ns = = NULL )
return ;
xmlSetNsProp ( cur , ns , BAD_CAST " lang " , lang ) ;
2001-02-23 20:55:21 +03:00
}
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2001-02-23 20:55:21 +03:00
/**
* 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
2002-09-26 02:25:35 +04:00
* It ' s up to the caller to free the memory with xmlFree ( ) .
2001-02-23 20:55:21 +03:00
*/
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 ) ;
}
2003-09-29 22:02:38 +04:00
# ifdef LIBXML_TREE_ENABLED
2001-02-23 20:55:21 +03:00
/**
* 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 ) {
2002-01-17 11:46:58 +03:00
xmlNsPtr ns ;
2001-02-23 20:55:21 +03:00
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 ;
}
2002-01-17 11:46:58 +03:00
ns = xmlSearchNsByHref ( cur - > doc , cur , XML_XML_NAMESPACE ) ;
if ( ns = = NULL )
return ;
2001-02-23 20:55:21 +03:00
switch ( val ) {
case 0 :
2002-01-17 11:46:58 +03:00
xmlSetNsProp ( cur , ns , BAD_CAST " space " , BAD_CAST " default " ) ;
2001-02-23 20:55:21 +03:00
break ;
case 1 :
2002-01-17 11:46:58 +03:00
xmlSetNsProp ( cur , ns , BAD_CAST " space " , BAD_CAST " preserve " ) ;
2001-02-23 20:55:21 +03:00
break ;
}
}
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2001-02-23 20:55:21 +03:00
/**
* 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 .
*
2001-12-17 18:30:10 +03:00
* Returns - 1 if xml : space is not inherited , 0 if " default " , 1 if " preserve "
2001-02-23 20:55:21 +03:00
*/
int
xmlNodeGetSpacePreserve ( xmlNodePtr cur ) {
xmlChar * space ;
while ( cur ! = NULL ) {
2002-01-17 11:46:58 +03:00
space = xmlGetNsProp ( cur , BAD_CAST " space " , XML_XML_NAMESPACE ) ;
2001-02-23 20:55:21 +03:00
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 ) ;
}
2003-09-29 22:02:38 +04:00
# ifdef LIBXML_TREE_ENABLED
2001-02-23 20:55:21 +03:00
/**
* 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 ) ;
}
2004-03-04 18:59:36 +03:00
# endif
2001-02-23 20:55:21 +03:00
2004-03-04 18:59:36 +03:00
# if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED)
2001-02-23 20:55:21 +03:00
/**
* 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
2003-09-22 14:24:45 +04:00
xmlNodeSetBase ( xmlNodePtr cur , const xmlChar * uri ) {
2002-01-17 11:46:58 +03:00
xmlNsPtr ns ;
2001-02-23 20:55:21 +03:00
if ( cur = = 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_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 :
return ;
case XML_ELEMENT_NODE :
case XML_ATTRIBUTE_NODE :
break ;
2002-05-05 10:57:27 +04:00
case XML_DOCUMENT_NODE :
# ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE :
# endif
case XML_HTML_DOCUMENT_NODE : {
xmlDocPtr doc = ( xmlDocPtr ) cur ;
if ( doc - > URL ! = NULL )
xmlFree ( ( xmlChar * ) doc - > URL ) ;
if ( uri = = NULL )
doc - > URL = NULL ;
else
doc - > URL = xmlStrdup ( uri ) ;
return ;
}
2001-02-23 20:55:21 +03:00
}
2002-01-17 11:46:58 +03:00
ns = xmlSearchNsByHref ( cur - > doc , cur , XML_XML_NAMESPACE ) ;
if ( ns = = NULL )
return ;
xmlSetNsProp ( cur , ns , BAD_CAST " base " , uri ) ;
2001-02-23 20:55:21 +03:00
}
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2001-02-23 20:55:21 +03:00
/**
* 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
2002-09-26 02:25:35 +04:00
* It ' s up to the caller to free the memory with xmlFree ( ) .
2001-02-23 20:55:21 +03:00
*/
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
}
2003-10-20 00:44:43 +04:00
/**
* xmlNodeBufGetContent :
* @ buffer : a buffer
* @ cur : the node being read
*
* Read the value of a node @ cur , 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 substituted .
* Fills up the buffer @ buffer with this value
*
* Returns 0 in case of success and - 1 in case of error .
*/
int
xmlNodeBufGetContent ( xmlBufferPtr buffer , xmlNodePtr cur )
{
if ( ( cur = = NULL ) | | ( buffer = = NULL ) ) return ( - 1 ) ;
switch ( cur - > type ) {
case XML_CDATA_SECTION_NODE :
case XML_TEXT_NODE :
xmlBufferCat ( buffer , cur - > content ) ;
break ;
case XML_DOCUMENT_FRAG_NODE :
case XML_ELEMENT_NODE : {
xmlNodePtr tmp = cur ;
while ( tmp ! = NULL ) {
switch ( tmp - > type ) {
case XML_CDATA_SECTION_NODE :
case XML_TEXT_NODE :
if ( tmp - > content ! = NULL )
xmlBufferCat ( buffer , tmp - > content ) ;
break ;
case XML_ENTITY_REF_NODE :
xmlNodeBufGetContent ( buffer , tmp - > children ) ;
break ;
default :
break ;
}
/*
* Skip to next node
*/
if ( tmp - > children ! = NULL ) {
if ( tmp - > children - > type ! = XML_ENTITY_DECL ) {
tmp = tmp - > children ;
continue ;
}
}
if ( tmp = = cur )
break ;
if ( tmp - > next ! = NULL ) {
tmp = tmp - > next ;
continue ;
}
do {
tmp = tmp - > parent ;
if ( tmp = = NULL )
break ;
if ( tmp = = cur ) {
tmp = NULL ;
break ;
}
if ( tmp - > next ! = NULL ) {
tmp = tmp - > next ;
break ;
}
} while ( tmp ! = NULL ) ;
}
break ;
}
case XML_ATTRIBUTE_NODE : {
xmlAttrPtr attr = ( xmlAttrPtr ) cur ;
xmlNodePtr tmp = attr - > children ;
while ( tmp ! = NULL ) {
if ( tmp - > type = = XML_TEXT_NODE )
xmlBufferCat ( buffer , tmp - > content ) ;
else
xmlNodeBufGetContent ( buffer , tmp ) ;
tmp = tmp - > next ;
}
break ;
}
case XML_COMMENT_NODE :
case XML_PI_NODE :
xmlBufferCat ( buffer , cur - > content ) ;
break ;
case XML_ENTITY_REF_NODE : {
xmlEntityPtr ent ;
xmlNodePtr tmp ;
/* lookup entity declaration */
ent = xmlGetDocEntity ( cur - > doc , cur - > name ) ;
if ( ent = = NULL )
return ( - 1 ) ;
/* an entity content can be any "well balanced chunk",
* i . e . the result of the content [ 43 ] production :
* http : //www.w3.org/TR/REC-xml#NT-content
* - > we iterate through child nodes and recursive call
* xmlNodeGetContent ( ) which handles all possible node types */
tmp = ent - > children ;
while ( tmp ) {
xmlNodeBufGetContent ( buffer , tmp ) ;
tmp = tmp - > next ;
}
break ;
}
case XML_ENTITY_NODE :
case XML_DOCUMENT_TYPE_NODE :
case XML_NOTATION_NODE :
case XML_DTD_NODE :
case XML_XINCLUDE_START :
case XML_XINCLUDE_END :
break ;
case XML_DOCUMENT_NODE :
# ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE :
# endif
case XML_HTML_DOCUMENT_NODE :
cur = cur - > children ;
while ( cur ! = NULL ) {
if ( ( cur - > type = = XML_ELEMENT_NODE ) | |
( cur - > type = = XML_TEXT_NODE ) | |
( cur - > type = = XML_CDATA_SECTION_NODE ) ) {
xmlNodeBufGetContent ( buffer , cur ) ;
}
cur = cur - > next ;
}
break ;
case XML_NAMESPACE_DECL :
xmlBufferCat ( buffer , ( ( xmlNsPtr ) cur ) - > href ) ;
break ;
case XML_ELEMENT_DECL :
case XML_ATTRIBUTE_DECL :
case XML_ENTITY_DECL :
break ;
}
return ( 0 ) ;
}
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 ) .
2001-12-17 18:30:10 +03:00
* Entity references are substituted .
* Returns a new # xmlChar * or NULL if no content is available .
2002-09-26 02:25:35 +04:00
* It ' s up to the caller to free the memory with xmlFree ( ) .
2001-02-23 20:55:21 +03:00
*/
xmlChar *
2002-04-20 10:41:40 +04:00
xmlNodeGetContent ( xmlNodePtr cur )
{
if ( cur = = NULL )
return ( NULL ) ;
2001-02-23 20:55:21 +03:00
switch ( cur - > type ) {
case XML_DOCUMENT_FRAG_NODE :
2002-04-20 10:41:40 +04:00
case XML_ELEMENT_NODE : {
xmlBufferPtr buffer ;
xmlChar * ret ;
2003-01-23 21:24:20 +03:00
buffer = xmlBufferCreateSize ( 64 ) ;
2002-04-20 10:41:40 +04:00
if ( buffer = = NULL )
return ( NULL ) ;
2003-10-20 01:47:14 +04:00
xmlNodeBufGetContent ( buffer , cur ) ;
2002-04-20 10:41:40 +04:00
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 ;
}
2001-02-23 20:55:21 +03:00
case XML_COMMENT_NODE :
case XML_PI_NODE :
2002-04-20 10:41:40 +04:00
if ( cur - > content ! = NULL )
return ( xmlStrdup ( cur - > content ) ) ;
return ( NULL ) ;
case XML_ENTITY_REF_NODE : {
xmlEntityPtr ent ;
xmlBufferPtr buffer ;
xmlChar * ret ;
/* lookup entity declaration */
ent = xmlGetDocEntity ( cur - > doc , cur - > name ) ;
if ( ent = = NULL )
return ( NULL ) ;
buffer = xmlBufferCreate ( ) ;
if ( buffer = = NULL )
return ( NULL ) ;
2003-10-20 01:47:14 +04:00
xmlNodeBufGetContent ( buffer , cur ) ;
2002-04-20 10:41:40 +04:00
ret = buffer - > content ;
buffer - > content = NULL ;
xmlBufferFree ( buffer ) ;
return ( ret ) ;
}
2001-02-23 20:55:21 +03:00
case XML_ENTITY_NODE :
case XML_DOCUMENT_TYPE_NODE :
case XML_NOTATION_NODE :
case XML_DTD_NODE :
2002-04-20 10:41:40 +04:00
case XML_XINCLUDE_START :
case XML_XINCLUDE_END :
2003-03-24 21:39:54 +03:00
return ( NULL ) ;
case XML_DOCUMENT_NODE :
2001-04-23 17:41:34 +04:00
# ifdef LIBXML_DOCB_ENABLED
2002-04-20 10:41:40 +04:00
case XML_DOCB_DOCUMENT_NODE :
2001-02-23 20:55:21 +03:00
# endif
2003-03-24 21:39:54 +03:00
case XML_HTML_DOCUMENT_NODE : {
2003-10-20 01:47:14 +04:00
xmlBufferPtr buffer ;
xmlChar * ret ;
2003-03-24 21:39:54 +03:00
2003-10-20 01:47:14 +04:00
buffer = xmlBufferCreate ( ) ;
if ( buffer = = NULL )
return ( NULL ) ;
xmlNodeBufGetContent ( buffer , ( xmlNodePtr ) cur ) ;
ret = buffer - > content ;
buffer - > content = NULL ;
xmlBufferFree ( buffer ) ;
return ( ret ) ;
2003-03-24 21:39:54 +03:00
}
2002-10-14 19:39:04 +04:00
case XML_NAMESPACE_DECL : {
xmlChar * tmp ;
tmp = xmlStrdup ( ( ( xmlNsPtr ) cur ) - > href ) ;
return ( tmp ) ;
}
2001-02-23 20:55:21 +03:00
case XML_ELEMENT_DECL :
2002-04-20 10:41:40 +04:00
/* TODO !!! */
return ( NULL ) ;
2001-02-23 20:55:21 +03:00
case XML_ATTRIBUTE_DECL :
2002-04-20 10:41:40 +04:00
/* TODO !!! */
return ( NULL ) ;
2001-02-23 20:55:21 +03:00
case XML_ENTITY_DECL :
2002-04-20 10:41:40 +04:00
/* TODO !!! */
return ( NULL ) ;
2001-02-23 20:55:21 +03:00
case XML_CDATA_SECTION_NODE :
case XML_TEXT_NODE :
2002-04-20 10:41:40 +04:00
if ( cur - > content ! = NULL )
return ( xmlStrdup ( cur - > content ) ) ;
return ( NULL ) ;
2001-02-23 20:55:21 +03:00
}
2002-04-20 10:41:40 +04:00
return ( NULL ) ;
2001-02-23 20:55:21 +03:00
}
2003-09-29 22:02:38 +04:00
2001-02-23 20:55:21 +03:00
/**
* 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 :
2002-01-16 18:37:50 +03:00
case XML_ATTRIBUTE_NODE :
2001-02-23 20:55:21 +03:00
if ( cur - > children ! = NULL ) xmlFreeNodeList ( cur - > children ) ;
cur - > children = xmlStringGetNodeList ( cur - > doc , content ) ;
UPDATE_LAST_CHILD_AND_PARENT ( cur )
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 ) {
2004-01-04 17:49:01 +03:00
if ( ! ( ( cur - > doc ! = NULL ) & & ( cur - > doc - > dict ! = NULL ) & &
xmlDictOwns ( cur - > doc - > dict , cur - > content ) ) )
xmlFree ( cur - > content ) ;
2001-02-23 20:55:21 +03:00
}
if ( cur - > children ! = NULL ) xmlFreeNodeList ( cur - > children ) ;
cur - > last = cur - > children = NULL ;
if ( content ! = NULL ) {
cur - > content = xmlStrdup ( content ) ;
} 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 ;
}
}
2003-09-29 22:02:38 +04:00
# ifdef LIBXML_TREE_ENABLED
2001-02-23 20:55:21 +03:00
/**
* 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 :
2002-01-16 18:37:50 +03:00
case XML_ATTRIBUTE_NODE :
2001-02-23 20:55:21 +03:00
if ( cur - > children ! = NULL ) xmlFreeNodeList ( cur - > children ) ;
cur - > children = xmlStringLenGetNodeList ( cur - > doc , content , len ) ;
UPDATE_LAST_CHILD_AND_PARENT ( cur )
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 ) {
xmlFree ( cur - > content ) ;
}
if ( cur - > children ! = NULL ) xmlFreeNodeList ( cur - > children ) ;
cur - > children = cur - > last = NULL ;
if ( content ! = NULL ) {
cur - > content = xmlStrndup ( content , len ) ;
} 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 ;
}
}
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2001-02-23 20:55:21 +03:00
/**
* 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 : {
2002-01-13 19:15:43 +03:00
xmlNodePtr last , newNode , tmp ;
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 ) {
2002-01-13 19:15:43 +03:00
tmp = xmlAddChild ( cur , newNode ) ;
if ( tmp ! = newNode )
return ;
2001-02-23 20:55:21 +03:00
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 ) {
2004-01-04 17:49:01 +03:00
if ( ( cur - > doc ! = NULL ) & & ( cur - > doc - > dict ! = NULL ) & &
xmlDictOwns ( cur - > doc - > dict , cur - > content ) ) {
cur - > content =
xmlStrncatNew ( cur - > content , content , len ) ;
break ;
}
2001-02-23 20:55:21 +03:00
cur - > content = xmlStrncat ( cur - > content , content , len ) ;
}
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 ) ;
xmlNodeAddContent ( first , second - > content ) ;
xmlUnlinkNode ( second ) ;
xmlFreeNode ( second ) ;
return ( first ) ;
}
2004-03-04 18:59:36 +03:00
# if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED)
2001-02-23 20:55:21 +03:00
/**
* xmlGetNsList :
* @ doc : the document
* @ node : the current node
*
* Search all the namespace applying to a given element .
2001-12-17 18:30:10 +03:00
* Returns an NULL terminated array of all the # xmlNsPtr found
2001-02-23 20:55:21 +03:00
* 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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " getting namespace list " ) ;
2001-06-30 01:31:07 +04:00
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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " getting namespace list " ) ;
2001-06-30 01:31:07 +04:00
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
}
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
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 ) {
2003-10-28 17:27:41 +03:00
2001-02-23 20:55:21 +03:00
xmlNsPtr cur ;
2003-10-28 17:27:41 +03:00
xmlNodePtr orig = node ;
2001-02-23 20:55:21 +03:00
if ( node = = NULL ) return ( NULL ) ;
if ( ( nameSpace ! = NULL ) & &
( xmlStrEqual ( nameSpace , ( const xmlChar * ) " xml " ) ) ) {
2002-08-01 16:22:24 +04:00
if ( ( doc = = NULL ) & & ( node - > type = = XML_ELEMENT_NODE ) ) {
/*
* The XML - 1.0 namespace is normally held on the root
* element . In this case exceptionally create it on the
* node element .
*/
cur = ( xmlNsPtr ) xmlMalloc ( sizeof ( xmlNs ) ) ;
if ( cur = = NULL ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " searching namespace " ) ;
2002-08-01 16:22:24 +04:00
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlNs ) ) ;
cur - > type = XML_LOCAL_NAMESPACE ;
cur - > href = xmlStrdup ( XML_XML_NAMESPACE ) ;
cur - > prefix = xmlStrdup ( ( const xmlChar * ) " xml " ) ;
cur - > next = node - > nsDef ;
node - > nsDef = cur ;
return ( cur ) ;
}
2001-02-23 20:55:21 +03:00
if ( doc - > oldNs = = NULL ) {
/*
* Allocate a new Namespace and fill the fields .
*/
doc - > oldNs = ( xmlNsPtr ) xmlMalloc ( sizeof ( xmlNs ) ) ;
if ( doc - > oldNs = = NULL ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " searching namespace " ) ;
2001-02-23 20:55:21 +03:00
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 ;
}
2003-10-28 17:27:41 +03:00
if ( orig ! = node ) {
cur = node - > ns ;
if ( 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 ) ;
}
}
2001-02-23 20:55:21 +03:00
}
node = node - > parent ;
}
return ( NULL ) ;
}
2003-09-12 13:44:56 +04:00
/**
* xmlNsInScope :
* @ doc : the document
* @ node : the current node
* @ ancestor : the ancestor carrying the namespace
* @ prefix : the namespace prefix
*
* Verify that the given namespace held on @ ancestor is still in scope
* on node .
*
* Returns 1 if true , 0 if false and - 1 in case of error .
*/
static int
2003-09-14 23:56:14 +04:00
xmlNsInScope ( xmlDocPtr doc ATTRIBUTE_UNUSED , xmlNodePtr node ,
xmlNodePtr ancestor , const xmlChar * prefix )
2003-09-12 13:44:56 +04:00
{
xmlNsPtr tst ;
while ( ( node ! = NULL ) & & ( node ! = ancestor ) ) {
if ( ( node - > type = = XML_ENTITY_REF_NODE ) | |
( node - > type = = XML_ENTITY_NODE ) | |
( node - > type = = XML_ENTITY_DECL ) )
return ( - 1 ) ;
if ( node - > type = = XML_ELEMENT_NODE ) {
tst = node - > nsDef ;
while ( tst ! = NULL ) {
if ( ( tst - > prefix = = NULL )
& & ( prefix = = NULL ) )
return ( 0 ) ;
if ( ( tst - > prefix ! = NULL )
& & ( prefix ! = NULL )
& & ( xmlStrEqual ( tst - > prefix , prefix ) ) )
return ( 0 ) ;
tst = tst - > next ;
}
}
node = node - > parent ;
}
if ( node ! = ancestor )
return ( - 1 ) ;
return ( 1 ) ;
}
2001-02-23 20:55:21 +03:00
/**
* 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
2003-09-12 13:44:56 +04:00
xmlSearchNsByHref ( xmlDocPtr doc , xmlNodePtr node , const xmlChar * href )
{
2001-02-23 20:55:21 +03:00
xmlNsPtr cur ;
xmlNodePtr orig = node ;
2004-05-17 07:17:26 +04:00
int is_attr ;
2001-02-23 20:55:21 +03:00
2003-09-12 13:44:56 +04:00
if ( ( node = = NULL ) | | ( href = = NULL ) )
return ( NULL ) ;
2001-02-23 20:55:21 +03:00
if ( xmlStrEqual ( href , XML_XML_NAMESPACE ) ) {
2003-09-12 13:44:56 +04:00
/*
* Only the document can hold the XML spec namespace .
*/
if ( ( doc = = NULL ) & & ( node - > type = = XML_ELEMENT_NODE ) ) {
/*
* The XML - 1.0 namespace is normally held on the root
* element . In this case exceptionally create it on the
* node element .
*/
cur = ( xmlNsPtr ) xmlMalloc ( sizeof ( xmlNs ) ) ;
if ( cur = = NULL ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " searching namespace " ) ;
2003-09-12 13:44:56 +04:00
return ( NULL ) ;
}
memset ( cur , 0 , sizeof ( xmlNs ) ) ;
cur - > type = XML_LOCAL_NAMESPACE ;
cur - > href = xmlStrdup ( XML_XML_NAMESPACE ) ;
cur - > prefix = xmlStrdup ( ( const xmlChar * ) " xml " ) ;
cur - > next = node - > nsDef ;
node - > nsDef = cur ;
return ( cur ) ;
}
if ( doc - > oldNs = = NULL ) {
/*
* Allocate a new Namespace and fill the fields .
*/
doc - > oldNs = ( xmlNsPtr ) xmlMalloc ( sizeof ( xmlNs ) ) ;
if ( doc - > oldNs = = NULL ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " searching namespace " ) ;
2003-09-12 13:44:56 +04:00
return ( NULL ) ;
}
memset ( doc - > oldNs , 0 , sizeof ( xmlNs ) ) ;
doc - > oldNs - > type = XML_LOCAL_NAMESPACE ;
2001-02-23 20:55:21 +03:00
2003-09-12 13:44:56 +04:00
doc - > oldNs - > href = xmlStrdup ( XML_XML_NAMESPACE ) ;
doc - > oldNs - > prefix = xmlStrdup ( ( const xmlChar * ) " xml " ) ;
}
return ( doc - > oldNs ) ;
2001-02-23 20:55:21 +03:00
}
2004-05-17 07:17:26 +04:00
is_attr = ( node - > type = = XML_ATTRIBUTE_NODE ) ;
2001-02-23 20:55:21 +03:00
while ( node ! = NULL ) {
2003-09-12 13:44:56 +04:00
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 - > href ! = NULL ) & & ( href ! = NULL ) & &
( xmlStrEqual ( cur - > href , href ) ) ) {
2004-05-17 07:17:26 +04:00
if ( ( ( ! is_attr ) | | ( cur - > prefix ! = NULL ) ) & &
( xmlNsInScope ( doc , orig , node , cur - > href ) = = 1 ) )
2003-09-12 13:44:56 +04:00
return ( cur ) ;
}
cur = cur - > next ;
}
2003-10-28 17:27:41 +03:00
if ( orig ! = node ) {
cur = node - > ns ;
if ( cur ! = NULL ) {
if ( ( cur - > href ! = NULL ) & & ( href ! = NULL ) & &
( xmlStrEqual ( cur - > href , href ) ) ) {
2004-05-17 07:17:26 +04:00
if ( ( ( ! is_attr ) | | ( cur - > prefix ! = NULL ) ) & &
( xmlNsInScope ( doc , orig , node , cur - > href ) = = 1 ) )
2003-10-28 17:27:41 +03:00
return ( cur ) ;
}
2003-09-12 13:44:56 +04:00
}
2003-10-28 17:27:41 +03:00
}
2003-09-12 13:44:56 +04:00
}
node = node - > parent ;
2001-02-23 20:55:21 +03:00
}
2003-09-12 13:44:56 +04:00
return ( NULL ) ;
2001-02-23 20:55:21 +03:00
}
/**
2002-12-10 18:19:08 +03:00
* xmlNewReconciliedNs :
2001-02-23 20:55:21 +03:00
* @ 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 !
*/
2002-03-07 03:05:35 +03:00
if ( ns - > prefix = = NULL )
2002-06-14 21:07:10 +04:00
snprintf ( ( char * ) prefix , sizeof ( prefix ) , " default " ) ;
2002-03-07 03:05:35 +03:00
else
2002-06-14 21:07:10 +04:00
snprintf ( ( char * ) prefix , sizeof ( prefix ) , " %.20s " , ns - > prefix ) ;
2002-03-07 03:05:35 +03:00
2001-02-23 20:55:21 +03:00
def = xmlSearchNs ( doc , tree , prefix ) ;
while ( def ! = NULL ) {
if ( counter > 1000 ) return ( NULL ) ;
2002-03-07 03:05:35 +03:00
if ( ns - > prefix = = NULL )
2002-06-14 21:07:10 +04:00
snprintf ( ( char * ) prefix , sizeof ( prefix ) , " default%d " , counter + + ) ;
2002-03-07 03:05:35 +03:00
else
2002-06-14 21:07:10 +04:00
snprintf ( ( char * ) prefix , sizeof ( prefix ) , " %.20s%d " , ns - > prefix , counter + + ) ;
2001-02-23 20:55:21 +03:00
def = xmlSearchNs ( doc , tree , prefix ) ;
}
/*
2001-12-17 18:30:10 +03:00
* OK , now we are ready to create a new one .
2001-02-23 20:55:21 +03:00
*/
def = xmlNewNs ( tree , ns - > href , prefix ) ;
return ( def ) ;
}
2003-09-29 22:02:38 +04:00
# ifdef LIBXML_TREE_ENABLED
2001-02-23 20:55:21 +03:00
/**
2002-12-10 18:19:08 +03:00
* xmlReconciliateNs :
2001-02-23 20:55:21 +03:00
* @ 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
2001-12-17 18:30:10 +03:00
* as possible the function try to reuse the existing namespaces found in
2001-02-23 20:55:21 +03:00
* 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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " fixing namespaces " ) ;
2001-02-23 20:55:21 +03:00
return ( - 1 ) ;
}
newNs = ( xmlNsPtr * ) xmlMalloc ( sizeCache *
sizeof ( xmlNsPtr ) ) ;
if ( newNs = = NULL ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " fixing namespaces " ) ;
2001-02-23 20:55:21 +03:00
xmlFree ( oldNs ) ;
return ( - 1 ) ;
}
}
for ( i = 0 ; i < nbCache ; i + + ) {
if ( oldNs [ i ] = = node - > ns ) {
node - > ns = newNs [ i ] ;
break ;
}
}
if ( i = = nbCache ) {
/*
2001-12-17 18:30:10 +03:00
* OK we need to recreate a new namespace definition
2001-02-23 20:55:21 +03:00
*/
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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " fixing namespaces " ) ;
2001-02-23 20:55:21 +03:00
xmlFree ( newNs ) ;
return ( - 1 ) ;
}
newNs = ( xmlNsPtr * ) xmlRealloc ( newNs , sizeCache *
sizeof ( xmlNsPtr ) ) ;
if ( newNs = = NULL ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " fixing namespaces " ) ;
2001-02-23 20:55:21 +03:00
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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " fixing namespaces " ) ;
2001-02-23 20:55:21 +03:00
return ( - 1 ) ;
}
newNs = ( xmlNsPtr * ) xmlMalloc ( sizeCache *
sizeof ( xmlNsPtr ) ) ;
if ( newNs = = NULL ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " fixing namespaces " ) ;
2001-02-23 20:55:21 +03:00
xmlFree ( oldNs ) ;
return ( - 1 ) ;
}
}
for ( i = 0 ; i < nbCache ; i + + ) {
if ( oldNs [ i ] = = attr - > ns ) {
2002-10-28 22:01:59 +03:00
attr - > ns = newNs [ i ] ;
2001-02-23 20:55:21 +03:00
break ;
}
}
if ( i = = nbCache ) {
/*
2001-12-17 18:30:10 +03:00
* OK we need to recreate a new namespace definition
2001-02-23 20:55:21 +03:00
*/
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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " fixing namespaces " ) ;
2001-02-23 20:55:21 +03:00
xmlFree ( newNs ) ;
return ( - 1 ) ;
}
newNs = ( xmlNsPtr * ) xmlRealloc ( newNs , sizeCache *
sizeof ( xmlNsPtr ) ) ;
if ( newNs = = NULL ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " fixing namespaces " ) ;
2001-02-23 20:55:21 +03:00
xmlFree ( oldNs ) ;
return ( - 1 ) ;
}
}
newNs [ nbCache ] = n ;
oldNs [ nbCache + + ] = attr - > ns ;
attr - > ns = n ;
}
}
}
attr = attr - > next ;
}
/*
* Browse the full subtree , deep first
*/
2004-07-30 16:02:58 +04:00
if ( node - > children ! = NULL & & node - > type ! = XML_ENTITY_REF_NODE ) {
2001-02-23 20:55:21 +03:00
/* 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 ;
2002-03-06 20:35:40 +03:00
} else
break ;
2001-02-23 20:55:21 +03:00
}
2002-03-07 03:05:35 +03:00
if ( oldNs ! = NULL )
xmlFree ( oldNs ) ;
if ( newNs ! = NULL )
xmlFree ( newNs ) ;
2001-02-23 20:55:21 +03:00
return ( ret ) ;
}
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2001-02-23 20:55:21 +03:00
/**
* 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 ) ;
2003-07-07 18:42:44 +04:00
if ( ( attrDecl ! = NULL ) & & ( attrDecl - > defaultValue ! = NULL ) )
/* return attribute declaration only if a default value is given
( that includes # FIXED declarations ) */
2001-02-23 20:55:21 +03:00
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 ;
2003-09-29 22:02:38 +04:00
# ifdef LIBXML_TREE_ENABLED
2001-06-06 14:46:28 +04:00
xmlDocPtr doc ;
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2001-06-06 14:46:28 +04:00
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
*/
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 ) ;
2003-09-29 22:02:38 +04:00
# ifdef LIBXML_TREE_ENABLED
2001-06-06 14:46:28 +04:00
/*
* Check if there is a default declaration in the internal
* or external subsets
*/
doc = node - > doc ;
if ( doc ! = NULL ) {
if ( doc - > intSubset ! = NULL ) {
2002-03-08 01:21:56 +03:00
xmlAttributePtr attrDecl = NULL ;
xmlNsPtr * nsList , * cur ;
xmlChar * ename ;
2001-06-06 14:46:28 +04:00
2002-03-08 01:21:56 +03:00
nsList = xmlGetNsList ( node - > doc , node ) ;
if ( nsList = = NULL )
return ( NULL ) ;
if ( ( node - > ns ! = NULL ) & & ( node - > ns - > prefix ! = NULL ) ) {
ename = xmlStrdup ( node - > ns - > prefix ) ;
ename = xmlStrcat ( ename , BAD_CAST " : " ) ;
ename = xmlStrcat ( ename , node - > name ) ;
} else {
ename = xmlStrdup ( node - > name ) ;
}
if ( ename = = NULL ) {
xmlFree ( nsList ) ;
return ( NULL ) ;
}
cur = nsList ;
while ( * cur ! = NULL ) {
if ( xmlStrEqual ( ( * cur ) - > href , nameSpace ) ) {
attrDecl = xmlGetDtdQAttrDesc ( doc - > intSubset , ename ,
name , ( * cur ) - > prefix ) ;
if ( ( attrDecl = = NULL ) & & ( doc - > extSubset ! = NULL ) )
attrDecl = xmlGetDtdQAttrDesc ( doc - > extSubset , ename ,
name , ( * cur ) - > prefix ) ;
}
cur + + ;
2001-06-06 14:46:28 +04:00
}
2002-03-08 01:21:56 +03:00
xmlFree ( nsList ) ;
xmlFree ( ename ) ;
return ( ( xmlAttrPtr ) attrDecl ) ;
2001-06-06 14:46:28 +04:00
}
}
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2001-06-06 14:46:28 +04:00
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 .
2003-02-16 18:50:27 +03:00
* NOTE : this function acts independently of namespaces associated
2003-02-05 16:19:53 +03:00
* to the attribute . Use xmlGetNsProp ( ) or xmlGetNoNsProp ( )
* for namespace aware processing .
2001-02-23 20:55:21 +03:00
*
* Returns the attribute value or NULL if not found .
2002-09-26 02:25:35 +04:00
* It ' s up to the caller to free the memory with xmlFree ( ) .
2001-02-23 20:55:21 +03:00
*/
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 ) ;
2003-07-07 18:42:44 +04:00
if ( ( attrDecl ! = NULL ) & & ( attrDecl - > defaultValue ! = NULL ) )
/* return attribute declaration only if a default value is given
( that includes # FIXED declarations ) */
2001-02-23 20:55:21 +03:00
return ( xmlStrdup ( attrDecl - > defaultValue ) ) ;
}
}
return ( NULL ) ;
}
2003-02-05 16:19:53 +03:00
/**
* xmlGetNoNsProp :
* @ 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 .
* This function is similar to xmlGetProp except it will accept only
* an attribute in no namespace .
*
* Returns the attribute value or NULL if not found .
* It ' s up to the caller to free the memory with xmlFree ( ) .
*/
xmlChar *
xmlGetNoNsProp ( 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 ( ( prop - > ns = = NULL ) & & ( 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 ) ;
2003-07-07 18:42:44 +04:00
if ( ( attrDecl ! = NULL ) & & ( attrDecl - > defaultValue ! = NULL ) )
/* return attribute declaration only if a default value is given
( that includes # FIXED declarations ) */
2003-02-05 16:19:53 +03:00
return ( xmlStrdup ( attrDecl - > defaultValue ) ) ;
}
}
return ( NULL ) ;
}
2001-02-23 20:55:21 +03:00
/**
* 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 .
2002-09-26 02:25:35 +04:00
* It ' s up to the caller to free the memory with xmlFree ( ) .
2001-02-23 20:55:21 +03:00
*/
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 )
2003-02-05 16:19:53 +03:00
return ( xmlGetNoNsProp ( node , name ) ) ;
2001-02-23 20:55:21 +03:00
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 ) ;
}
2004-03-04 18:59:36 +03:00
# if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
/**
* 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 , prev = NULL ; ;
if ( ( node = = NULL ) | | ( name = = NULL ) )
return ( - 1 ) ;
prop = node - > properties ;
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 ) ;
}
/**
* 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 ) & & ( 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 ) ;
}
# endif
# if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_HTML_ENABLED)
2001-02-23 20:55:21 +03:00
/**
* 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
2003-02-24 20:17:58 +03:00
if ( ( node = = NULL ) | | ( name = = NULL ) | | ( node - > type ! = XML_ELEMENT_NODE ) )
2001-02-23 20:55:21 +03:00
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 ) ;
}
/**
* 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
*/
if ( ( xmlStrEqual ( prop - > name , name ) ) & &
2002-08-01 16:52:24 +04:00
( prop - > ns ! = NULL ) & & ( xmlStrEqual ( prop - > ns - > href , ns - > href ) ) ) {
2001-02-23 20:55:21 +03:00
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 ) ;
}
2003-09-29 22:02:38 +04:00
# endif /* LIBXML_TREE_ENABLED */
2001-05-11 21:41:21 +04:00
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 ) ;
cur = node - > content ;
while ( * cur ! = 0 ) {
2003-10-18 20:20:14 +04:00
if ( ! IS_BLANK_CH ( * cur ) ) return ( 0 ) ;
2001-02-23 20:55:21 +03:00
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
2003-04-24 20:06:47 +04:00
*
* Returns - 1 in case of error , 0 otherwise
2001-02-23 20:55:21 +03:00
*/
2003-04-24 20:06:47 +04:00
int
2001-02-23 20:55:21 +03:00
xmlTextConcat ( xmlNodePtr node , const xmlChar * content , int len ) {
2003-04-24 20:06:47 +04:00
if ( node = = NULL ) return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
if ( ( node - > type ! = XML_TEXT_NODE ) & &
( node - > type ! = XML_CDATA_SECTION_NODE ) ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
2001-12-17 18:30:10 +03:00
" xmlTextConcat: node is not text nor CDATA \n " ) ;
2001-02-23 20:55:21 +03:00
# endif
2003-04-24 20:06:47 +04:00
return ( - 1 ) ;
2001-02-23 20:55:21 +03:00
}
2004-01-04 17:49:01 +03:00
/* need to check if content is currently in the dictionary */
if ( ( node - > doc ! = NULL ) & & ( node - > doc - > dict ! = NULL ) & &
xmlDictOwns ( node - > doc - > dict , node - > content ) ) {
node - > content = xmlStrncatNew ( node - > content , content , len ) ;
} else {
node - > content = xmlStrncat ( node - > content , content , len ) ;
}
2003-04-24 20:06:47 +04:00
if ( node - > content = = NULL )
return ( - 1 ) ;
return ( 0 ) ;
2001-02-23 20:55:21 +03:00
}
/************************************************************************
* *
* 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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " creating buffer " ) ;
2001-02-23 20:55:21 +03:00
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 ;
2003-04-19 04:07:51 +04:00
ret - > content = ( xmlChar * ) xmlMallocAtomic ( ret - > size * sizeof ( xmlChar ) ) ;
2001-02-23 20:55:21 +03:00
if ( ret - > content = = NULL ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " creating buffer " ) ;
2001-02-23 20:55:21 +03:00
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 ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " creating buffer " ) ;
2001-02-23 20:55:21 +03:00
return ( NULL ) ;
}
ret - > use = 0 ;
ret - > alloc = xmlBufferAllocScheme ;
ret - > size = ( size ? size + 2 : 0 ) ; /* +1 for ending null */
if ( ret - > size ) {
2003-04-19 04:07:51 +04:00
ret - > content = ( xmlChar * ) xmlMallocAtomic ( ret - > size * sizeof ( xmlChar ) ) ;
2001-02-23 20:55:21 +03:00
if ( ret - > content = = NULL ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " creating buffer " ) ;
2001-02-23 20:55:21 +03:00
xmlFree ( ret ) ;
return ( NULL ) ;
}
ret - > content [ 0 ] = 0 ;
} else
ret - > content = NULL ;
return ( ret ) ;
}
2003-09-18 17:35:51 +04:00
/**
* xmlBufferCreateStatic :
* @ mem : the memory area
* @ size : the size in byte
*
2003-12-19 06:13:47 +03:00
* routine to create an XML buffer from an immutable memory area .
* The area won ' t be modified nor copied , and is expected to be
2003-09-18 17:35:51 +04:00
* present until the end of the buffer lifetime .
*
* returns the new structure .
*/
xmlBufferPtr
xmlBufferCreateStatic ( void * mem , size_t size ) {
xmlBufferPtr ret ;
if ( ( mem = = NULL ) | | ( size = = 0 ) )
return ( NULL ) ;
ret = ( xmlBufferPtr ) xmlMalloc ( sizeof ( xmlBuffer ) ) ;
if ( ret = = NULL ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " creating buffer " ) ;
2003-09-18 17:35:51 +04:00
return ( NULL ) ;
}
ret - > use = size ;
ret - > size = size ;
ret - > alloc = XML_BUFFER_ALLOC_IMMUTABLE ;
ret - > content = ( xmlChar * ) mem ;
return ( ret ) ;
}
2001-02-23 20:55:21 +03:00
/**
* xmlBufferSetAllocationScheme :
2002-09-26 02:25:35 +04:00
* @ buf : the buffer to tune
2001-02-23 20:55:21 +03:00
* @ 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 ;
}
2003-09-18 17:35:51 +04:00
if ( buf - > alloc = = XML_BUFFER_ALLOC_IMMUTABLE ) return ;
2001-02-23 20:55:21 +03:00
buf - > alloc = scheme ;
}
/**
* xmlBufferFree :
* @ buf : the buffer to free
*
2002-01-22 21:15:52 +03:00
* Frees an XML buffer . It frees both the content and the structure which
* encapsulate it .
2001-02-23 20:55:21 +03:00
*/
void
xmlBufferFree ( xmlBufferPtr buf ) {
if ( buf = = NULL ) {
# ifdef DEBUG_BUFFER
xmlGenericError ( xmlGenericErrorContext ,
" xmlBufferFree: buf == NULL \n " ) ;
# endif
return ;
}
2003-09-18 17:35:51 +04:00
if ( ( buf - > content ! = NULL ) & &
( buf - > alloc ! = XML_BUFFER_ALLOC_IMMUTABLE ) ) {
2001-02-23 20:55:21 +03:00
xmlFree ( buf - > content ) ;
}
xmlFree ( buf ) ;
}
/**
* xmlBufferEmpty :
* @ buf : the buffer
*
* empty a buffer .
*/
void
xmlBufferEmpty ( xmlBufferPtr buf ) {
if ( buf - > content = = NULL ) return ;
buf - > use = 0 ;
2003-09-18 17:35:51 +04:00
if ( buf - > alloc = = XML_BUFFER_ALLOC_IMMUTABLE ) {
2003-09-24 01:50:54 +04:00
buf - > content = BAD_CAST " " ;
2003-09-18 17:35:51 +04:00
} else {
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 .
*
2001-12-17 18:30:10 +03:00
* Returns the number of # xmlChar removed , or - 1 in case of failure .
2001-02-23 20:55:21 +03:00
*/
int
xmlBufferShrink ( xmlBufferPtr buf , unsigned int len ) {
if ( len = = 0 ) return ( 0 ) ;
if ( len > buf - > use ) return ( - 1 ) ;
buf - > use - = len ;
2003-09-18 17:35:51 +04:00
if ( buf - > alloc = = XML_BUFFER_ALLOC_IMMUTABLE ) {
buf - > content + = len ;
} else {
memmove ( buf - > content , & buf - > content [ len ] , buf - > use * sizeof ( xmlChar ) ) ;
buf - > content [ buf - > use ] = 0 ;
}
2001-02-23 20:55:21 +03:00
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 ;
2003-09-18 17:35:51 +04:00
if ( buf - > alloc = = XML_BUFFER_ALLOC_IMMUTABLE ) return ( 0 ) ;
2001-02-23 20:55:21 +03:00
if ( len + buf - > use < buf - > size ) return ( 0 ) ;
2004-07-26 22:00:58 +04:00
/*
* Windows has a BIG problem on realloc timing , so we try to double
* the buffer size ( if that ' s enough ) ( bug 146697 )
*/
# ifdef WIN32
if ( buf - > size > len )
size = buf - > size * 2 ;
else
size = buf - > use + len + 100 ;
# else
2001-02-23 20:55:21 +03:00
size = buf - > use + len + 100 ;
2004-07-26 22:00:58 +04:00
# endif
2001-02-23 20:55:21 +03:00
newbuf = ( xmlChar * ) xmlRealloc ( buf - > content , size ) ;
2003-10-08 03:16:40 +04:00
if ( newbuf = = NULL ) {
xmlTreeErrMemory ( " growing buffer " ) ;
return ( - 1 ) ;
}
2001-02-23 20:55:21 +03:00
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 * .
2001-12-17 18:30:10 +03:00
* Returns the number of # xmlChar written
2001-02-23 20:55:21 +03:00
*/
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
*
2001-12-17 18:30:10 +03:00
* Resize a buffer to accommodate minimum size of @ size .
2001-02-23 20:55:21 +03:00
*
* Returns 0 in case of problems , 1 otherwise
*/
int
xmlBufferResize ( xmlBufferPtr buf , unsigned int size )
{
unsigned int newSize ;
xmlChar * rebuf = NULL ;
2003-09-18 17:35:51 +04:00
if ( buf - > alloc = = XML_BUFFER_ALLOC_IMMUTABLE ) return ( 0 ) ;
2001-02-23 20:55:21 +03:00
/* 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 :
2004-04-21 02:20:59 +04:00
/*take care of empty case*/
newSize = ( buf - > size ? buf - > size * 2 : size + 10 ) ;
2001-02-23 20:55:21 +03:00
while ( size > newSize ) newSize * = 2 ;
break ;
case XML_BUFFER_ALLOC_EXACT :
newSize = size + 10 ;
break ;
default :
newSize = size + 10 ;
break ;
}
if ( buf - > content = = NULL )
2003-04-19 04:07:51 +04:00
rebuf = ( xmlChar * ) xmlMallocAtomic ( newSize * sizeof ( xmlChar ) ) ;
2003-08-19 19:01:28 +04:00
else if ( buf - > size - buf - > use < 100 ) {
2001-02-23 20:55:21 +03:00
rebuf = ( xmlChar * ) xmlRealloc ( buf - > content ,
newSize * sizeof ( xmlChar ) ) ;
2003-08-19 19:01:28 +04:00
} else {
/*
* if we are reallocating a buffer far from being full , it ' s
* better to make a new allocation and copy only the used range
* and free the old one .
*/
rebuf = ( xmlChar * ) xmlMallocAtomic ( newSize * sizeof ( xmlChar ) ) ;
if ( rebuf ! = NULL ) {
memcpy ( rebuf , buf - > content , buf - > use ) ;
xmlFree ( buf - > content ) ;
2004-07-29 11:07:16 +04:00
rebuf [ buf - > use ] = 0 ;
2003-08-19 19:01:28 +04:00
}
}
2001-02-23 20:55:21 +03:00
if ( rebuf = = NULL ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " growing buffer " ) ;
2001-02-23 20:55:21 +03:00
return 0 ;
}
buf - > content = rebuf ;
buf - > size = newSize ;
return 1 ;
}
/**
* xmlBufferAdd :
* @ buf : the buffer to dump
2001-12-17 18:30:10 +03:00
* @ str : the # xmlChar string
* @ len : the number of # xmlChar to add
2001-02-23 20:55:21 +03:00
*
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 .
2004-07-31 20:24:01 +04:00
*
* Returns 0 successful , a positive error code number otherwise
* and - 1 in case of internal or API error .
2001-02-23 20:55:21 +03:00
*/
2004-07-31 20:24:01 +04:00
int
2001-02-23 20:55:21 +03:00
xmlBufferAdd ( xmlBufferPtr buf , const xmlChar * str , int len ) {
unsigned int needSize ;
if ( str = = NULL ) {
# ifdef DEBUG_BUFFER
xmlGenericError ( xmlGenericErrorContext ,
" xmlBufferAdd: str == NULL \n " ) ;
# endif
2004-07-31 20:24:01 +04:00
return - 1 ;
2001-02-23 20:55:21 +03:00
}
2004-07-31 20:24:01 +04:00
if ( buf - > alloc = = XML_BUFFER_ALLOC_IMMUTABLE ) return - 1 ;
2001-02-23 20:55:21 +03:00
if ( len < - 1 ) {
# ifdef DEBUG_BUFFER
xmlGenericError ( xmlGenericErrorContext ,
" xmlBufferAdd: len < 0 \n " ) ;
# endif
2004-07-31 20:24:01 +04:00
return - 1 ;
2001-02-23 20:55:21 +03:00
}
2004-07-31 20:24:01 +04:00
if ( len = = 0 ) return 0 ;
2001-02-23 20:55:21 +03:00
if ( len < 0 )
len = xmlStrlen ( str ) ;
2004-07-31 20:24:01 +04:00
if ( len < = 0 ) return - 1 ;
2001-02-23 20:55:21 +03:00
needSize = buf - > use + len + 2 ;
if ( needSize > buf - > size ) {
if ( ! xmlBufferResize ( buf , needSize ) ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " growing buffer " ) ;
2004-07-31 20:24:01 +04:00
return XML_ERR_NO_MEMORY ;
2001-02-23 20:55:21 +03:00
}
}
memmove ( & buf - > content [ buf - > use ] , str , len * sizeof ( xmlChar ) ) ;
buf - > use + = len ;
buf - > content [ buf - > use ] = 0 ;
2004-07-31 20:24:01 +04:00
return 0 ;
2001-02-23 20:55:21 +03:00
}
/**
* xmlBufferAddHead :
* @ buf : the buffer
2001-12-17 18:30:10 +03:00
* @ str : the # xmlChar string
* @ len : the number of # xmlChar to add
2001-02-23 20:55:21 +03:00
*
* 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 .
2004-07-31 20:24:01 +04:00
*
* Returns 0 successful , a positive error code number otherwise
* and - 1 in case of internal or API error .
2001-02-23 20:55:21 +03:00
*/
2004-07-31 20:24:01 +04:00
int
2001-02-23 20:55:21 +03:00
xmlBufferAddHead ( xmlBufferPtr buf , const xmlChar * str , int len ) {
unsigned int needSize ;
2004-07-31 20:24:01 +04:00
if ( buf - > alloc = = XML_BUFFER_ALLOC_IMMUTABLE ) return - 1 ;
2001-02-23 20:55:21 +03:00
if ( str = = NULL ) {
# ifdef DEBUG_BUFFER
xmlGenericError ( xmlGenericErrorContext ,
2001-12-17 18:30:10 +03:00
" xmlBufferAddHead: str == NULL \n " ) ;
2001-02-23 20:55:21 +03:00
# endif
2004-07-31 20:24:01 +04:00
return - 1 ;
2001-02-23 20:55:21 +03:00
}
if ( len < - 1 ) {
# ifdef DEBUG_BUFFER
xmlGenericError ( xmlGenericErrorContext ,
2001-12-17 18:30:10 +03:00
" xmlBufferAddHead: len < 0 \n " ) ;
2001-02-23 20:55:21 +03:00
# endif
2004-07-31 20:24:01 +04:00
return - 1 ;
2001-02-23 20:55:21 +03:00
}
2004-07-31 20:24:01 +04:00
if ( len = = 0 ) return 0 ;
2001-02-23 20:55:21 +03:00
if ( len < 0 )
len = xmlStrlen ( str ) ;
2004-07-31 20:24:01 +04:00
if ( len < = 0 ) return - 1 ;
2001-02-23 20:55:21 +03:00
needSize = buf - > use + len + 2 ;
if ( needSize > buf - > size ) {
if ( ! xmlBufferResize ( buf , needSize ) ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " growing buffer " ) ;
2004-07-31 20:24:01 +04:00
return XML_ERR_NO_MEMORY ;
2001-02-23 20:55:21 +03:00
}
}
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 ;
2004-07-31 20:24:01 +04:00
return 0 ;
2001-02-23 20:55:21 +03:00
}
/**
* xmlBufferCat :
2004-07-31 20:24:01 +04:00
* @ buf : the buffer to add to
2001-12-17 18:30:10 +03:00
* @ str : the # xmlChar string
2001-02-23 20:55:21 +03:00
*
* Append a zero terminated string to an XML buffer .
2004-07-31 20:24:01 +04:00
*
* Returns 0 successful , a positive error code number otherwise
* and - 1 in case of internal or API error .
2001-02-23 20:55:21 +03:00
*/
2004-07-31 20:24:01 +04:00
int
2001-02-23 20:55:21 +03:00
xmlBufferCat ( xmlBufferPtr buf , const xmlChar * str ) {
2004-07-31 20:24:01 +04:00
if ( buf - > alloc = = XML_BUFFER_ALLOC_IMMUTABLE ) return - 1 ;
if ( str = = NULL ) return - 1 ;
return xmlBufferAdd ( buf , str , - 1 ) ;
2001-02-23 20:55:21 +03:00
}
/**
* xmlBufferCCat :
* @ buf : the buffer to dump
* @ str : the C char string
*
* Append a zero terminated C string to an XML buffer .
2004-07-31 20:24:01 +04:00
*
* Returns 0 successful , a positive error code number otherwise
* and - 1 in case of internal or API error .
2001-02-23 20:55:21 +03:00
*/
2004-07-31 20:24:01 +04:00
int
2001-02-23 20:55:21 +03:00
xmlBufferCCat ( xmlBufferPtr buf , const char * str ) {
const char * cur ;
2004-07-31 20:24:01 +04:00
if ( buf - > alloc = = XML_BUFFER_ALLOC_IMMUTABLE ) return - 1 ;
2001-02-23 20:55:21 +03:00
if ( str = = NULL ) {
# ifdef DEBUG_BUFFER
xmlGenericError ( xmlGenericErrorContext ,
2001-12-17 18:30:10 +03:00
" xmlBufferCCat: str == NULL \n " ) ;
2001-02-23 20:55:21 +03:00
# endif
2004-07-31 20:24:01 +04:00
return - 1 ;
2001-02-23 20:55:21 +03:00
}
for ( cur = str ; * cur ! = 0 ; cur + + ) {
if ( buf - > use + 10 > = buf - > size ) {
if ( ! xmlBufferResize ( buf , buf - > use + 10 ) ) {
2003-10-08 03:16:40 +04:00
xmlTreeErrMemory ( " growing buffer " ) ;
2004-07-31 20:24:01 +04:00
return XML_ERR_NO_MEMORY ;
2001-02-23 20:55:21 +03:00
}
}
buf - > content [ buf - > use + + ] = * cur ;
}
buf - > content [ buf - > use ] = 0 ;
2004-07-31 20:24:01 +04:00
return 0 ;
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
2003-09-18 17:35:51 +04:00
xmlBufferWriteCHAR ( xmlBufferPtr buf , const xmlChar * string ) {
if ( buf - > alloc = = XML_BUFFER_ALLOC_IMMUTABLE ) return ;
2001-02-23 20:55:21 +03:00
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 ) {
2003-09-18 17:35:51 +04:00
if ( buf - > alloc = = XML_BUFFER_ALLOC_IMMUTABLE ) return ;
2001-02-23 20:55:21 +03:00
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
2001-12-17 18:30:10 +03:00
* a quoted or double quoted # xmlChar string , checking first if it holds
2001-02-23 20:55:21 +03:00
* quote or double - quotes internally
*/
void
xmlBufferWriteQuotedString ( xmlBufferPtr buf , const xmlChar * string ) {
2003-08-04 05:33:43 +04:00
const xmlChar * cur , * base ;
2003-09-18 17:35:51 +04:00
if ( buf - > alloc = = XML_BUFFER_ALLOC_IMMUTABLE ) return ;
2003-08-04 05:33:43 +04:00
if ( xmlStrchr ( string , ' \" ' ) ) {
2003-08-04 23:43:15 +04:00
if ( xmlStrchr ( string , ' \' ' ) ) {
2001-02-23 20:55:21 +03:00
# ifdef DEBUG_BUFFER
xmlGenericError ( xmlGenericErrorContext ,
" xmlBufferWriteQuotedString: string contains quote and double-quotes ! \n " ) ;
# endif
2003-08-04 05:33:43 +04:00
xmlBufferCCat ( buf , " \" " ) ;
base = cur = string ;
while ( * cur ! = 0 ) {
if ( * cur = = ' " ' ) {
if ( base ! = cur )
xmlBufferAdd ( buf , base , cur - base ) ;
xmlBufferAdd ( buf , BAD_CAST " " " , 6 ) ;
cur + + ;
base = cur ;
}
else {
cur + + ;
}
}
if ( base ! = cur )
xmlBufferAdd ( buf , base , cur - base ) ;
xmlBufferCCat ( buf , " \" " ) ;
2001-02-23 20:55:21 +03:00
}
2003-08-04 05:33:43 +04:00
else {
xmlBufferCCat ( buf , " \' " ) ;
xmlBufferCat ( buf , string ) ;
xmlBufferCCat ( buf , " \' " ) ;
}
2001-02-23 20:55:21 +03:00
} else {
xmlBufferCCat ( buf , " \" " ) ;
xmlBufferCat ( buf , string ) ;
xmlBufferCCat ( buf , " \" " ) ;
}
}
2003-09-29 17:20:24 +04: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 ;
}