2004-03-04 16:40:59 +03:00
/*
* xmlsave . c : Implemetation of the document serializer
*
* See Copyright for the status of this software .
*
* daniel @ veillard . com
*/
# define IN_LIBXML
# include "libxml.h"
# include <string.h>
# include <libxml/xmlmemory.h>
# include <libxml/parserInternals.h>
# include <libxml/tree.h>
# include <libxml/xmlsave.h>
# ifdef LIBXML_HTML_ENABLED
# include <libxml/HTMLtree.h>
2004-03-28 20:12:44 +04:00
# define MAX_INDENT 60
2004-03-04 16:40:59 +03:00
/************************************************************************
* *
* XHTML detection *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define XHTML_STRICT_PUBLIC_ID BAD_CAST \
" -//W3C//DTD XHTML 1.0 Strict//EN "
# define XHTML_STRICT_SYSTEM_ID BAD_CAST \
" http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd "
# define XHTML_FRAME_PUBLIC_ID BAD_CAST \
" -//W3C//DTD XHTML 1.0 Frameset//EN "
# define XHTML_FRAME_SYSTEM_ID BAD_CAST \
" http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd "
# define XHTML_TRANS_PUBLIC_ID BAD_CAST \
" -//W3C//DTD XHTML 1.0 Transitional//EN "
# define XHTML_TRANS_SYSTEM_ID BAD_CAST \
" http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd "
# define XHTML_NS_NAME BAD_CAST "http: //www.w3.org/1999/xhtml"
/**
* xmlIsXHTML :
* @ systemID : the system identifier
* @ publicID : the public identifier
*
* Try to find if the document correspond to an XHTML DTD
*
* Returns 1 if true , 0 if not and - 1 in case of error
*/
int
xmlIsXHTML ( const xmlChar * systemID , const xmlChar * publicID ) {
if ( ( systemID = = NULL ) & & ( publicID = = NULL ) )
return ( - 1 ) ;
if ( publicID ! = NULL ) {
if ( xmlStrEqual ( publicID , XHTML_STRICT_PUBLIC_ID ) ) return ( 1 ) ;
if ( xmlStrEqual ( publicID , XHTML_FRAME_PUBLIC_ID ) ) return ( 1 ) ;
if ( xmlStrEqual ( publicID , XHTML_TRANS_PUBLIC_ID ) ) return ( 1 ) ;
}
if ( systemID ! = NULL ) {
if ( xmlStrEqual ( systemID , XHTML_STRICT_SYSTEM_ID ) ) return ( 1 ) ;
if ( xmlStrEqual ( systemID , XHTML_FRAME_SYSTEM_ID ) ) return ( 1 ) ;
if ( xmlStrEqual ( systemID , XHTML_TRANS_SYSTEM_ID ) ) return ( 1 ) ;
}
return ( 0 ) ;
}
# endif /* LIBXML_HTML_ENABLED */
# ifdef LIBXML_OUTPUT_ENABLED
# define TODO \
xmlGenericError ( xmlGenericErrorContext , \
" Unimplemented block at %s:%d \n " , \
__FILE__ , __LINE__ ) ;
struct _xmlSaveCtxt {
void * _private ;
int type ;
int fd ;
const xmlChar * filename ;
const xmlChar * encoding ;
xmlCharEncodingHandlerPtr handler ;
2004-03-15 16:46:37 +03:00
xmlOutputBufferPtr buf ;
xmlDocPtr doc ;
2004-03-04 16:40:59 +03:00
int options ;
int level ;
2004-03-15 16:46:37 +03:00
int format ;
2004-03-28 20:12:44 +04:00
char indent [ MAX_INDENT + 1 ] ;
int indent_nr ;
int indent_size ;
2004-03-04 16:40:59 +03:00
} ;
/************************************************************************
* *
* Output error handlers *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlSaveErrMemory :
* @ extra : extra informations
*
* Handle an out of memory condition
*/
static void
xmlSaveErrMemory ( const char * extra )
{
__xmlSimpleError ( XML_FROM_OUTPUT , XML_ERR_NO_MEMORY , NULL , NULL , extra ) ;
}
/**
* xmlSaveErr :
* @ code : the error number
* @ node : the location of the error .
* @ extra : extra informations
*
* Handle an out of memory condition
*/
static void
xmlSaveErr ( int code , xmlNodePtr node , const char * extra )
{
const char * msg = NULL ;
switch ( code ) {
case XML_SAVE_NOT_UTF8 :
msg = " string is not in UTF-8 " ;
break ;
case XML_SAVE_CHAR_INVALID :
msg = " invalid character value " ;
break ;
case XML_SAVE_UNKNOWN_ENCODING :
msg = " unknown encoding %s " ;
break ;
case XML_SAVE_NO_DOCTYPE :
msg = " document has no DOCTYPE " ;
break ;
default :
msg = " unexpected error number " ;
}
__xmlSimpleError ( XML_FROM_OUTPUT , code , node , msg , extra ) ;
}
/************************************************************************
* *
* Allocation and deallocation *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-28 20:12:44 +04:00
/**
* xmlSaveCtxtInit :
* @ ctxt : the saving context
*
* Initialize a saving context
*/
static void
xmlSaveCtxtInit ( xmlSaveCtxtPtr ctxt )
{
int i ;
if ( ctxt = = NULL ) return ;
if ( xmlTreeIndentString = = NULL ) {
memset ( & ctxt - > indent [ 0 ] , 0 , MAX_INDENT + 1 ) ;
} else {
ctxt - > indent_size = xmlStrlen ( ( const xmlChar * ) xmlTreeIndentString ) ;
ctxt - > indent_nr = MAX_INDENT / ctxt - > indent_size ;
for ( i = 0 ; i < ctxt - > indent_nr ; i + + )
memcpy ( & ctxt - > indent [ i * ctxt - > indent_size ] , xmlTreeIndentString ,
ctxt - > indent_size ) ;
ctxt - > indent [ ctxt - > indent_nr * ctxt - > indent_size ] = 0 ;
}
}
2004-03-04 16:40:59 +03:00
/**
* xmlFreeSaveCtxt :
*
* Free a saving context , destroying the ouptut in any remaining buffer
*/
static void
xmlFreeSaveCtxt ( xmlSaveCtxtPtr ctxt )
{
if ( ctxt = = NULL ) return ;
if ( ctxt - > encoding ! = NULL )
xmlFree ( ( char * ) ctxt - > encoding ) ;
2004-04-29 21:14:25 +04:00
if ( ctxt - > buf ! = NULL )
xmlOutputBufferClose ( ctxt - > buf ) ;
2004-03-04 16:40:59 +03:00
xmlFree ( ctxt ) ;
}
/**
* xmlNewSaveCtxt :
*
* Create a new saving context
*
* Returns the new structure or NULL in case of error
*/
static xmlSaveCtxtPtr
xmlNewSaveCtxt ( const char * encoding , int options )
{
xmlSaveCtxtPtr ret ;
ret = ( xmlSaveCtxtPtr ) xmlMalloc ( sizeof ( xmlSaveCtxt ) ) ;
if ( ret = = NULL ) {
xmlSaveErrMemory ( " creating saving context " ) ;
return ( NULL ) ;
}
memset ( ret , 0 , sizeof ( xmlSaveCtxt ) ) ;
ret - > options = options ;
if ( encoding ! = NULL ) {
ret - > handler = xmlFindCharEncodingHandler ( encoding ) ;
if ( ret - > handler = = NULL ) {
xmlSaveErr ( XML_SAVE_UNKNOWN_ENCODING , NULL , encoding ) ;
xmlFreeSaveCtxt ( ret ) ;
return ( NULL ) ;
}
ret - > encoding = xmlStrdup ( ( const xmlChar * ) encoding ) ;
}
2004-03-28 20:12:44 +04:00
xmlSaveCtxtInit ( ret ) ;
2004-03-04 16:40:59 +03:00
return ( ret ) ;
}
/************************************************************************
* *
* Dumping XML tree content to a simple buffer *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlAttrSerializeContent :
* @ buf : the XML buffer output
* @ doc : the document
* @ attr : the attribute pointer
*
* Serialize the attribute in the buffer
*/
static void
xmlAttrSerializeContent ( xmlBufferPtr buf , xmlDocPtr doc , xmlAttrPtr attr )
{
xmlNodePtr children ;
children = attr - > children ;
while ( children ! = NULL ) {
switch ( children - > type ) {
case XML_TEXT_NODE :
xmlAttrSerializeTxtContent ( buf , doc , attr , children - > content ) ;
break ;
case XML_ENTITY_REF_NODE :
xmlBufferAdd ( buf , BAD_CAST " & " , 1 ) ;
xmlBufferAdd ( buf , children - > name ,
xmlStrlen ( children - > name ) ) ;
xmlBufferAdd ( buf , BAD_CAST " ; " , 1 ) ;
break ;
default :
/* should not happen unless we have a badly built tree */
break ;
}
children = children - > next ;
}
}
/************************************************************************
* *
* Dumping XML tree content to an I / O output buffer *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifdef LIBXML_HTML_ENABLED
static void
2004-03-15 16:46:37 +03:00
xhtmlNodeDumpOutput ( xmlSaveCtxtPtr ctxt , xmlNodePtr cur ) ;
2004-03-04 16:40:59 +03:00
# endif
2004-03-15 16:46:37 +03:00
static void xmlNodeListDumpOutput ( xmlSaveCtxtPtr ctxt , xmlNodePtr cur ) ;
static void xmlNodeDumpOutputInternal ( xmlSaveCtxtPtr ctxt , xmlNodePtr cur ) ;
2004-03-04 16:40:59 +03:00
void xmlNsListDumpOutput ( xmlOutputBufferPtr buf , xmlNsPtr cur ) ;
/**
* xmlNsDumpOutput :
* @ buf : the XML buffer output
* @ cur : a namespace
*
* Dump a local Namespace definition .
* Should be called in the context of attributes dumps .
*/
static void
xmlNsDumpOutput ( xmlOutputBufferPtr buf , xmlNsPtr cur ) {
2004-03-15 16:46:37 +03:00
if ( cur = = NULL ) return ;
2004-03-04 16:40:59 +03:00
if ( ( cur - > type = = XML_LOCAL_NAMESPACE ) & & ( cur - > href ! = NULL ) ) {
if ( xmlStrEqual ( cur - > prefix , BAD_CAST " xml " ) )
return ;
/* Within the context of an element attributes */
if ( cur - > prefix ! = NULL ) {
xmlOutputBufferWriteString ( buf , " xmlns: " ) ;
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > prefix ) ;
} else
xmlOutputBufferWriteString ( buf , " xmlns " ) ;
xmlOutputBufferWriteString ( buf , " = " ) ;
xmlBufferWriteQuotedString ( buf - > buffer , cur - > href ) ;
}
}
/**
* xmlNsListDumpOutput :
* @ buf : the XML buffer output
* @ cur : the first namespace
*
* Dump a list of local Namespace definitions .
* Should be called in the context of attributes dumps .
*/
void
xmlNsListDumpOutput ( xmlOutputBufferPtr buf , xmlNsPtr cur ) {
while ( cur ! = NULL ) {
xmlNsDumpOutput ( buf , cur ) ;
cur = cur - > next ;
}
}
/**
* xmlDtdDumpOutput :
* @ buf : the XML buffer output
2004-03-15 16:46:37 +03:00
* @ dtd : the pointer to the DTD
2004-03-04 16:40:59 +03:00
*
* Dump the XML document DTD , if any .
*/
static void
2004-03-15 16:46:37 +03:00
xmlDtdDumpOutput ( xmlSaveCtxtPtr ctxt , xmlDtdPtr dtd ) {
xmlOutputBufferPtr buf ;
int format , level ;
xmlDocPtr doc ;
if ( dtd = = NULL ) return ;
if ( ( ctxt = = NULL ) | | ( ctxt - > buf = = NULL ) )
return ;
buf = ctxt - > buf ;
2004-03-04 16:40:59 +03:00
xmlOutputBufferWriteString ( buf , " <!DOCTYPE " ) ;
xmlOutputBufferWriteString ( buf , ( const char * ) dtd - > name ) ;
if ( dtd - > ExternalID ! = NULL ) {
xmlOutputBufferWriteString ( buf , " PUBLIC " ) ;
xmlBufferWriteQuotedString ( buf - > buffer , dtd - > ExternalID ) ;
xmlOutputBufferWriteString ( buf , " " ) ;
xmlBufferWriteQuotedString ( buf - > buffer , dtd - > SystemID ) ;
} else if ( dtd - > SystemID ! = NULL ) {
xmlOutputBufferWriteString ( buf , " SYSTEM " ) ;
xmlBufferWriteQuotedString ( buf - > buffer , dtd - > SystemID ) ;
}
if ( ( dtd - > entities = = NULL ) & & ( dtd - > elements = = NULL ) & &
( dtd - > attributes = = NULL ) & & ( dtd - > notations = = NULL ) & &
( dtd - > pentities = = NULL ) ) {
xmlOutputBufferWriteString ( buf , " > " ) ;
return ;
}
xmlOutputBufferWriteString ( buf , " [ \n " ) ;
2004-03-15 16:46:37 +03:00
format = ctxt - > format ;
level = ctxt - > level ;
doc = ctxt - > doc ;
ctxt - > format = 0 ;
ctxt - > level = - 1 ;
ctxt - > doc = dtd - > doc ;
xmlNodeListDumpOutput ( ctxt , dtd - > children ) ;
ctxt - > format = format ;
ctxt - > level = level ;
ctxt - > doc = doc ;
2004-03-04 16:40:59 +03:00
xmlOutputBufferWriteString ( buf , " ]> " ) ;
}
/**
* xmlAttrDumpOutput :
* @ buf : the XML buffer output
* @ cur : the attribute pointer
*
* Dump an XML attribute
*/
static void
2004-03-15 16:46:37 +03:00
xmlAttrDumpOutput ( xmlSaveCtxtPtr ctxt , xmlAttrPtr cur ) {
xmlOutputBufferPtr buf ;
if ( cur = = NULL ) return ;
buf = ctxt - > buf ;
2004-03-04 16:40:59 +03:00
xmlOutputBufferWriteString ( buf , " " ) ;
if ( ( cur - > ns ! = NULL ) & & ( cur - > ns - > prefix ! = NULL ) ) {
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > ns - > prefix ) ;
xmlOutputBufferWriteString ( buf , " : " ) ;
}
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > name ) ;
xmlOutputBufferWriteString ( buf , " = \" " ) ;
2004-03-15 16:46:37 +03:00
xmlAttrSerializeContent ( buf - > buffer , ctxt - > doc , cur ) ;
2004-03-04 16:40:59 +03:00
xmlOutputBufferWriteString ( buf , " \" " ) ;
}
/**
* xmlAttrListDumpOutput :
* @ buf : the XML buffer output
* @ doc : the document
* @ cur : the first attribute pointer
* @ encoding : an optional encoding string
*
* Dump a list of XML attributes
*/
static void
2004-03-15 16:46:37 +03:00
xmlAttrListDumpOutput ( xmlSaveCtxtPtr ctxt , xmlAttrPtr cur ) {
if ( cur = = NULL ) return ;
2004-03-04 16:40:59 +03:00
while ( cur ! = NULL ) {
2004-03-15 16:46:37 +03:00
xmlAttrDumpOutput ( ctxt , cur ) ;
2004-03-04 16:40:59 +03:00
cur = cur - > next ;
}
}
/**
* xmlNodeListDumpOutput :
* @ cur : the first node
*
* Dump an XML node list , recursive behaviour , children are printed too .
*/
static void
2004-03-15 16:46:37 +03:00
xmlNodeListDumpOutput ( xmlSaveCtxtPtr ctxt , xmlNodePtr cur ) {
xmlOutputBufferPtr buf ;
2004-03-04 16:40:59 +03:00
2004-03-15 16:46:37 +03:00
if ( cur = = NULL ) return ;
buf = ctxt - > buf ;
2004-03-04 16:40:59 +03:00
while ( cur ! = NULL ) {
2004-03-15 16:46:37 +03:00
if ( ( ctxt - > format ) & & ( xmlIndentTreeOutput ) & &
2004-03-04 16:40:59 +03:00
( cur - > type = = XML_ELEMENT_NODE ) )
2004-03-28 20:12:44 +04:00
xmlOutputBufferWrite ( buf , ctxt - > indent_size *
( ctxt - > level > ctxt - > indent_nr ?
ctxt - > indent_nr : ctxt - > level ) ,
ctxt - > indent ) ;
2004-03-15 16:46:37 +03:00
xmlNodeDumpOutputInternal ( ctxt , cur ) ;
if ( ctxt - > format ) {
2004-03-04 16:40:59 +03:00
xmlOutputBufferWriteString ( buf , " \n " ) ;
}
cur = cur - > next ;
}
}
/**
* xmlNodeDumpOutputInternal :
* @ cur : the current node
*
* Dump an XML node , recursive behaviour , children are printed too .
*/
static void
2004-03-15 16:46:37 +03:00
xmlNodeDumpOutputInternal ( xmlSaveCtxtPtr ctxt , xmlNodePtr cur ) {
2004-03-28 20:12:44 +04:00
int format ;
2004-03-04 16:40:59 +03:00
xmlNodePtr tmp ;
xmlChar * start , * end ;
2004-03-15 16:46:37 +03:00
xmlOutputBufferPtr buf ;
2004-03-04 16:40:59 +03:00
2004-03-15 16:46:37 +03:00
if ( cur = = NULL ) return ;
buf = ctxt - > buf ;
2004-03-04 16:40:59 +03:00
if ( cur - > type = = XML_XINCLUDE_START )
return ;
if ( cur - > type = = XML_XINCLUDE_END )
return ;
if ( cur - > type = = XML_DTD_NODE ) {
2004-03-15 16:46:37 +03:00
xmlDtdDumpOutput ( ctxt , ( xmlDtdPtr ) cur ) ;
2004-03-04 16:40:59 +03:00
return ;
}
if ( cur - > type = = XML_DOCUMENT_FRAG_NODE ) {
2004-03-15 16:46:37 +03:00
xmlNodeListDumpOutput ( ctxt , cur - > children ) ;
2004-03-04 16:40:59 +03:00
return ;
}
if ( cur - > type = = XML_ELEMENT_DECL ) {
xmlDumpElementDecl ( buf - > buffer , ( xmlElementPtr ) cur ) ;
return ;
}
if ( cur - > type = = XML_ATTRIBUTE_DECL ) {
xmlDumpAttributeDecl ( buf - > buffer , ( xmlAttributePtr ) cur ) ;
return ;
}
if ( cur - > type = = XML_ENTITY_DECL ) {
xmlDumpEntityDecl ( buf - > buffer , ( xmlEntityPtr ) cur ) ;
return ;
}
if ( cur - > type = = XML_TEXT_NODE ) {
if ( cur - > content ! = NULL ) {
if ( ( cur - > name = = xmlStringText ) | |
( cur - > name ! = xmlStringTextNoenc ) ) {
xmlChar * buffer ;
2004-03-15 16:46:37 +03:00
if ( ctxt - > encoding = = NULL )
buffer = xmlEncodeEntitiesReentrant ( ctxt - > doc ,
cur - > content ) ;
2004-03-04 16:40:59 +03:00
else
2004-03-15 16:46:37 +03:00
buffer = xmlEncodeSpecialChars ( ctxt - > doc , cur - > content ) ;
2004-03-04 16:40:59 +03:00
if ( buffer ! = NULL ) {
xmlOutputBufferWriteString ( buf , ( const char * ) buffer ) ;
xmlFree ( buffer ) ;
}
} else {
/*
* Disable escaping , needed for XSLT
*/
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > content ) ;
}
}
return ;
}
if ( cur - > type = = XML_PI_NODE ) {
if ( cur - > content ! = NULL ) {
xmlOutputBufferWriteString ( buf , " <? " ) ;
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > name ) ;
if ( cur - > content ! = NULL ) {
xmlOutputBufferWriteString ( buf , " " ) ;
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > content ) ;
}
xmlOutputBufferWriteString ( buf , " ?> " ) ;
} else {
xmlOutputBufferWriteString ( buf , " <? " ) ;
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > name ) ;
xmlOutputBufferWriteString ( buf , " ?> " ) ;
}
return ;
}
if ( cur - > type = = XML_COMMENT_NODE ) {
if ( cur - > content ! = NULL ) {
xmlOutputBufferWriteString ( buf , " <!-- " ) ;
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > content ) ;
xmlOutputBufferWriteString ( buf , " --> " ) ;
}
return ;
}
if ( cur - > type = = XML_ENTITY_REF_NODE ) {
xmlOutputBufferWriteString ( buf , " & " ) ;
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > name ) ;
xmlOutputBufferWriteString ( buf , " ; " ) ;
return ;
}
if ( cur - > type = = XML_CDATA_SECTION_NODE ) {
start = end = cur - > content ;
while ( * end ! = ' \0 ' ) {
if ( ( * end = = ' ] ' ) & & ( * ( end + 1 ) = = ' ] ' ) & & ( * ( end + 2 ) = = ' > ' ) ) {
end = end + 2 ;
xmlOutputBufferWriteString ( buf , " <![CDATA[ " ) ;
xmlOutputBufferWrite ( buf , end - start , ( const char * ) start ) ;
xmlOutputBufferWriteString ( buf , " ]]> " ) ;
start = end ;
}
end + + ;
}
if ( start ! = end ) {
xmlOutputBufferWriteString ( buf , " <![CDATA[ " ) ;
xmlOutputBufferWriteString ( buf , ( const char * ) start ) ;
xmlOutputBufferWriteString ( buf , " ]]> " ) ;
}
return ;
}
if ( cur - > type = = XML_ATTRIBUTE_NODE ) {
2004-03-15 16:46:37 +03:00
xmlAttrDumpOutput ( ctxt , ( xmlAttrPtr ) cur ) ;
2004-03-04 16:40:59 +03:00
return ;
}
if ( cur - > type = = XML_NAMESPACE_DECL ) {
xmlNsDumpOutput ( buf , ( xmlNsPtr ) cur ) ;
return ;
}
2004-03-15 16:46:37 +03:00
format = ctxt - > format ;
2004-03-04 16:40:59 +03:00
if ( format = = 1 ) {
tmp = cur - > children ;
while ( tmp ! = NULL ) {
if ( ( tmp - > type = = XML_TEXT_NODE ) | |
( tmp - > type = = XML_CDATA_SECTION_NODE ) | |
( tmp - > type = = XML_ENTITY_REF_NODE ) ) {
2004-03-15 16:46:37 +03:00
ctxt - > format = 0 ;
2004-03-04 16:40:59 +03:00
break ;
}
tmp = tmp - > next ;
}
}
xmlOutputBufferWriteString ( buf , " < " ) ;
if ( ( cur - > ns ! = NULL ) & & ( cur - > ns - > prefix ! = NULL ) ) {
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > ns - > prefix ) ;
xmlOutputBufferWriteString ( buf , " : " ) ;
}
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > name ) ;
if ( cur - > nsDef )
xmlNsListDumpOutput ( buf , cur - > nsDef ) ;
if ( cur - > properties ! = NULL )
2004-03-15 16:46:37 +03:00
xmlAttrListDumpOutput ( ctxt , cur - > properties ) ;
2004-03-04 16:40:59 +03:00
if ( ( ( cur - > type = = XML_ELEMENT_NODE ) | | ( cur - > content = = NULL ) ) & &
( cur - > children = = NULL ) & & ( ! xmlSaveNoEmptyTags ) ) {
xmlOutputBufferWriteString ( buf , " /> " ) ;
2004-03-15 16:46:37 +03:00
ctxt - > format = format ;
2004-03-04 16:40:59 +03:00
return ;
}
xmlOutputBufferWriteString ( buf , " > " ) ;
if ( ( cur - > type ! = XML_ELEMENT_NODE ) & & ( cur - > content ! = NULL ) ) {
xmlChar * buffer ;
2004-03-15 16:46:37 +03:00
if ( ctxt - > encoding = = NULL )
buffer = xmlEncodeEntitiesReentrant ( ctxt - > doc , cur - > content ) ;
2004-03-04 16:40:59 +03:00
else
2004-03-15 16:46:37 +03:00
buffer = xmlEncodeSpecialChars ( ctxt - > doc , cur - > content ) ;
2004-03-04 16:40:59 +03:00
if ( buffer ! = NULL ) {
xmlOutputBufferWriteString ( buf , ( const char * ) buffer ) ;
xmlFree ( buffer ) ;
}
}
if ( cur - > children ! = NULL ) {
2004-03-15 16:46:37 +03:00
if ( ctxt - > format ) xmlOutputBufferWriteString ( buf , " \n " ) ;
if ( ctxt - > level > = 0 ) ctxt - > level + + ;
xmlNodeListDumpOutput ( ctxt , cur - > children ) ;
if ( ctxt - > level > 0 ) ctxt - > level - - ;
if ( ( xmlIndentTreeOutput ) & & ( ctxt - > format ) )
2004-03-28 20:12:44 +04:00
xmlOutputBufferWrite ( buf , ctxt - > indent_size *
( ctxt - > level > ctxt - > indent_nr ?
ctxt - > indent_nr : ctxt - > level ) ,
ctxt - > indent ) ;
2004-03-04 16:40:59 +03:00
}
xmlOutputBufferWriteString ( buf , " </ " ) ;
if ( ( cur - > ns ! = NULL ) & & ( cur - > ns - > prefix ! = NULL ) ) {
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > ns - > prefix ) ;
xmlOutputBufferWriteString ( buf , " : " ) ;
}
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > name ) ;
xmlOutputBufferWriteString ( buf , " > " ) ;
2004-03-15 16:46:37 +03:00
ctxt - > format = format ;
2004-03-04 16:40:59 +03:00
}
/**
* xmlDocContentDumpOutput :
* @ cur : the document
*
* Dump an XML document .
*/
static void
2004-03-15 16:46:37 +03:00
xmlDocContentDumpOutput ( xmlSaveCtxtPtr ctxt , xmlDocPtr cur ) {
2004-03-04 16:40:59 +03:00
# ifdef LIBXML_HTML_ENABLED
xmlDtdPtr dtd ;
int is_xhtml = 0 ;
# endif
const xmlChar * oldenc = cur - > encoding ;
2004-03-15 16:46:37 +03:00
const xmlChar * encoding = ctxt - > encoding ;
xmlOutputBufferPtr buf ;
2004-03-04 16:40:59 +03:00
xmlInitParser ( ) ;
2004-03-15 16:46:37 +03:00
if ( ctxt - > encoding ! = NULL )
cur - > encoding = BAD_CAST ctxt - > encoding ;
2004-03-04 16:40:59 +03:00
2004-03-15 16:46:37 +03:00
buf = ctxt - > buf ;
2004-03-04 16:40:59 +03:00
xmlOutputBufferWriteString ( buf , " <?xml version= " ) ;
if ( cur - > version ! = NULL )
xmlBufferWriteQuotedString ( buf - > buffer , cur - > version ) ;
else
xmlOutputBufferWriteString ( buf , " \" 1.0 \" " ) ;
2004-03-15 16:46:37 +03:00
if ( ctxt - > encoding = = NULL ) {
2004-03-04 16:40:59 +03:00
if ( cur - > encoding ! = NULL )
2004-03-15 16:46:37 +03:00
encoding = cur - > encoding ;
2004-03-04 16:40:59 +03:00
else if ( cur - > charset ! = XML_CHAR_ENCODING_UTF8 )
2004-03-15 16:46:37 +03:00
encoding = ( const xmlChar * )
xmlGetCharEncodingName ( ( xmlCharEncoding ) cur - > charset ) ;
2004-03-04 16:40:59 +03:00
}
if ( encoding ! = NULL ) {
xmlOutputBufferWriteString ( buf , " encoding= " ) ;
xmlBufferWriteQuotedString ( buf - > buffer , ( xmlChar * ) encoding ) ;
}
switch ( cur - > standalone ) {
case 0 :
xmlOutputBufferWriteString ( buf , " standalone= \" no \" " ) ;
break ;
case 1 :
xmlOutputBufferWriteString ( buf , " standalone= \" yes \" " ) ;
break ;
}
xmlOutputBufferWriteString ( buf , " ?> \n " ) ;
# ifdef LIBXML_HTML_ENABLED
dtd = xmlGetIntSubset ( cur ) ;
if ( dtd ! = NULL ) {
is_xhtml = xmlIsXHTML ( dtd - > SystemID , dtd - > ExternalID ) ;
if ( is_xhtml < 0 ) is_xhtml = 0 ;
}
if ( is_xhtml ) {
if ( encoding ! = NULL )
2004-03-15 16:46:37 +03:00
htmlSetMetaEncoding ( cur , ( const xmlChar * ) ctxt - > encoding ) ;
2004-03-04 16:40:59 +03:00
else
htmlSetMetaEncoding ( cur , BAD_CAST " UTF-8 " ) ;
}
# endif
if ( cur - > children ! = NULL ) {
xmlNodePtr child = cur - > children ;
while ( child ! = NULL ) {
2004-03-15 16:46:37 +03:00
ctxt - > level = 0 ;
2004-03-04 16:40:59 +03:00
# ifdef LIBXML_HTML_ENABLED
if ( is_xhtml )
2004-03-15 16:46:37 +03:00
xhtmlNodeDumpOutput ( ctxt , child ) ;
2004-03-04 16:40:59 +03:00
else
# endif
2004-03-15 16:46:37 +03:00
xmlNodeDumpOutputInternal ( ctxt , child ) ;
2004-03-04 16:40:59 +03:00
xmlOutputBufferWriteString ( buf , " \n " ) ;
child = child - > next ;
}
}
2004-03-15 16:46:37 +03:00
if ( ctxt - > encoding ! = NULL )
2004-03-04 16:40:59 +03:00
cur - > encoding = oldenc ;
}
# ifdef LIBXML_HTML_ENABLED
/************************************************************************
* *
* Functions specific to XHTML serialization *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xhtmlIsEmpty :
* @ node : the node
*
* Check if a node is an empty xhtml node
*
* Returns 1 if the node is an empty node , 0 if not and - 1 in case of error
*/
static int
xhtmlIsEmpty ( xmlNodePtr node ) {
if ( node = = NULL )
return ( - 1 ) ;
if ( node - > type ! = XML_ELEMENT_NODE )
return ( 0 ) ;
if ( ( node - > ns ! = NULL ) & & ( ! xmlStrEqual ( node - > ns - > href , XHTML_NS_NAME ) ) )
return ( 0 ) ;
if ( node - > children ! = NULL )
return ( 0 ) ;
switch ( node - > name [ 0 ] ) {
case ' a ' :
if ( xmlStrEqual ( node - > name , BAD_CAST " area " ) )
return ( 1 ) ;
return ( 0 ) ;
case ' b ' :
if ( xmlStrEqual ( node - > name , BAD_CAST " br " ) )
return ( 1 ) ;
if ( xmlStrEqual ( node - > name , BAD_CAST " base " ) )
return ( 1 ) ;
if ( xmlStrEqual ( node - > name , BAD_CAST " basefont " ) )
return ( 1 ) ;
return ( 0 ) ;
case ' c ' :
if ( xmlStrEqual ( node - > name , BAD_CAST " col " ) )
return ( 1 ) ;
return ( 0 ) ;
case ' f ' :
if ( xmlStrEqual ( node - > name , BAD_CAST " frame " ) )
return ( 1 ) ;
return ( 0 ) ;
case ' h ' :
if ( xmlStrEqual ( node - > name , BAD_CAST " hr " ) )
return ( 1 ) ;
return ( 0 ) ;
case ' i ' :
if ( xmlStrEqual ( node - > name , BAD_CAST " img " ) )
return ( 1 ) ;
if ( xmlStrEqual ( node - > name , BAD_CAST " input " ) )
return ( 1 ) ;
if ( xmlStrEqual ( node - > name , BAD_CAST " isindex " ) )
return ( 1 ) ;
return ( 0 ) ;
case ' l ' :
if ( xmlStrEqual ( node - > name , BAD_CAST " link " ) )
return ( 1 ) ;
return ( 0 ) ;
case ' m ' :
if ( xmlStrEqual ( node - > name , BAD_CAST " meta " ) )
return ( 1 ) ;
return ( 0 ) ;
case ' p ' :
if ( xmlStrEqual ( node - > name , BAD_CAST " param " ) )
return ( 1 ) ;
return ( 0 ) ;
}
return ( 0 ) ;
}
/**
* xhtmlAttrListDumpOutput :
* @ cur : the first attribute pointer
*
* Dump a list of XML attributes
*/
static void
2004-03-15 16:46:37 +03:00
xhtmlAttrListDumpOutput ( xmlSaveCtxtPtr ctxt , xmlAttrPtr cur ) {
2004-03-04 16:40:59 +03:00
xmlAttrPtr xml_lang = NULL ;
xmlAttrPtr lang = NULL ;
xmlAttrPtr name = NULL ;
xmlAttrPtr id = NULL ;
xmlNodePtr parent ;
2004-03-15 16:46:37 +03:00
xmlOutputBufferPtr buf ;
2004-03-04 16:40:59 +03:00
2004-03-15 16:46:37 +03:00
if ( cur = = NULL ) return ;
buf = ctxt - > buf ;
2004-03-04 16:40:59 +03:00
parent = cur - > parent ;
while ( cur ! = NULL ) {
if ( ( cur - > ns = = NULL ) & & ( xmlStrEqual ( cur - > name , BAD_CAST " id " ) ) )
id = cur ;
else
if ( ( cur - > ns = = NULL ) & & ( xmlStrEqual ( cur - > name , BAD_CAST " name " ) ) )
name = cur ;
else
if ( ( cur - > ns = = NULL ) & & ( xmlStrEqual ( cur - > name , BAD_CAST " lang " ) ) )
lang = cur ;
else
if ( ( cur - > ns ! = NULL ) & & ( xmlStrEqual ( cur - > name , BAD_CAST " lang " ) ) & &
( xmlStrEqual ( cur - > ns - > prefix , BAD_CAST " xml " ) ) )
xml_lang = cur ;
else if ( ( cur - > ns = = NULL ) & &
( ( cur - > children = = NULL ) | |
( cur - > children - > content = = NULL ) | |
( cur - > children - > content [ 0 ] = = 0 ) ) & &
( htmlIsBooleanAttr ( cur - > name ) ) ) {
if ( cur - > children ! = NULL )
xmlFreeNode ( cur - > children ) ;
cur - > children = xmlNewText ( cur - > name ) ;
if ( cur - > children ! = NULL )
cur - > children - > parent = ( xmlNodePtr ) cur ;
}
2004-03-15 16:46:37 +03:00
xmlAttrDumpOutput ( ctxt , cur ) ;
2004-03-04 16:40:59 +03:00
cur = cur - > next ;
}
/*
* C .8
*/
if ( ( name ! = NULL ) & & ( id = = NULL ) ) {
if ( ( parent ! = NULL ) & & ( parent - > name ! = NULL ) & &
( ( xmlStrEqual ( parent - > name , BAD_CAST " a " ) ) | |
( xmlStrEqual ( parent - > name , BAD_CAST " p " ) ) | |
( xmlStrEqual ( parent - > name , BAD_CAST " div " ) ) | |
( xmlStrEqual ( parent - > name , BAD_CAST " img " ) ) | |
( xmlStrEqual ( parent - > name , BAD_CAST " map " ) ) | |
( xmlStrEqual ( parent - > name , BAD_CAST " applet " ) ) | |
( xmlStrEqual ( parent - > name , BAD_CAST " form " ) ) | |
( xmlStrEqual ( parent - > name , BAD_CAST " frame " ) ) | |
( xmlStrEqual ( parent - > name , BAD_CAST " iframe " ) ) ) ) {
xmlOutputBufferWriteString ( buf , " id= \" " ) ;
2004-03-15 16:46:37 +03:00
xmlAttrSerializeContent ( buf - > buffer , ctxt - > doc , name ) ;
2004-03-04 16:40:59 +03:00
xmlOutputBufferWriteString ( buf , " \" " ) ;
}
}
/*
* C .7 .
*/
if ( ( lang ! = NULL ) & & ( xml_lang = = NULL ) ) {
xmlOutputBufferWriteString ( buf , " xml:lang= \" " ) ;
2004-03-15 16:46:37 +03:00
xmlAttrSerializeContent ( buf - > buffer , ctxt - > doc , lang ) ;
2004-03-04 16:40:59 +03:00
xmlOutputBufferWriteString ( buf , " \" " ) ;
} else
if ( ( xml_lang ! = NULL ) & & ( lang = = NULL ) ) {
xmlOutputBufferWriteString ( buf , " lang= \" " ) ;
2004-03-15 16:46:37 +03:00
xmlAttrSerializeContent ( buf - > buffer , ctxt - > doc , xml_lang ) ;
2004-03-04 16:40:59 +03:00
xmlOutputBufferWriteString ( buf , " \" " ) ;
}
}
/**
* xhtmlNodeListDumpOutput :
* @ buf : the XML buffer output
* @ doc : the XHTML document
* @ cur : the first node
* @ level : the imbrication level for indenting
* @ format : is formatting allowed
* @ encoding : an optional encoding string
*
* Dump an XML node list , recursive behaviour , children are printed too .
* Note that @ format = 1 provide node indenting only if xmlIndentTreeOutput = 1
* or xmlKeepBlanksDefault ( 0 ) was called
*/
static void
2004-03-15 16:46:37 +03:00
xhtmlNodeListDumpOutput ( xmlSaveCtxtPtr ctxt , xmlNodePtr cur ) {
xmlOutputBufferPtr buf ;
2004-03-04 16:40:59 +03:00
2004-03-15 16:46:37 +03:00
if ( cur = = NULL ) return ;
buf = ctxt - > buf ;
2004-03-04 16:40:59 +03:00
while ( cur ! = NULL ) {
2004-03-15 16:46:37 +03:00
if ( ( ctxt - > format ) & & ( xmlIndentTreeOutput ) & &
2004-03-04 16:40:59 +03:00
( cur - > type = = XML_ELEMENT_NODE ) )
2004-03-28 20:12:44 +04:00
xmlOutputBufferWrite ( buf , ctxt - > indent_size *
( ctxt - > level > ctxt - > indent_nr ?
ctxt - > indent_nr : ctxt - > level ) ,
ctxt - > indent ) ;
2004-03-15 16:46:37 +03:00
xhtmlNodeDumpOutput ( ctxt , cur ) ;
if ( ctxt - > format ) {
2004-03-04 16:40:59 +03:00
xmlOutputBufferWriteString ( buf , " \n " ) ;
}
cur = cur - > next ;
}
}
/**
* xhtmlNodeDumpOutput :
* @ buf : the XML buffer output
* @ doc : the XHTML document
* @ cur : the current node
* @ level : the imbrication level for indenting
* @ format : is formatting allowed
* @ encoding : an optional encoding string
*
* Dump an XHTML node , recursive behaviour , children are printed too .
*/
static void
2004-03-15 16:46:37 +03:00
xhtmlNodeDumpOutput ( xmlSaveCtxtPtr ctxt , xmlNodePtr cur ) {
2004-03-28 20:12:44 +04:00
int format ;
2004-03-04 16:40:59 +03:00
xmlNodePtr tmp ;
xmlChar * start , * end ;
2004-03-15 16:46:37 +03:00
xmlOutputBufferPtr buf ;
2004-03-04 16:40:59 +03:00
2004-03-15 16:46:37 +03:00
if ( cur = = NULL ) return ;
2004-03-04 16:40:59 +03:00
if ( cur - > type = = XML_XINCLUDE_START )
return ;
if ( cur - > type = = XML_XINCLUDE_END )
return ;
if ( cur - > type = = XML_DTD_NODE ) {
2004-03-15 16:46:37 +03:00
xmlDtdDumpOutput ( ctxt , ( xmlDtdPtr ) cur ) ;
2004-03-04 16:40:59 +03:00
return ;
}
2004-03-15 16:46:37 +03:00
buf = ctxt - > buf ;
2004-03-04 16:40:59 +03:00
if ( cur - > type = = XML_ELEMENT_DECL ) {
xmlDumpElementDecl ( buf - > buffer , ( xmlElementPtr ) cur ) ;
return ;
}
if ( cur - > type = = XML_ATTRIBUTE_DECL ) {
xmlDumpAttributeDecl ( buf - > buffer , ( xmlAttributePtr ) cur ) ;
return ;
}
if ( cur - > type = = XML_ENTITY_DECL ) {
xmlDumpEntityDecl ( buf - > buffer , ( xmlEntityPtr ) cur ) ;
return ;
}
if ( cur - > type = = XML_TEXT_NODE ) {
if ( cur - > content ! = NULL ) {
if ( ( cur - > name = = xmlStringText ) | |
( cur - > name ! = xmlStringTextNoenc ) ) {
xmlChar * buffer ;
2004-03-15 16:46:37 +03:00
if ( ctxt - > encoding = = NULL )
buffer = xmlEncodeEntitiesReentrant ( ctxt - > doc ,
cur - > content ) ;
2004-03-04 16:40:59 +03:00
else
2004-03-15 16:46:37 +03:00
buffer = xmlEncodeSpecialChars ( ctxt - > doc , cur - > content ) ;
2004-03-04 16:40:59 +03:00
if ( buffer ! = NULL ) {
xmlOutputBufferWriteString ( buf , ( const char * ) buffer ) ;
xmlFree ( buffer ) ;
}
} else {
/*
* Disable escaping , needed for XSLT
*/
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > content ) ;
}
}
return ;
}
if ( cur - > type = = XML_PI_NODE ) {
if ( cur - > content ! = NULL ) {
xmlOutputBufferWriteString ( buf , " <? " ) ;
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > name ) ;
if ( cur - > content ! = NULL ) {
xmlOutputBufferWriteString ( buf , " " ) ;
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > content ) ;
}
xmlOutputBufferWriteString ( buf , " ?> " ) ;
} else {
xmlOutputBufferWriteString ( buf , " <? " ) ;
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > name ) ;
xmlOutputBufferWriteString ( buf , " ?> " ) ;
}
return ;
}
if ( cur - > type = = XML_COMMENT_NODE ) {
if ( cur - > content ! = NULL ) {
xmlOutputBufferWriteString ( buf , " <!-- " ) ;
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > content ) ;
xmlOutputBufferWriteString ( buf , " --> " ) ;
}
return ;
}
if ( cur - > type = = XML_ENTITY_REF_NODE ) {
xmlOutputBufferWriteString ( buf , " & " ) ;
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > name ) ;
xmlOutputBufferWriteString ( buf , " ; " ) ;
return ;
}
if ( cur - > type = = XML_CDATA_SECTION_NODE ) {
start = end = cur - > content ;
while ( * end ! = ' \0 ' ) {
if ( * end = = ' ] ' & & * ( end + 1 ) = = ' ] ' & & * ( end + 2 ) = = ' > ' ) {
end = end + 2 ;
xmlOutputBufferWriteString ( buf , " <![CDATA[ " ) ;
xmlOutputBufferWrite ( buf , end - start , ( const char * ) start ) ;
xmlOutputBufferWriteString ( buf , " ]]> " ) ;
start = end ;
}
end + + ;
}
if ( start ! = end ) {
xmlOutputBufferWriteString ( buf , " <![CDATA[ " ) ;
xmlOutputBufferWriteString ( buf , ( const char * ) start ) ;
xmlOutputBufferWriteString ( buf , " ]]> " ) ;
}
return ;
}
2004-03-15 16:46:37 +03:00
format = ctxt - > format ;
2004-03-04 16:40:59 +03:00
if ( format = = 1 ) {
tmp = cur - > children ;
while ( tmp ! = NULL ) {
if ( ( tmp - > type = = XML_TEXT_NODE ) | |
( tmp - > type = = XML_ENTITY_REF_NODE ) ) {
format = 0 ;
break ;
}
tmp = tmp - > next ;
}
}
xmlOutputBufferWriteString ( buf , " < " ) ;
if ( ( cur - > ns ! = NULL ) & & ( cur - > ns - > prefix ! = NULL ) ) {
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > ns - > prefix ) ;
xmlOutputBufferWriteString ( buf , " : " ) ;
}
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > name ) ;
if ( cur - > nsDef )
xmlNsListDumpOutput ( buf , cur - > nsDef ) ;
if ( ( xmlStrEqual ( cur - > name , BAD_CAST " html " ) & &
( cur - > ns = = NULL ) & & ( cur - > nsDef = = NULL ) ) ) {
/*
* 3.1 .1 . Strictly Conforming Documents A .3 .1 .1 3 /
*/
xmlOutputBufferWriteString ( buf ,
" xmlns= \" http://www.w3.org/1999/xhtml \" " ) ;
}
if ( cur - > properties ! = NULL )
2004-03-15 16:46:37 +03:00
xhtmlAttrListDumpOutput ( ctxt , cur - > properties ) ;
2004-03-04 16:40:59 +03:00
if ( ( cur - > type = = XML_ELEMENT_NODE ) & & ( cur - > children = = NULL ) ) {
if ( ( ( cur - > ns = = NULL ) | | ( cur - > ns - > prefix = = NULL ) ) & &
( xhtmlIsEmpty ( cur ) = = 1 ) ) {
/*
* C .2 . Empty Elements
*/
xmlOutputBufferWriteString ( buf , " /> " ) ;
} else {
/*
* C .3 . Element Minimization and Empty Element Content
*/
xmlOutputBufferWriteString ( buf , " ></ " ) ;
if ( ( cur - > ns ! = NULL ) & & ( cur - > ns - > prefix ! = NULL ) ) {
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > ns - > prefix ) ;
xmlOutputBufferWriteString ( buf , " : " ) ;
}
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > name ) ;
xmlOutputBufferWriteString ( buf , " > " ) ;
}
return ;
}
xmlOutputBufferWriteString ( buf , " > " ) ;
if ( ( cur - > type ! = XML_ELEMENT_NODE ) & & ( cur - > content ! = NULL ) ) {
xmlChar * buffer ;
2004-03-15 16:46:37 +03:00
if ( ctxt - > encoding = = NULL )
buffer = xmlEncodeEntitiesReentrant ( ctxt - > doc , cur - > content ) ;
2004-03-04 16:40:59 +03:00
else
2004-03-15 16:46:37 +03:00
buffer = xmlEncodeSpecialChars ( ctxt - > doc , cur - > content ) ;
2004-03-04 16:40:59 +03:00
if ( buffer ! = NULL ) {
xmlOutputBufferWriteString ( buf , ( const char * ) buffer ) ;
xmlFree ( buffer ) ;
}
}
/*
* 4.8 . Script and Style elements
*/
if ( ( cur - > type = = XML_ELEMENT_NODE ) & &
( ( xmlStrEqual ( cur - > name , BAD_CAST " script " ) ) | |
( xmlStrEqual ( cur - > name , BAD_CAST " style " ) ) ) & &
( ( cur - > ns = = NULL ) | |
( xmlStrEqual ( cur - > ns - > href , XHTML_NS_NAME ) ) ) ) {
xmlNodePtr child = cur - > children ;
while ( child ! = NULL ) {
if ( ( child - > type = = XML_TEXT_NODE ) | |
( child - > type = = XML_CDATA_SECTION_NODE ) ) {
/*
* Apparently CDATA escaping for style just break on IE ,
* mozilla and galeon , so . . .
*/
if ( xmlStrEqual ( cur - > name , BAD_CAST " style " ) & &
( xmlStrchr ( child - > content , ' < ' ) = = NULL ) & &
( xmlStrchr ( child - > content , ' > ' ) = = NULL ) & &
( xmlStrchr ( child - > content , ' & ' ) = = NULL ) ) {
2004-03-15 16:46:37 +03:00
int level = ctxt - > level ;
int indent = ctxt - > format ;
ctxt - > level = 0 ;
ctxt - > format = 0 ;
xhtmlNodeDumpOutput ( ctxt , child ) ;
ctxt - > level = level ;
ctxt - > format = indent ;
2004-03-04 16:40:59 +03:00
} else {
start = end = child - > content ;
while ( * end ! = ' \0 ' ) {
if ( * end = = ' ] ' & &
* ( end + 1 ) = = ' ] ' & &
* ( end + 2 ) = = ' > ' ) {
end = end + 2 ;
xmlOutputBufferWriteString ( buf , " <![CDATA[ " ) ;
xmlOutputBufferWrite ( buf , end - start ,
( const char * ) start ) ;
xmlOutputBufferWriteString ( buf , " ]]> " ) ;
start = end ;
}
end + + ;
}
if ( start ! = end ) {
xmlOutputBufferWriteString ( buf , " <![CDATA[ " ) ;
xmlOutputBufferWriteString ( buf , ( const char * ) start ) ;
xmlOutputBufferWriteString ( buf , " ]]> " ) ;
}
}
} else {
2004-03-15 16:46:37 +03:00
int level = ctxt - > level ;
int indent = ctxt - > format ;
ctxt - > level = 0 ;
ctxt - > format = 0 ;
xhtmlNodeDumpOutput ( ctxt , child ) ;
ctxt - > level = level ;
ctxt - > format = indent ;
2004-03-04 16:40:59 +03:00
}
child = child - > next ;
}
} else if ( cur - > children ! = NULL ) {
if ( format ) xmlOutputBufferWriteString ( buf , " \n " ) ;
2004-03-15 16:46:37 +03:00
if ( ctxt - > level > = 0 ) ctxt - > level + + ;
xhtmlNodeListDumpOutput ( ctxt , cur - > children ) ;
if ( ctxt - > level > 0 ) ctxt - > level - - ;
2004-03-04 16:40:59 +03:00
if ( ( xmlIndentTreeOutput ) & & ( format ) )
2004-03-28 20:12:44 +04:00
xmlOutputBufferWrite ( buf , ctxt - > indent_size *
( ctxt - > level > ctxt - > indent_nr ?
ctxt - > indent_nr : ctxt - > level ) ,
ctxt - > indent ) ;
2004-03-04 16:40:59 +03:00
}
xmlOutputBufferWriteString ( buf , " </ " ) ;
if ( ( cur - > ns ! = NULL ) & & ( cur - > ns - > prefix ! = NULL ) ) {
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > ns - > prefix ) ;
xmlOutputBufferWriteString ( buf , " : " ) ;
}
xmlOutputBufferWriteString ( buf , ( const char * ) cur - > name ) ;
xmlOutputBufferWriteString ( buf , " > " ) ;
}
# endif
/************************************************************************
* *
* Public entry points *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlSaveToFd :
* @ fd : a file descriptor number
* @ encoding : the encoding name to use or NULL
* @ options : a set of xmlSaveOptions
*
* Create a document saving context serializing to a file descriptor
* with the encoding and the options given .
*
* Returns a new serialization context or NULL in case of error .
*/
xmlSaveCtxtPtr
xmlSaveToFd ( int fd , const char * encoding , int options )
{
xmlSaveCtxtPtr ret ;
ret = xmlNewSaveCtxt ( encoding , options ) ;
if ( ret = = NULL ) return ( NULL ) ;
2004-03-15 16:46:37 +03:00
ret - > buf = xmlOutputBufferCreateFd ( fd , ret - > handler ) ;
if ( ret - > buf = = NULL ) {
2004-03-04 16:40:59 +03:00
xmlFreeSaveCtxt ( ret ) ;
return ( NULL ) ;
}
return ( ret ) ;
}
/**
* xmlSaveToFilename :
* @ filename : a file name or an URL
* @ encoding : the encoding name to use or NULL
* @ options : a set of xmlSaveOptions
*
* Create a document saving context serializing to a filename or possibly
* to an URL ( but this is less reliable ) with the encoding and the options
* given .
*
* Returns a new serialization context or NULL in case of error .
*/
xmlSaveCtxtPtr
xmlSaveToFilename ( const char * filename , const char * encoding , int options )
{
xmlSaveCtxtPtr ret ;
int compression = 0 ; /* TODO handle compression option */
ret = xmlNewSaveCtxt ( encoding , options ) ;
if ( ret = = NULL ) return ( NULL ) ;
2004-03-15 16:46:37 +03:00
ret - > buf = xmlOutputBufferCreateFilename ( filename , ret - > handler ,
2004-03-04 16:40:59 +03:00
compression ) ;
2004-03-15 16:46:37 +03:00
if ( ret - > buf = = NULL ) {
2004-03-04 16:40:59 +03:00
xmlFreeSaveCtxt ( ret ) ;
return ( NULL ) ;
}
return ( ret ) ;
}
#if 0
/**
* xmlSaveToBuffer :
* @ buffer : a buffer
* @ encoding : the encoding name to use or NULL
* @ options : a set of xmlSaveOptions
*
* Create a document saving context serializing to a buffer
* with the encoding and the options given
*
* Returns a new serialization context or NULL in case of error .
*/
xmlSaveCtxtPtr
xmlSaveToBuffer ( xmlBufferPtr buffer , const char * encoding , int options )
{
TODO
return ( NULL ) ;
}
# endif
/**
* xmlSaveToIO :
* @ iowrite : an I / O write function
* @ ioclose : an I / O close function
* @ ioctx : an I / O handler
* @ encoding : the encoding name to use or NULL
* @ options : a set of xmlSaveOptions
*
* Create a document saving context serializing to a file descriptor
* with the encoding and the options given
*
* Returns a new serialization context or NULL in case of error .
*/
xmlSaveCtxtPtr
xmlSaveToIO ( xmlOutputWriteCallback iowrite ,
xmlOutputCloseCallback ioclose ,
void * ioctx , const char * encoding , int options )
{
xmlSaveCtxtPtr ret ;
ret = xmlNewSaveCtxt ( encoding , options ) ;
if ( ret = = NULL ) return ( NULL ) ;
2004-03-15 16:46:37 +03:00
ret - > buf = xmlOutputBufferCreateIO ( iowrite , ioclose , ioctx , ret - > handler ) ;
if ( ret - > buf = = NULL ) {
2004-03-04 16:40:59 +03:00
xmlFreeSaveCtxt ( ret ) ;
return ( NULL ) ;
}
return ( ret ) ;
}
/**
* xmlSaveDoc :
* @ ctxt : a document saving context
* @ doc : a document
*
* Save a full document to a saving context
2004-04-16 20:30:05 +04:00
* TODO : The function is not fully implemented yet as it does not return the
* byte count but 0 instead
2004-03-04 16:40:59 +03:00
*
* Returns the number of byte written or - 1 in case of error
*/
long
xmlSaveDoc ( xmlSaveCtxtPtr ctxt , xmlDocPtr doc )
{
2004-03-15 16:46:37 +03:00
long ret = 0 ;
xmlDocContentDumpOutput ( ctxt , doc ) ;
return ( ret ) ;
2004-03-04 16:40:59 +03:00
}
/**
* xmlSaveTree :
* @ ctxt : a document saving context
* @ node : a document
*
* Save a subtree starting at the node parameter to a saving context
2004-04-16 20:30:05 +04:00
* TODO : The function is not fully implemented yet as it does not return the
* byte count but 0 instead
2004-03-04 16:40:59 +03:00
*
* Returns the number of byte written or - 1 in case of error
*/
long
xmlSaveTree ( xmlSaveCtxtPtr ctxt , xmlNodePtr node )
{
2004-03-15 16:46:37 +03:00
long ret = 0 ;
xmlNodeDumpOutputInternal ( ctxt , node ) ;
return ( ret ) ;
2004-03-04 16:40:59 +03:00
}
/**
* xmlSaveFlush :
* @ ctxt : a document saving context
*
* Flush a document saving context , i . e . make sure that all bytes have
* been output .
*
* Returns the number of byte written or - 1 in case of error .
*/
int
xmlSaveFlush ( xmlSaveCtxtPtr ctxt )
{
if ( ctxt = = NULL ) return ( - 1 ) ;
2004-03-15 16:46:37 +03:00
if ( ctxt - > buf = = NULL ) return ( - 1 ) ;
return ( xmlOutputBufferFlush ( ctxt - > buf ) ) ;
2004-03-04 16:40:59 +03:00
}
/**
* xmlSaveClose :
* @ ctxt : a document saving context
*
* Close a document saving context , i . e . make sure that all bytes have
* been output and free the associated data .
*
* Returns the number of byte written or - 1 in case of error .
*/
int
xmlSaveClose ( xmlSaveCtxtPtr ctxt )
{
int ret ;
if ( ctxt = = NULL ) return ( - 1 ) ;
ret = xmlSaveFlush ( ctxt ) ;
xmlFreeSaveCtxt ( ctxt ) ;
return ( ret ) ;
}
/************************************************************************
* *
* Public entry points based on buffers *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlAttrSerializeTxtContent :
* @ buf : the XML buffer output
* @ doc : the document
* @ attr : the attribute node
* @ string : the text content
*
* Serialize text attribute values to an xml simple buffer
*/
void
xmlAttrSerializeTxtContent ( xmlBufferPtr buf , xmlDocPtr doc ,
xmlAttrPtr attr , const xmlChar * string ) {
xmlChar * base , * cur ;
if ( string = = NULL ) return ;
base = cur = ( xmlChar * ) string ;
while ( * cur ! = 0 ) {
if ( * cur = = ' \n ' ) {
if ( base ! = cur )
xmlBufferAdd ( buf , base , cur - base ) ;
xmlBufferAdd ( buf , BAD_CAST " " , 5 ) ;
cur + + ;
base = cur ;
} else if ( * cur = = ' \r ' ) {
if ( base ! = cur )
xmlBufferAdd ( buf , base , cur - base ) ;
xmlBufferAdd ( buf , BAD_CAST " " , 5 ) ;
cur + + ;
base = cur ;
} else if ( * cur = = ' \t ' ) {
if ( base ! = cur )
xmlBufferAdd ( buf , base , cur - base ) ;
xmlBufferAdd ( buf , BAD_CAST " 	 " , 4 ) ;
cur + + ;
base = cur ;
} else if ( * cur = = ' " ' ) {
if ( base ! = cur )
xmlBufferAdd ( buf , base , cur - base ) ;
xmlBufferAdd ( buf , BAD_CAST " " " , 6 ) ;
cur + + ;
base = cur ;
} else if ( * cur = = ' < ' ) {
if ( base ! = cur )
xmlBufferAdd ( buf , base , cur - base ) ;
xmlBufferAdd ( buf , BAD_CAST " < " , 4 ) ;
cur + + ;
base = cur ;
} else if ( * cur = = ' > ' ) {
if ( base ! = cur )
xmlBufferAdd ( buf , base , cur - base ) ;
xmlBufferAdd ( buf , BAD_CAST " > " , 4 ) ;
cur + + ;
base = cur ;
} else if ( * cur = = ' & ' ) {
if ( base ! = cur )
xmlBufferAdd ( buf , base , cur - base ) ;
xmlBufferAdd ( buf , BAD_CAST " & " , 5 ) ;
cur + + ;
base = cur ;
} else if ( ( * cur > = 0x80 ) & & ( ( doc = = NULL ) | |
( doc - > encoding = = NULL ) ) ) {
/*
* We assume we have UTF - 8 content .
*/
char tmp [ 10 ] ;
int val = 0 , l = 1 ;
if ( base ! = cur )
xmlBufferAdd ( buf , base , cur - base ) ;
if ( * cur < 0xC0 ) {
xmlSaveErr ( XML_SAVE_NOT_UTF8 , ( xmlNodePtr ) attr , NULL ) ;
if ( doc ! = NULL )
doc - > encoding = xmlStrdup ( BAD_CAST " ISO-8859-1 " ) ;
snprintf ( tmp , sizeof ( tmp ) , " &#%d; " , * cur ) ;
tmp [ sizeof ( tmp ) - 1 ] = 0 ;
xmlBufferAdd ( buf , ( xmlChar * ) tmp , - 1 ) ;
cur + + ;
base = cur ;
continue ;
} else if ( * cur < 0xE0 ) {
val = ( cur [ 0 ] ) & 0x1F ;
val < < = 6 ;
val | = ( cur [ 1 ] ) & 0x3F ;
l = 2 ;
} else if ( * cur < 0xF0 ) {
val = ( cur [ 0 ] ) & 0x0F ;
val < < = 6 ;
val | = ( cur [ 1 ] ) & 0x3F ;
val < < = 6 ;
val | = ( cur [ 2 ] ) & 0x3F ;
l = 3 ;
} else if ( * cur < 0xF8 ) {
val = ( cur [ 0 ] ) & 0x07 ;
val < < = 6 ;
val | = ( cur [ 1 ] ) & 0x3F ;
val < < = 6 ;
val | = ( cur [ 2 ] ) & 0x3F ;
val < < = 6 ;
val | = ( cur [ 3 ] ) & 0x3F ;
l = 4 ;
}
if ( ( l = = 1 ) | | ( ! IS_CHAR ( val ) ) ) {
xmlSaveErr ( XML_SAVE_CHAR_INVALID , ( xmlNodePtr ) attr , NULL ) ;
if ( doc ! = NULL )
doc - > encoding = xmlStrdup ( BAD_CAST " ISO-8859-1 " ) ;
snprintf ( tmp , sizeof ( tmp ) , " &#%d; " , * cur ) ;
tmp [ sizeof ( tmp ) - 1 ] = 0 ;
xmlBufferAdd ( buf , ( xmlChar * ) tmp , - 1 ) ;
cur + + ;
base = cur ;
continue ;
}
/*
* We could do multiple things here . Just save
* as a char ref
*/
snprintf ( tmp , sizeof ( tmp ) , " &#x%X; " , val ) ;
tmp [ sizeof ( tmp ) - 1 ] = 0 ;
xmlBufferAdd ( buf , ( xmlChar * ) tmp , - 1 ) ;
cur + = l ;
base = cur ;
} else {
cur + + ;
}
}
if ( base ! = cur )
xmlBufferAdd ( buf , base , cur - base ) ;
}
/**
* xmlNodeDump :
* @ buf : the XML buffer output
* @ doc : the document
* @ cur : the current node
* @ level : the imbrication level for indenting
* @ format : is formatting allowed
*
* Dump an XML node , recursive behaviour , children are printed too .
* Note that @ format = 1 provide node indenting only if xmlIndentTreeOutput = 1
* or xmlKeepBlanksDefault ( 0 ) was called
*
* Returns the number of bytes written to the buffer or - 1 in case of error
*/
int
xmlNodeDump ( xmlBufferPtr buf , xmlDocPtr doc , xmlNodePtr cur , int level ,
int format )
{
unsigned int use ;
int ret ;
xmlOutputBufferPtr outbuf ;
xmlInitParser ( ) ;
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNodeDump : node == NULL \n " ) ;
# endif
return ( - 1 ) ;
}
if ( buf = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlNodeDump : buf == NULL \n " ) ;
# endif
return ( - 1 ) ;
}
outbuf = ( xmlOutputBufferPtr ) xmlMalloc ( sizeof ( xmlOutputBuffer ) ) ;
if ( outbuf = = NULL ) {
xmlSaveErrMemory ( " creating buffer " ) ;
return ( - 1 ) ;
}
memset ( outbuf , 0 , ( size_t ) sizeof ( xmlOutputBuffer ) ) ;
outbuf - > buffer = buf ;
outbuf - > encoder = NULL ;
outbuf - > writecallback = NULL ;
outbuf - > closecallback = NULL ;
outbuf - > context = NULL ;
outbuf - > written = 0 ;
use = buf - > use ;
xmlNodeDumpOutput ( outbuf , doc , cur , level , format , NULL ) ;
xmlFree ( outbuf ) ;
ret = buf - > use - use ;
return ( ret ) ;
}
/**
* xmlElemDump :
* @ f : the FILE * for the output
* @ doc : the document
* @ cur : the current node
*
* Dump an XML / HTML node , recursive behaviour , children are printed too .
*/
void
xmlElemDump ( FILE * f , xmlDocPtr doc , xmlNodePtr cur )
{
xmlOutputBufferPtr outbuf ;
xmlInitParser ( ) ;
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlElemDump : cur == NULL \n " ) ;
# endif
return ;
}
# ifdef DEBUG_TREE
if ( doc = = NULL ) {
xmlGenericError ( xmlGenericErrorContext ,
" xmlElemDump : doc == NULL \n " ) ;
}
# endif
outbuf = xmlOutputBufferCreateFile ( f , NULL ) ;
if ( outbuf = = NULL )
return ;
if ( ( doc ! = NULL ) & & ( doc - > type = = XML_HTML_DOCUMENT_NODE ) ) {
# ifdef LIBXML_HTML_ENABLED
htmlNodeDumpOutput ( outbuf , doc , cur , NULL ) ;
# else
xmlSaveErr ( XML_ERR_INTERNAL_ERROR , cur , " HTML support not compiled in \n " ) ;
# endif /* LIBXML_HTML_ENABLED */
} else
xmlNodeDumpOutput ( outbuf , doc , cur , 0 , 1 , NULL ) ;
xmlOutputBufferClose ( outbuf ) ;
}
/************************************************************************
* *
* Saving functions front - ends *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* xmlNodeDumpOutput :
* @ buf : the XML buffer output
* @ doc : the document
* @ cur : the current node
* @ level : the imbrication level for indenting
* @ format : is formatting allowed
* @ encoding : an optional encoding string
*
* Dump an XML node , recursive behaviour , children are printed too .
* Note that @ format = 1 provide node indenting only if xmlIndentTreeOutput = 1
* or xmlKeepBlanksDefault ( 0 ) was called
*/
void
xmlNodeDumpOutput ( xmlOutputBufferPtr buf , xmlDocPtr doc , xmlNodePtr cur ,
int level , int format , const char * encoding )
{
2004-03-15 16:46:37 +03:00
xmlSaveCtxt ctxt ;
2004-03-04 16:40:59 +03:00
# ifdef LIBXML_HTML_ENABLED
xmlDtdPtr dtd ;
int is_xhtml = 0 ;
# endif
xmlInitParser ( ) ;
2004-03-15 16:46:37 +03:00
memset ( & ctxt , 0 , sizeof ( ctxt ) ) ;
ctxt . doc = doc ;
ctxt . buf = buf ;
ctxt . level = level ;
ctxt . format = format ;
ctxt . encoding = ( const xmlChar * ) encoding ;
2004-03-28 20:12:44 +04:00
xmlSaveCtxtInit ( & ctxt ) ;
2004-03-15 16:46:37 +03:00
2004-03-04 16:40:59 +03:00
# ifdef LIBXML_HTML_ENABLED
dtd = xmlGetIntSubset ( doc ) ;
if ( dtd ! = NULL ) {
is_xhtml = xmlIsXHTML ( dtd - > SystemID , dtd - > ExternalID ) ;
if ( is_xhtml < 0 )
is_xhtml = 0 ;
if ( ( is_xhtml ) & & ( cur - > parent = = ( xmlNodePtr ) doc ) & &
( cur - > type = = XML_ELEMENT_NODE ) & &
( xmlStrEqual ( cur - > name , BAD_CAST " html " ) ) ) {
if ( encoding ! = NULL )
htmlSetMetaEncoding ( ( htmlDocPtr ) doc ,
( const xmlChar * ) encoding ) ;
else
htmlSetMetaEncoding ( ( htmlDocPtr ) doc , BAD_CAST " UTF-8 " ) ;
}
}
if ( is_xhtml )
2004-03-15 16:46:37 +03:00
xhtmlNodeDumpOutput ( & ctxt , cur ) ;
2004-03-04 16:40:59 +03:00
else
# endif
2004-03-15 16:46:37 +03:00
xmlNodeDumpOutputInternal ( & ctxt , cur ) ;
2004-03-04 16:40:59 +03:00
}
/**
* xmlDocDumpFormatMemoryEnc :
* @ out_doc : Document to generate XML text from
* @ doc_txt_ptr : Memory pointer for allocated XML text
* @ doc_txt_len : Length of the generated XML text
* @ txt_encoding : Character encoding to use when generating XML text
* @ format : should formatting spaces been added
*
* Dump the current DOM tree into memory using the character encoding specified
* by the caller . Note it is up to the caller of this function to free the
* allocated memory with xmlFree ( ) .
* Note that @ format = 1 provide node indenting only if xmlIndentTreeOutput = 1
* or xmlKeepBlanksDefault ( 0 ) was called
*/
void
xmlDocDumpFormatMemoryEnc ( xmlDocPtr out_doc , xmlChar * * doc_txt_ptr ,
int * doc_txt_len , const char * txt_encoding ,
int format ) {
2004-03-15 16:46:37 +03:00
xmlSaveCtxt ctxt ;
2004-03-04 16:40:59 +03:00
int dummy = 0 ;
xmlOutputBufferPtr out_buff = NULL ;
xmlCharEncodingHandlerPtr conv_hdlr = NULL ;
if ( doc_txt_len = = NULL ) {
doc_txt_len = & dummy ; /* Continue, caller just won't get length */
}
if ( doc_txt_ptr = = NULL ) {
* doc_txt_len = 0 ;
return ;
}
* doc_txt_ptr = NULL ;
* doc_txt_len = 0 ;
if ( out_doc = = NULL ) {
/* No document, no output */
return ;
}
/*
* Validate the encoding value , if provided .
* This logic is copied from xmlSaveFileEnc .
*/
if ( txt_encoding = = NULL )
txt_encoding = ( const char * ) out_doc - > encoding ;
if ( txt_encoding ! = NULL ) {
conv_hdlr = xmlFindCharEncodingHandler ( txt_encoding ) ;
if ( conv_hdlr = = NULL ) {
xmlSaveErr ( XML_SAVE_UNKNOWN_ENCODING , ( xmlNodePtr ) out_doc ,
txt_encoding ) ;
return ;
}
}
if ( ( out_buff = xmlAllocOutputBuffer ( conv_hdlr ) ) = = NULL ) {
xmlSaveErrMemory ( " creating buffer " ) ;
return ;
}
2004-03-15 16:46:37 +03:00
memset ( & ctxt , 0 , sizeof ( ctxt ) ) ;
ctxt . doc = out_doc ;
ctxt . buf = out_buff ;
ctxt . level = 0 ;
ctxt . format = format ;
ctxt . encoding = ( const xmlChar * ) txt_encoding ;
2004-03-28 20:12:44 +04:00
xmlSaveCtxtInit ( & ctxt ) ;
2004-03-15 16:46:37 +03:00
xmlDocContentDumpOutput ( & ctxt , out_doc ) ;
2004-03-04 16:40:59 +03:00
xmlOutputBufferFlush ( out_buff ) ;
if ( out_buff - > conv ! = NULL ) {
* doc_txt_len = out_buff - > conv - > use ;
* doc_txt_ptr = xmlStrndup ( out_buff - > conv - > content , * doc_txt_len ) ;
} else {
* doc_txt_len = out_buff - > buffer - > use ;
* doc_txt_ptr = xmlStrndup ( out_buff - > buffer - > content , * doc_txt_len ) ;
}
( void ) xmlOutputBufferClose ( out_buff ) ;
if ( ( * doc_txt_ptr = = NULL ) & & ( * doc_txt_len > 0 ) ) {
* doc_txt_len = 0 ;
xmlSaveErrMemory ( " creating output " ) ;
}
return ;
}
/**
* xmlDocDumpMemory :
* @ cur : the document
* @ mem : OUT : the memory pointer
* @ size : OUT : the memory length
*
* Dump an XML document in memory and return the # xmlChar * and it ' s size
* in bytes . It ' s up to the caller to free the memory with xmlFree ( ) .
* The resulting byte array is zero terminated , though the last 0 is not
* included in the returned size .
*/
void
xmlDocDumpMemory ( xmlDocPtr cur , xmlChar * * mem , int * size ) {
xmlDocDumpFormatMemoryEnc ( cur , mem , size , NULL , 0 ) ;
}
/**
* xmlDocDumpFormatMemory :
* @ cur : the document
* @ mem : OUT : the memory pointer
* @ size : OUT : the memory length
* @ format : should formatting spaces been added
*
*
* Dump an XML document in memory and return the # xmlChar * and it ' s size .
* It ' s up to the caller to free the memory with xmlFree ( ) .
* Note that @ format = 1 provide node indenting only if xmlIndentTreeOutput = 1
* or xmlKeepBlanksDefault ( 0 ) was called
*/
void
xmlDocDumpFormatMemory ( xmlDocPtr cur , xmlChar * * mem , int * size , int format ) {
xmlDocDumpFormatMemoryEnc ( cur , mem , size , NULL , format ) ;
}
/**
* xmlDocDumpMemoryEnc :
* @ out_doc : Document to generate XML text from
* @ doc_txt_ptr : Memory pointer for allocated XML text
* @ doc_txt_len : Length of the generated XML text
* @ txt_encoding : Character encoding to use when generating XML text
*
* Dump the current DOM tree into memory using the character encoding specified
* by the caller . Note it is up to the caller of this function to free the
* allocated memory with xmlFree ( ) .
*/
void
xmlDocDumpMemoryEnc ( xmlDocPtr out_doc , xmlChar * * doc_txt_ptr ,
int * doc_txt_len , const char * txt_encoding ) {
xmlDocDumpFormatMemoryEnc ( out_doc , doc_txt_ptr , doc_txt_len ,
txt_encoding , 0 ) ;
}
/**
* xmlDocFormatDump :
* @ f : the FILE *
* @ cur : the document
* @ format : should formatting spaces been added
*
* Dump an XML document to an open FILE .
*
* returns : the number of bytes written or - 1 in case of failure .
* Note that @ format = 1 provide node indenting only if xmlIndentTreeOutput = 1
* or xmlKeepBlanksDefault ( 0 ) was called
*/
int
xmlDocFormatDump ( FILE * f , xmlDocPtr cur , int format ) {
2004-03-15 16:46:37 +03:00
xmlSaveCtxt ctxt ;
2004-03-04 16:40:59 +03:00
xmlOutputBufferPtr buf ;
const char * encoding ;
xmlCharEncodingHandlerPtr handler = NULL ;
int ret ;
if ( cur = = NULL ) {
# ifdef DEBUG_TREE
xmlGenericError ( xmlGenericErrorContext ,
" xmlDocDump : document == NULL \n " ) ;
# endif
return ( - 1 ) ;
}
encoding = ( const char * ) cur - > encoding ;
if ( encoding ! = NULL ) {
handler = xmlFindCharEncodingHandler ( encoding ) ;
if ( handler = = NULL ) {
xmlFree ( ( char * ) cur - > encoding ) ;
cur - > encoding = NULL ;
}
}
buf = xmlOutputBufferCreateFile ( f , handler ) ;
if ( buf = = NULL ) return ( - 1 ) ;
2004-03-15 16:46:37 +03:00
memset ( & ctxt , 0 , sizeof ( ctxt ) ) ;
ctxt . doc = cur ;
ctxt . buf = buf ;
ctxt . level = 0 ;
ctxt . format = format ;
ctxt . encoding = ( const xmlChar * ) encoding ;
2004-03-28 20:12:44 +04:00
xmlSaveCtxtInit ( & ctxt ) ;
2004-03-15 16:46:37 +03:00
xmlDocContentDumpOutput ( & ctxt , cur ) ;
2004-03-04 16:40:59 +03:00
ret = xmlOutputBufferClose ( buf ) ;
return ( ret ) ;
}
/**
* xmlDocDump :
* @ f : the FILE *
* @ cur : the document
*
* Dump an XML document to an open FILE .
*
* returns : the number of bytes written or - 1 in case of failure .
*/
int
xmlDocDump ( FILE * f , xmlDocPtr cur ) {
return ( xmlDocFormatDump ( f , cur , 0 ) ) ;
}
/**
* xmlSaveFileTo :
* @ buf : an output I / O buffer
* @ cur : the document
* @ encoding : the encoding if any assuming the I / O layer handles the trancoding
*
* Dump an XML document to an I / O buffer .
*
* returns : the number of bytes written or - 1 in case of failure .
*/
int
xmlSaveFileTo ( xmlOutputBufferPtr buf , xmlDocPtr cur , const char * encoding ) {
2004-03-15 16:46:37 +03:00
xmlSaveCtxt ctxt ;
2004-03-04 16:40:59 +03:00
int ret ;
if ( buf = = NULL ) return ( 0 ) ;
2004-03-15 16:46:37 +03:00
memset ( & ctxt , 0 , sizeof ( ctxt ) ) ;
ctxt . doc = cur ;
ctxt . buf = buf ;
ctxt . level = 0 ;
ctxt . format = 0 ;
ctxt . encoding = ( const xmlChar * ) encoding ;
2004-03-28 20:12:44 +04:00
xmlSaveCtxtInit ( & ctxt ) ;
2004-03-15 16:46:37 +03:00
xmlDocContentDumpOutput ( & ctxt , cur ) ;
2004-03-04 16:40:59 +03:00
ret = xmlOutputBufferClose ( buf ) ;
return ( ret ) ;
}
/**
* xmlSaveFormatFileTo :
* @ buf : an output I / O buffer
* @ cur : the document
* @ encoding : the encoding if any assuming the I / O layer handles the trancoding
* @ format : should formatting spaces been added
*
* Dump an XML document to an I / O buffer .
2004-03-15 16:46:37 +03:00
* NOTE : the I / O buffer is closed as part of the call .
2004-03-04 16:40:59 +03:00
*
* returns : the number of bytes written or - 1 in case of failure .
*/
int
2004-03-15 16:46:37 +03:00
xmlSaveFormatFileTo ( xmlOutputBufferPtr buf , xmlDocPtr cur ,
const char * encoding , int format )
{
xmlSaveCtxt ctxt ;
int ret ;
2004-03-04 16:40:59 +03:00
2004-03-15 16:46:37 +03:00
if ( buf = = NULL )
return ( 0 ) ;
memset ( & ctxt , 0 , sizeof ( ctxt ) ) ;
ctxt . doc = cur ;
ctxt . buf = buf ;
ctxt . level = 0 ;
ctxt . format = format ;
ctxt . encoding = ( const xmlChar * ) encoding ;
2004-03-28 20:12:44 +04:00
xmlSaveCtxtInit ( & ctxt ) ;
2004-03-15 16:46:37 +03:00
xmlDocContentDumpOutput ( & ctxt , cur ) ;
ret = xmlOutputBufferClose ( buf ) ;
return ( ret ) ;
2004-03-04 16:40:59 +03:00
}
/**
* xmlSaveFormatFileEnc :
* @ filename : the filename or URL to output
* @ cur : the document being saved
* @ encoding : the name of the encoding to use or NULL .
* @ format : should formatting spaces be added .
*
* Dump an XML document to a file or an URL .
*
* Returns the number of bytes written or - 1 in case of error .
* Note that @ format = 1 provide node indenting only if xmlIndentTreeOutput = 1
* or xmlKeepBlanksDefault ( 0 ) was called
*/
int
xmlSaveFormatFileEnc ( const char * filename , xmlDocPtr cur ,
const char * encoding , int format ) {
2004-03-15 16:46:37 +03:00
xmlSaveCtxt ctxt ;
2004-03-04 16:40:59 +03:00
xmlOutputBufferPtr buf ;
xmlCharEncodingHandlerPtr handler = NULL ;
int ret ;
if ( cur = = NULL )
return ( - 1 ) ;
if ( encoding = = NULL )
encoding = ( const char * ) cur - > encoding ;
if ( encoding ! = NULL ) {
handler = xmlFindCharEncodingHandler ( encoding ) ;
if ( handler = = NULL )
return ( - 1 ) ;
}
# ifdef HAVE_ZLIB_H
if ( cur - > compression < 0 ) cur - > compression = xmlGetCompressMode ( ) ;
# endif
/*
* save the content to a temp buffer .
*/
buf = xmlOutputBufferCreateFilename ( filename , handler , cur - > compression ) ;
if ( buf = = NULL ) return ( - 1 ) ;
2004-03-15 16:46:37 +03:00
memset ( & ctxt , 0 , sizeof ( ctxt ) ) ;
ctxt . doc = cur ;
ctxt . buf = buf ;
ctxt . level = 0 ;
ctxt . format = format ;
ctxt . encoding = ( const xmlChar * ) encoding ;
2004-03-28 20:12:44 +04:00
xmlSaveCtxtInit ( & ctxt ) ;
2004-03-15 16:46:37 +03:00
xmlDocContentDumpOutput ( & ctxt , cur ) ;
2004-03-04 16:40:59 +03:00
ret = xmlOutputBufferClose ( buf ) ;
return ( ret ) ;
}
/**
* xmlSaveFileEnc :
* @ filename : the filename ( or URL )
* @ cur : the document
* @ encoding : the name of an encoding ( or NULL )
*
* Dump an XML document , converting it to the given encoding
*
* returns : the number of bytes written or - 1 in case of failure .
*/
int
xmlSaveFileEnc ( const char * filename , xmlDocPtr cur , const char * encoding ) {
return ( xmlSaveFormatFileEnc ( filename , cur , encoding , 0 ) ) ;
}
/**
* xmlSaveFormatFile :
* @ filename : the filename ( or URL )
* @ cur : the document
* @ format : should formatting spaces been added
*
* Dump an XML document to a file . Will use compression if
* compiled in and enabled . If @ filename is " - " the stdout file is
* used . If @ format is set then the document will be indented on output .
* Note that @ format = 1 provide node indenting only if xmlIndentTreeOutput = 1
* or xmlKeepBlanksDefault ( 0 ) was called
*
* returns : the number of bytes written or - 1 in case of failure .
*/
int
xmlSaveFormatFile ( const char * filename , xmlDocPtr cur , int format ) {
return ( xmlSaveFormatFileEnc ( filename , cur , NULL , format ) ) ;
}
/**
* xmlSaveFile :
* @ filename : the filename ( or URL )
* @ cur : the document
*
* Dump an XML document to a file . Will use compression if
* compiled in and enabled . If @ filename is " - " the stdout file is
* used .
* returns : the number of bytes written or - 1 in case of failure .
*/
int
xmlSaveFile ( const char * filename , xmlDocPtr cur ) {
return ( xmlSaveFormatFileEnc ( filename , cur , NULL , 0 ) ) ;
}
# endif /* LIBXML_OUTPUT_ENABLED */