Hi all, this patch adds a function that builds an XML fragment from a array. Implementation of var_dump has been taken as a skeleton. The main reason for this patch was that using DOM interface to create a long XML (approx 2.5MB) was slow.
Regards Petr Tuma
? ext/domxml/tests/domxml003.phpt Index: ext/domxml/php_domxml.c =================================================================== RCS file: /repository/php4/ext/domxml/php_domxml.c,v retrieving revision 1.235 diff -u -r1.235 php_domxml.c --- ext/domxml/php_domxml.c 18 Jan 2003 19:49:23 -0000 1.235 +++ ext/domxml/php_domxml.c 26 Jan 2003 23:13:28 -0000 @@ -276,6 +276,7 @@ #endif #if HAVE_DOMXSLT PHP_FE(domxml_xslt_version, NULL) + PHP_FE(domxml_build, NULL) PHP_FE(domxml_xslt_stylesheet, NULL) PHP_FE(domxml_xslt_stylesheet_doc, NULL) PHP_FE(domxml_xslt_stylesheet_file, NULL) @@ -5152,6 +5153,247 @@ return params; } /* }}} */ + + +/* {{{ php_domxml_build_array_element() +*/ +static int php_domxml_build_array_element(zval **zv, int num_args, va_list args, zend_hash_key *hash_key) +{ + char **buffer; + unsigned int *bufsize; + unsigned int *length; + int enc; + int indent; + int i,j; + char *p; + TSRMLS_FETCH(); + + /* get parameters */ + buffer = va_arg(args, char**); + bufsize = va_arg(args, unsigned int*); + length = va_arg(args, unsigned int*); + enc = va_arg(args, int); + indent = va_arg(args, int); + /* indention */ + if((*length+32) >= *bufsize) { + *bufsize*=2; + *buffer=erealloc(*buffer,*bufsize); + } + if(indent) + (*buffer)[(*length)++]='\n'; + /* opening tag */ + if (hash_key->nKeyLength==0) { + /* numeric key */ + memcpy(*buffer+*length,"<item index=\"",13); + (*length)+=13; + p=*buffer+*length; + for(i=0,j=hash_key->h;j;i++) { + p[i]='0'+j%10; + j/=10; + } + if(!i) + p[i++]='0'; + p[i++]='"'; + *length+=i; + } else { + if((*length+hash_key->nKeyLength+1)>=*bufsize) { + *bufsize*=2; + *buffer=erealloc(*buffer,*bufsize); + } + /* string key */ + (*buffer)[(*length)++]='<'; + memcpy(*buffer+(*length),hash_key->arKey,hash_key->nKeyLength-1); + *length+=hash_key->nKeyLength-1; + } + (*buffer)[(*length)++]='>'; + /* subtree content */ + i=php_domxml_build_var(zv, buffer,bufsize,length,enc,indent TSRMLS_CC); + /* indention */ + if(indent && i) { + if((*length+1)>+*bufsize) { + *bufsize*=2; + *buffer=erealloc(*buffer,*bufsize); + } + (*buffer)[(*length)++]='\n'; + } + /* closing tag */ + if(hash_key->nKeyLength==0) { + if((*length+hash_key->nKeyLength+7)>=*bufsize) { + *bufsize*=2; + *buffer=erealloc(*buffer,*bufsize); + } + /* numeric key */ + memcpy(*buffer+*length,"</item>",7); + *length+=7; + } else { + if((*length+hash_key->nKeyLength+2)>=*bufsize) { + *bufsize*=2; + *buffer=erealloc(*buffer,*bufsize); + } + /* string key */ + (*buffer)[(*length)++]='<'; + (*buffer)[(*length)++]='/'; + memcpy(*buffer+(*length),hash_key->arKey,hash_key->nKeyLength-1); + *length+=hash_key->nKeyLength-1; + (*buffer)[(*length)++]='>'; + } + return 0; +} +/* }}} */ + + +/* {{{ php_domxml_build_var() +*/ +static int php_domxml_build_var(zval **struc, char **buffer, unsigned int *bufsize, unsigned int *length, int enc, int indent TSRMLS_DC) +{ + HashTable *myht; + char* tmp_str; + int tmp_len; + int res=0; + static char hexcodes[16]="0123456789abcdef"; + + switch (Z_TYPE_PP(struc)) { + case IS_STRING: { + char *buf=*buffer+*length; + char *p=Z_STRVAL_PP(struc); + int i=0,j=Z_STRLEN_PP(struc); + for(;j>0;j--,p++) { + if((*length+i+6)>=*bufsize) { + *bufsize*=2; + *buffer=erealloc(*buffer,*bufsize); + buf=*buffer+*length; + } + switch(*p) { + case '<': + buf[i++]='&'; + buf[i++]='l'; + buf[i++]='t'; + buf[i++]=';'; + break; + case '>': + buf[i++]='&'; + buf[i++]='g'; + buf[i++]='t'; + buf[i++]=';'; + break; + case '&': + buf[i++]='&'; + buf[i++]='a'; + buf[i++]='m'; + buf[i++]='p'; + buf[i++]=';'; + break; + default: + /* already encoded? */ + if(!enc) { + unsigned char c=(unsigned char)*p; + if(c<32 || c>127) { + buf[i++]='&'; + buf[i++]='#'; + buf[i++]='x'; + buf[i++]=hexcodes[(c>>4)&15]; + buf[i++]=hexcodes[c&15]; + buf[i++]=';'; + } else + buf[i++]=*p; + } else { + buf[i++]=*p; + } + break; + } + } + *length+=i; + break; + } + case IS_NULL: + break; + case IS_BOOL: + if(Z_LVAL_PP(struc)) { + if((*length+1)>=*bufsize) { + *bufsize*=2; + *buffer=erealloc(*buffer,*bufsize); + } + (*buffer)[(*length)++]='1'; + } + break; + case IS_LONG: + if((*length+32)>=*bufsize) { + *bufsize*=2; + *buffer=erealloc(*buffer,*bufsize); + } + *length+=sprintf(*buffer+*length,"%ld",Z_LVAL_PP(struc)); + break; + case IS_DOUBLE: + if((*length+32)>=*bufsize) { + *bufsize*=2; + *buffer=erealloc(*buffer,*bufsize); + } + *length+=sprintf(*buffer+*length,"%G",Z_DVAL_PP(struc)); + break; + case IS_ARRAY: + res=1; + myht = Z_ARRVAL_PP(struc); + zend_hash_apply_with_arguments(myht, (apply_func_args_t) php_domxml_build_array_element, 1, buffer,bufsize,length,enc,indent); + break; + default: + if((*length+1)>=*bufsize) { + *bufsize*=2; + *buffer=erealloc(*buffer,*bufsize); + } + (*buffer)[(*length)++]='#'; + break; + } + return res; +} +/* }}} */ + + +/* {{{ proto string domxml_build(array data [, bool encoded [, bool indent]]) + Dumps an array as an XML fragment. If encoded is false all the characters + out of range 32-127 are encoded in the form of &#x??;. + If indent is true some kind of indentation is done. */ +PHP_FUNCTION(domxml_build) +{ + /* function parameters */ + zval *array; + zend_bool enc=0; + zend_bool indent=1; + /* output buffer */ + char *buffer; + /* allocated buffer size */ + unsigned int bufsize=4096; + /* actual data length */ + unsigned int length=0; + + /* get parameters */ + if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|bb", &array, &enc, &indent) == FAILURE) { + RETURN_FALSE; + } + /* init buffer */ + buffer=emalloc(bufsize); + /* fill output element */ + memcpy(buffer,"<data>",6); + length+=6; + if(indent) + buffer[length++]='\n'; + /* output array */ + php_domxml_build_var(&array,&buffer,&bufsize,&length,(int)enc,(int)indent); + /* fill the rest */ + if(length+8>=bufsize) { + bufsize+=8; + buffer=realloc(buffer,bufsize); + } + memcpy(buffer+length,"</data>\n",7); + length+=7; + if(indent) + buffer[length++]='\n'; + /* return string */ + RETVAL_STRINGL(buffer,length,1); + /* free buffer */ + efree(buffer); +} +/* }}} */ + /* {{{ proto object domxml_xslt_process(object xslstylesheet, object xmldoc [, array xslt_parameters [, bool xpath_parameters [, string profileFilename]]]) Perform an XSLT transformation */ Index: ext/domxml/php_domxml.h =================================================================== RCS file: /repository/php4/ext/domxml/php_domxml.h,v retrieving revision 1.75 diff -u -r1.75 php_domxml.h --- ext/domxml/php_domxml.h 6 Jan 2003 09:59:53 -0000 1.75 +++ ext/domxml/php_domxml.h 26 Jan 2003 23:13:29 -0000 @@ -227,6 +227,7 @@ /* DOMXSLT functions */ #if HAVE_DOMXSLT +PHP_FUNCTION(domxml_build); PHP_FUNCTION(domxml_xslt_stylesheet); PHP_FUNCTION(domxml_xslt_stylesheet_doc); PHP_FUNCTION(domxml_xslt_stylesheet_file);
--TEST-- domxml_build() basic functionality test --SKIPIF-- <?php require_once('skipif.inc'); ?> --FILE-- <?php $a=array( "title" => "Test", "rev" => 10, "working" => true, "q" => 4.5783, "lines" => array("something",false,76.5,34)); var_dump(domxml_build($a,true,false)); ?> --EXPECT-- string(200) "<data><title>Test</title><rev>10</rev><working>1</working><q>4.5783</q><lines><item index="0">something</item><item index="1"></item><item index="2">76.5</item><item index="3">34</item></lines></data>"
-- PHP Development Mailing List <http://www.php.net/> To unsubscribe, visit: http://www.php.net/unsub.php