File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / simplexml / simplexml.c
Revision 1.1.1.5 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 20:03:55 2014 UTC (10 years, 1 month ago) by misho
Branches: php, MAIN
CVS tags: v5_4_29, HEAD
php 5.4.29

    1: /*
    2:   +----------------------------------------------------------------------+
    3:   | PHP Version 5                                                        |
    4:   +----------------------------------------------------------------------+
    5:   | Copyright (c) 1997-2014 The PHP Group                                |
    6:   +----------------------------------------------------------------------+
    7:   | This source file is subject to version 3.01 of the PHP license,      |
    8:   | that is bundled with this package in the file LICENSE, and is        |
    9:   | available through the world-wide-web at the following url:           |
   10:   | http://www.php.net/license/3_01.txt                                  |
   11:   | If you did not receive a copy of the PHP license and are unable to   |
   12:   | obtain it through the world-wide-web, please send a note to          |
   13:   | license@php.net so we can mail you a copy immediately.               |
   14:   +----------------------------------------------------------------------+
   15:   | Authors: Sterling Hughes <sterling@php.net>                          |
   16:   |          Marcus Boerger <helly@php.net>                              |
   17:   |          Rob Richards <rrichards@php.net>                            |
   18:   +----------------------------------------------------------------------+
   19: */
   20: 
   21: /* $Id: simplexml.c,v 1.1.1.5 2014/06/15 20:03:55 misho Exp $ */
   22: 
   23: #ifdef HAVE_CONFIG_H
   24: #include "config.h"
   25: #endif
   26: 
   27: #include "php.h"
   28: #if HAVE_LIBXML && HAVE_SIMPLEXML
   29: 
   30: #include "php_ini.h"
   31: #include "ext/standard/info.h"
   32: #include "ext/standard/php_string.h"
   33: #include "php_simplexml.h"
   34: #include "php_simplexml_exports.h"
   35: #include "zend_exceptions.h"
   36: #include "zend_interfaces.h"
   37: #include "sxe.h"
   38: 
   39: #define SXE_ELEMENT_BY_NAME 0
   40: 
   41: zend_class_entry *sxe_class_entry = NULL;
   42: 
   43: PHP_SXE_API zend_class_entry *sxe_get_element_class_entry() /* {{{ */
   44: {
   45: 	return sxe_class_entry;
   46: }
   47: /* }}} */
   48: 
   49: #define SXE_ME(func, arg_info, flags) PHP_ME(simplexml_element, func, arg_info, flags)
   50: #define SXE_MALIAS(func, alias, arg_info, flags) PHP_MALIAS(simplexml_element, func, alias, arg_info, flags)
   51: 
   52: #define SXE_METHOD(func) PHP_METHOD(simplexml_element, func)
   53: 
   54: static php_sxe_object* php_sxe_object_new(zend_class_entry *ce TSRMLS_DC);
   55: static zend_object_value php_sxe_register_object(php_sxe_object * TSRMLS_DC);
   56: static xmlNodePtr php_sxe_reset_iterator(php_sxe_object *sxe, int use_data TSRMLS_DC);
   57: static xmlNodePtr php_sxe_iterator_fetch(php_sxe_object *sxe, xmlNodePtr node, int use_data TSRMLS_DC);
   58: static zval *sxe_get_value(zval *z TSRMLS_DC);
   59: static void php_sxe_iterator_dtor(zend_object_iterator *iter TSRMLS_DC);
   60: static int php_sxe_iterator_valid(zend_object_iterator *iter TSRMLS_DC);
   61: static void php_sxe_iterator_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC);
   62: static int php_sxe_iterator_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC);
   63: static void php_sxe_iterator_move_forward(zend_object_iterator *iter TSRMLS_DC);
   64: static void php_sxe_iterator_rewind(zend_object_iterator *iter TSRMLS_DC);
   65: 
   66: /* {{{ _node_as_zval()
   67:  */
   68: static void _node_as_zval(php_sxe_object *sxe, xmlNodePtr node, zval *value, SXE_ITER itertype, char *name, const xmlChar *nsprefix, int isprefix TSRMLS_DC)
   69: {
   70: 	php_sxe_object *subnode;
   71: 
   72: 	subnode = php_sxe_object_new(sxe->zo.ce TSRMLS_CC);
   73: 	subnode->document = sxe->document;
   74: 	subnode->document->refcount++;
   75: 	subnode->iter.type = itertype;
   76: 	if (name) {
   77: 		subnode->iter.name = xmlStrdup((xmlChar *)name);
   78: 	}
   79: 	if (nsprefix && *nsprefix) {
   80: 		subnode->iter.nsprefix = xmlStrdup(nsprefix);
   81: 		subnode->iter.isprefix = isprefix;
   82: 	}
   83: 
   84: 	php_libxml_increment_node_ptr((php_libxml_node_object *)subnode, node, NULL TSRMLS_CC);
   85: 
   86: 	value->type = IS_OBJECT;
   87: 	value->value.obj = php_sxe_register_object(subnode TSRMLS_CC);
   88: }
   89: /* }}} */
   90: 
   91: #define APPEND_PREV_ELEMENT(__c, __v) \
   92: 	if ((__c) == 1) { \
   93: 		array_init(return_value); \
   94: 		add_next_index_zval(return_value, __v); \
   95: 	}
   96: 
   97: #define APPEND_CUR_ELEMENT(__c, __v) \
   98: 	if (++(__c) > 1) { \
   99: 		add_next_index_zval(return_value, __v); \
  100: 	}
  101: 
  102: #define GET_NODE(__s, __n) { \
  103: 	if ((__s)->node && (__s)->node->node) { \
  104: 		__n = (__s)->node->node; \
  105: 	} else { \
  106: 		__n = NULL; \
  107: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Node no longer exists"); \
  108: 	} \
  109: }
  110: 
  111: static xmlNodePtr php_sxe_get_first_node(php_sxe_object *sxe, xmlNodePtr node TSRMLS_DC) /* {{{ */
  112: {
  113: 	php_sxe_object *intern;
  114: 	xmlNodePtr retnode = NULL;
  115: 
  116: 	if (sxe && sxe->iter.type != SXE_ITER_NONE) {
  117: 		php_sxe_reset_iterator(sxe, 1 TSRMLS_CC);
  118: 		if (sxe->iter.data) {
  119: 			intern = (php_sxe_object *)zend_object_store_get_object(sxe->iter.data TSRMLS_CC);
  120: 			GET_NODE(intern, retnode)
  121: 		}
  122: 		return retnode;
  123: 	} else {
  124: 		return node;
  125: 	}
  126: }
  127: /* }}} */
  128: 
  129: static inline int match_ns(php_sxe_object *sxe, xmlNodePtr node, xmlChar *name, int prefix) /* {{{ */
  130: {
  131: 	if (name == NULL && (node->ns == NULL || node->ns->prefix == NULL)) {
  132: 		return 1;
  133: 	}
  134: 
  135: 	if (node->ns && !xmlStrcmp(prefix ? node->ns->prefix : node->ns->href, name)) {
  136: 		return 1;
  137: 	}
  138: 
  139: 	return 0;
  140: }
  141: /* }}} */
  142: 
  143: static xmlNodePtr sxe_get_element_by_offset(php_sxe_object *sxe, long offset, xmlNodePtr node, long *cnt) /* {{{ */
  144: {
  145: 	long nodendx = 0;
  146: 
  147: 	if (sxe->iter.type == SXE_ITER_NONE) {
  148: 		if (offset == 0) {
  149: 			if (cnt) {
  150: 				*cnt = 0;
  151: 			}
  152: 			return node;
  153: 		} else {
  154: 			return NULL;
  155: 		}
  156: 	}
  157: 	while (node && nodendx <= offset) {
  158: 		SKIP_TEXT(node)
  159: 		if (node->type == XML_ELEMENT_NODE && match_ns(sxe, node, sxe->iter.nsprefix, sxe->iter.isprefix)) {
  160: 			if (sxe->iter.type == SXE_ITER_CHILD || (
  161: 				sxe->iter.type == SXE_ITER_ELEMENT && !xmlStrcmp(node->name, sxe->iter.name))) {
  162: 				if (nodendx == offset) {
  163: 					break;
  164: 				}
  165: 				nodendx++;
  166: 			}
  167: 		}
  168: next_iter:
  169: 		node = node->next;
  170: 	}
  171: 
  172: 	if (cnt) {
  173: 		*cnt = nodendx;
  174: 	}
  175: 
  176: 	return node;
  177: }
  178: /* }}} */
  179: 
  180: static xmlNodePtr sxe_find_element_by_name(php_sxe_object *sxe, xmlNodePtr node, xmlChar *name TSRMLS_DC) /* {{{ */
  181: {
  182: 	while (node) {
  183: 		SKIP_TEXT(node)
  184: 		if (node->type == XML_ELEMENT_NODE && match_ns(sxe, node, sxe->iter.nsprefix, sxe->iter.isprefix)) {
  185: 			if (!xmlStrcmp(node->name, name)) {
  186: 				return node;
  187: 			}
  188: 		}
  189: next_iter:
  190: 		node = node->next;
  191: 	}
  192: 	return NULL;
  193: } /* }}} */
  194: 
  195: static xmlNodePtr sxe_get_element_by_name(php_sxe_object *sxe, xmlNodePtr node, char **name, SXE_ITER *type TSRMLS_DC) /* {{{ */
  196: {
  197: 	int         orgtype;
  198: 	xmlNodePtr  orgnode = node;
  199: 	xmlNodePtr  retnode = NULL;
  200: 
  201: 	if (sxe->iter.type != SXE_ITER_ATTRLIST)
  202: 	{
  203: 		orgtype = sxe->iter.type;
  204: 		if (sxe->iter.type == SXE_ITER_NONE) {
  205: 			sxe->iter.type = SXE_ITER_CHILD;
  206: 		}
  207: 		node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
  208: 		sxe->iter.type = orgtype;
  209: 	}
  210: 
  211: 	if (sxe->iter.type == SXE_ITER_ELEMENT) {
  212: 		orgnode = sxe_find_element_by_name(sxe, node, sxe->iter.name TSRMLS_CC);
  213: 		if (!orgnode) {
  214: 			return NULL;
  215: 		}
  216: 		node = orgnode->children;
  217: 	}
  218: 
  219: 	while (node) {
  220: 		SKIP_TEXT(node)
  221: 		if (node->type == XML_ELEMENT_NODE && match_ns(sxe, node, sxe->iter.nsprefix, sxe->iter.isprefix)) {
  222: 			if (!xmlStrcmp(node->name, (xmlChar *)*name)) {
  223: 				if (1||retnode)
  224: 				{
  225: 					*type = SXE_ITER_ELEMENT;
  226: 					return orgnode;
  227: 				}
  228: 				retnode = node;
  229: 			}
  230: 		}
  231: next_iter:
  232: 		node = node->next;
  233: 	}
  234: 
  235: 	if (retnode)
  236: 	{
  237: 		*type = SXE_ITER_NONE;
  238: 		*name = NULL;
  239: 		return retnode;
  240: 	}
  241: 
  242: 	return NULL;
  243: }
  244: /* }}} */
  245: 
  246: /* {{{ sxe_prop_dim_read()
  247:  */
  248: static zval * sxe_prop_dim_read(zval *object, zval *member, zend_bool elements, zend_bool attribs, int type TSRMLS_DC)
  249: {
  250: 	zval           *return_value;
  251: 	php_sxe_object *sxe;
  252: 	char           *name;
  253: 	xmlNodePtr      node;
  254: 	xmlAttrPtr      attr = NULL;
  255: 	zval            tmp_zv;
  256: 	int             nodendx = 0;
  257: 	int             test = 0;
  258: 
  259: 	sxe = php_sxe_fetch_object(object TSRMLS_CC);
  260: 
  261: 	if (!member || Z_TYPE_P(member) == IS_LONG) {
  262: 		if (sxe->iter.type != SXE_ITER_ATTRLIST) {
  263: 			attribs = 0;
  264: 			elements = 1;
  265: 		} else if (!member) {
  266: 			/* This happens when the user did: $sxe[]->foo = $value */
  267: 			php_error_docref(NULL TSRMLS_CC, E_ERROR, "Cannot create unnamed attribute");
  268: 			return NULL;
  269: 		}
  270: 		name = NULL;
  271: 	} else {
  272: 		if (Z_TYPE_P(member) != IS_STRING) {
  273: 			tmp_zv = *member;
  274: 			zval_copy_ctor(&tmp_zv);
  275: 			member = &tmp_zv;
  276: 			convert_to_string(member);
  277: 		}
  278: 		name = Z_STRVAL_P(member);
  279: 	}
  280: 
  281: 	GET_NODE(sxe, node);
  282: 
  283: 	if (sxe->iter.type == SXE_ITER_ATTRLIST) {
  284: 		attribs = 1;
  285: 		elements = 0;
  286: 		node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
  287: 		attr = (xmlAttrPtr)node;
  288: 		test = sxe->iter.name != NULL;
  289: 	} else if (sxe->iter.type != SXE_ITER_CHILD) {
  290: 		node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
  291: 		attr = node ? node->properties : NULL;
  292: 		test = 0;
  293: 		if (!member && node && node->parent &&
  294: 		    node->parent->type == XML_DOCUMENT_NODE) {
  295: 			/* This happens when the user did: $sxe[]->foo = $value */
  296: 			php_error_docref(NULL TSRMLS_CC, E_ERROR, "Cannot create unnamed attribute");
  297: 			return NULL;
  298: 		}
  299: 	}
  300: 
  301: 	MAKE_STD_ZVAL(return_value);
  302: 	ZVAL_NULL(return_value);
  303: 
  304: 	if (node) {
  305: 		if (attribs) {
  306: 			if (Z_TYPE_P(member) != IS_LONG || sxe->iter.type == SXE_ITER_ATTRLIST) {
  307: 				if (Z_TYPE_P(member) == IS_LONG) {
  308: 					while (attr && nodendx <= Z_LVAL_P(member)) {
  309: 						if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
  310: 							if (nodendx == Z_LVAL_P(member)) {
  311: 								_node_as_zval(sxe, (xmlNodePtr) attr, return_value, SXE_ITER_NONE, NULL, sxe->iter.nsprefix, sxe->iter.isprefix TSRMLS_CC);
  312: 								break;
  313: 							}
  314: 							nodendx++;
  315: 						}
  316: 						attr = attr->next;
  317: 					}
  318: 				} else {
  319: 					while (attr) {
  320: 						if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && !xmlStrcmp(attr->name, (xmlChar *)name) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
  321: 							_node_as_zval(sxe, (xmlNodePtr) attr, return_value, SXE_ITER_NONE, NULL, sxe->iter.nsprefix, sxe->iter.isprefix TSRMLS_CC);
  322: 							break;
  323: 						}
  324: 						attr = attr->next;
  325: 					}
  326: 				}
  327: 			}
  328: 		}
  329: 
  330: 		if (elements) {
  331: 			if (!sxe->node) {
  332: 				php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, node, NULL TSRMLS_CC);
  333: 			}
  334: 			if (!member || Z_TYPE_P(member) == IS_LONG) {
  335: 				long cnt = 0;
  336: 				xmlNodePtr mynode = node;
  337: 
  338: 				if (sxe->iter.type == SXE_ITER_CHILD) {
  339: 					node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
  340: 				}
  341: 				if (sxe->iter.type == SXE_ITER_NONE) {
  342: 					if (member && Z_LVAL_P(member) > 0) {
  343: 						php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot add element %s number %ld when only 0 such elements exist", mynode->name, Z_LVAL_P(member));
  344: 					}
  345: 				} else if (member) {
  346: 					node = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node, &cnt);
  347: 				} else {
  348: 					node = NULL;
  349: 				}
  350: 				if (node) {
  351: 					_node_as_zval(sxe, node, return_value, SXE_ITER_NONE, NULL, sxe->iter.nsprefix, sxe->iter.isprefix TSRMLS_CC);
  352: 				} else if (type == BP_VAR_W || type == BP_VAR_RW) {
  353: 					if (member && cnt < Z_LVAL_P(member)) {
  354: 						php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot add element %s number %ld when only %ld such elements exist", mynode->name, Z_LVAL_P(member), cnt);
  355: 					}
  356: 					node = xmlNewTextChild(mynode->parent, mynode->ns, mynode->name, NULL);
  357: 					_node_as_zval(sxe, node, return_value, SXE_ITER_NONE, NULL, sxe->iter.nsprefix, sxe->iter.isprefix TSRMLS_CC);
  358: 				}
  359: 			} else {
  360: #if SXE_ELEMENT_BY_NAME
  361: 				int newtype;
  362: 
  363: 				GET_NODE(sxe, node);
  364: 				node = sxe_get_element_by_name(sxe, node, &name, &newtype TSRMLS_CC);
  365: 				if (node) {
  366: 					_node_as_zval(sxe, node, return_value, newtype, name, sxe->iter.nsprefix, sxe->iter.isprefix TSRMLS_CC);
  367: 				}
  368: #else
  369: 				_node_as_zval(sxe, node, return_value, SXE_ITER_ELEMENT, name, sxe->iter.nsprefix, sxe->iter.isprefix TSRMLS_CC);
  370: #endif
  371: 			}
  372: 		}
  373: 	}
  374: 
  375: 	Z_SET_REFCOUNT_P(return_value, 0);
  376: 	Z_UNSET_ISREF_P(return_value);
  377: 
  378: 	if (member == &tmp_zv) {
  379: 		zval_dtor(&tmp_zv);
  380: 	}
  381: 	if (Z_TYPE_P(return_value) == IS_NULL) {
  382: 		FREE_ZVAL(return_value);
  383: 		return_value = &EG(uninitialized_zval);
  384: 	}
  385: 
  386: 	return return_value;
  387: }
  388: /* }}} */
  389: 
  390: /* {{{ sxe_property_read()
  391:  */
  392: static zval * sxe_property_read(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
  393: {
  394: 	return sxe_prop_dim_read(object, member, 1, 0, type TSRMLS_CC);
  395: }
  396: /* }}} */
  397: 
  398: /* {{{ sxe_dimension_read()
  399:  */
  400: static zval * sxe_dimension_read(zval *object, zval *offset, int type TSRMLS_DC)
  401: {
  402: 	return sxe_prop_dim_read(object, offset, 0, 1, type TSRMLS_CC);
  403: }
  404: /* }}} */
  405: 
  406: /* {{{ change_node_zval()
  407:  */
  408: static void change_node_zval(xmlNodePtr node, zval *value TSRMLS_DC)
  409: {
  410: 	zval value_copy;
  411: 	xmlChar *buffer;
  412: 	int buffer_len;
  413: 
  414: 	if (!value)
  415: 	{
  416: 		xmlNodeSetContentLen(node, (xmlChar *)"", 0);
  417: 		return;
  418: 	}
  419: 	switch (Z_TYPE_P(value)) {
  420: 		case IS_LONG:
  421: 		case IS_BOOL:
  422: 		case IS_DOUBLE:
  423: 		case IS_NULL:
  424: 			if (Z_REFCOUNT_P(value) > 1) {
  425: 				value_copy = *value;
  426: 				zval_copy_ctor(&value_copy);
  427: 				value = &value_copy;
  428: 			}
  429: 			convert_to_string(value);
  430: 			/* break missing intentionally */
  431: 		case IS_STRING:
  432: 			buffer = xmlEncodeEntitiesReentrant(node->doc, (xmlChar *)Z_STRVAL_P(value));
  433: 			buffer_len = xmlStrlen(buffer);
  434: 			/* check for NULL buffer in case of memory error in xmlEncodeEntitiesReentrant */
  435: 			if (buffer) {
  436: 				xmlNodeSetContentLen(node, buffer, buffer_len);
  437: 				xmlFree(buffer);
  438: 			}
  439: 			if (value == &value_copy) {
  440: 				zval_dtor(value);
  441: 			}
  442: 			break;
  443: 		default:
  444: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "It is not possible to assign complex types to nodes");
  445: 			break;
  446: 	}
  447: }
  448: /* }}} */
  449: 
  450: /* {{{ sxe_property_write()
  451:  */
  452: static int sxe_prop_dim_write(zval *object, zval *member, zval *value, zend_bool elements, zend_bool attribs, xmlNodePtr *pnewnode TSRMLS_DC)
  453: {
  454: 	php_sxe_object *sxe;
  455: 	xmlNodePtr      node;
  456: 	xmlNodePtr      newnode = NULL;
  457: 	xmlNodePtr      mynode;
  458: 	xmlNodePtr		tempnode;
  459: 	xmlAttrPtr      attr = NULL;
  460: 	int             counter = 0;
  461: 	int             is_attr = 0;
  462: 	int				nodendx = 0;
  463: 	int             test = 0;
  464: 	int				new_value = 0;
  465: 	long            cnt = 0;
  466: 	int				retval = SUCCESS;
  467: 	zval            tmp_zv, trim_zv, value_copy;
  468: 
  469: 	sxe = php_sxe_fetch_object(object TSRMLS_CC);
  470: 
  471: 	if (!member || Z_TYPE_P(member) == IS_LONG) {
  472: 		if (sxe->iter.type != SXE_ITER_ATTRLIST) {
  473: 			attribs = 0;
  474: 			elements = 1;
  475: 		} else if (!member) {
  476: 			/* This happens when the user did: $sxe[] = $value
  477: 			 * and could also be E_PARSE, but we use this only during parsing
  478: 			 * and this is during runtime.
  479: 			 */
  480: 			php_error_docref(NULL TSRMLS_CC, E_ERROR, "Cannot create unnamed attribute");
  481: 			return FAILURE;
  482: 		}
  483: 	} else {
  484: 		if (Z_TYPE_P(member) != IS_STRING) {
  485: 			trim_zv = *member;
  486: 			zval_copy_ctor(&trim_zv);
  487: 			convert_to_string(&trim_zv);
  488: 			php_trim(Z_STRVAL(trim_zv), Z_STRLEN(trim_zv), NULL, 0, &tmp_zv, 3 TSRMLS_CC);
  489: 			zval_dtor(&trim_zv);
  490: 			member = &tmp_zv;
  491: 		}
  492: 
  493: 		if (!Z_STRLEN_P(member)) {
  494: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot write or create unnamed %s", attribs ? "attribute" : "element");
  495: 			if (member == &tmp_zv) {
  496: 				zval_dtor(&tmp_zv);
  497: 			}
  498: 			return FAILURE;
  499: 		}
  500: 	}
  501: 
  502: 	GET_NODE(sxe, node);
  503: 
  504: 	if (sxe->iter.type == SXE_ITER_ATTRLIST) {
  505: 		attribs = 1;
  506: 		elements = 0;
  507: 		node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
  508: 		attr = (xmlAttrPtr)node;
  509: 		test = sxe->iter.name != NULL;
  510: 	} else if (sxe->iter.type != SXE_ITER_CHILD) {
  511: 		mynode = node;
  512: 		node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
  513: 		attr = node ? node->properties : NULL;
  514: 		test = 0;
  515: 		if (!member && node && node->parent &&
  516: 		    node->parent->type == XML_DOCUMENT_NODE) {
  517: 			/* This happens when the user did: $sxe[] = $value
  518: 			 * and could also be E_PARSE, but we use this only during parsing
  519: 			 * and this is during runtime.
  520: 			 */
  521: 			php_error_docref(NULL TSRMLS_CC, E_ERROR, "Cannot create unnamed attribute");
  522: 			return FAILURE;
  523: 		}
  524: 		if (attribs && !node && sxe->iter.type == SXE_ITER_ELEMENT) {
  525: 			node = xmlNewChild(mynode, mynode->ns, sxe->iter.name, NULL);
  526: 			attr = node->properties;
  527: 		}
  528: 	}
  529: 
  530: 	mynode = node;
  531: 
  532: 	if (value) {
  533: 		switch (Z_TYPE_P(value)) {
  534: 			case IS_LONG:
  535: 			case IS_BOOL:
  536: 			case IS_DOUBLE:
  537: 			case IS_NULL:
  538: 				if (Z_REFCOUNT_P(value) > 1) {
  539: 					value_copy = *value;
  540: 					zval_copy_ctor(&value_copy);
  541: 					value = &value_copy;
  542: 				}
  543: 				convert_to_string(value);
  544: 				break;
  545: 			case IS_STRING:
  546: 				break;
  547: 			case IS_OBJECT:
  548: 				if (Z_OBJCE_P(value) == sxe_class_entry) {
  549: 					value = sxe_get_value(value TSRMLS_CC);
  550: 					INIT_PZVAL(value);
  551: 					new_value = 1;
  552: 					break;
  553: 				}
  554: 				/* break is missing intentionally */
  555: 			default:
  556: 				if (member == &tmp_zv) {
  557: 					zval_dtor(&tmp_zv);
  558: 				}
  559: 				zend_error(E_WARNING, "It is not yet possible to assign complex types to %s", attribs ? "attributes" : "properties");
  560: 				return FAILURE;
  561: 		}
  562: 	}
  563: 
  564: 	if (node) {
  565: 		if (attribs) {
  566: 			if (Z_TYPE_P(member) == IS_LONG) {
  567: 				while (attr && nodendx <= Z_LVAL_P(member)) {
  568: 					if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
  569: 						if (nodendx == Z_LVAL_P(member)) {
  570: 							is_attr = 1;
  571: 							++counter;
  572: 							break;
  573: 						}
  574: 						nodendx++;
  575: 					}
  576: 					attr = attr->next;
  577: 				}
  578: 			} else {
  579: 				while (attr) {
  580: 					if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && !xmlStrcmp(attr->name, (xmlChar *)Z_STRVAL_P(member)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
  581: 						is_attr = 1;
  582: 						++counter;
  583: 						break;
  584: 					}
  585: 					attr = attr->next;
  586: 				}
  587: 			}
  588: 
  589: 		}
  590: 
  591: 		if (elements) {
  592: 			if (!member || Z_TYPE_P(member) == IS_LONG) {
  593: 				if (node->type == XML_ATTRIBUTE_NODE) {
  594: 					php_error_docref(NULL TSRMLS_CC, E_ERROR, "Cannot create duplicate attribute");
  595: 					return FAILURE;
  596: 				}
  597: 
  598: 				if (sxe->iter.type == SXE_ITER_NONE) {
  599: 					newnode = node;
  600: 					++counter;
  601: 					if (member && Z_LVAL_P(member) > 0) {
  602: 						php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot add element %s number %ld when only 0 such elements exist", mynode->name, Z_LVAL_P(member));
  603: 						retval = FAILURE;
  604: 					}
  605: 				} else if (member) {
  606: 					newnode = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node, &cnt);
  607: 					if (newnode) {
  608: 						++counter;
  609: 					}
  610: 				}
  611: 			} else {
  612: 				node = node->children;
  613: 				while (node) {
  614: 					SKIP_TEXT(node);
  615: 
  616: 					if (!xmlStrcmp(node->name, (xmlChar *)Z_STRVAL_P(member))) {
  617: 						newnode = node;
  618: 						++counter;
  619: 					}
  620: 
  621: next_iter:
  622: 					node = node->next;
  623: 				}
  624: 			}
  625: 		}
  626: 
  627: 		if (counter == 1) {
  628: 			if (is_attr) {
  629: 				newnode = (xmlNodePtr) attr;
  630: 			}
  631: 			if (value) {
  632: 				while ((tempnode = (xmlNodePtr) newnode->children)) {
  633: 					xmlUnlinkNode(tempnode);
  634: 					php_libxml_node_free_resource((xmlNodePtr) tempnode TSRMLS_CC);
  635: 				}
  636: 				change_node_zval(newnode, value TSRMLS_CC);
  637: 			}
  638: 		} else if (counter > 1) {
  639: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot assign to an array of nodes (duplicate subnodes or attr detected)");
  640: 			retval = FAILURE;
  641: 		} else if (elements) {
  642: 			if (!node) {
  643: 				if (!member || Z_TYPE_P(member) == IS_LONG) {
  644: 					newnode = xmlNewTextChild(mynode->parent, mynode->ns, mynode->name, value ? (xmlChar *)Z_STRVAL_P(value) : NULL);
  645: 				} else {
  646: 					newnode = xmlNewTextChild(mynode, mynode->ns, (xmlChar *)Z_STRVAL_P(member), value ? (xmlChar *)Z_STRVAL_P(value) : NULL);
  647: 				}
  648: 			} else if (!member || Z_TYPE_P(member) == IS_LONG) {
  649: 				if (member && cnt < Z_LVAL_P(member)) {
  650: 					php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot add element %s number %ld when only %ld such elements exist", mynode->name, Z_LVAL_P(member), cnt);
  651: 					retval = FAILURE;
  652: 				}
  653: 				newnode = xmlNewTextChild(mynode->parent, mynode->ns, mynode->name, value ? (xmlChar *)Z_STRVAL_P(value) : NULL);
  654: 			}
  655: 		} else if (attribs) {
  656: 			if (Z_TYPE_P(member) == IS_LONG) {
  657: 				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot change attribute number %ld when only %d attributes exist", Z_LVAL_P(member), nodendx);
  658: 				retval = FAILURE;
  659: 			} else {
  660: 				newnode = (xmlNodePtr)xmlNewProp(node, (xmlChar *)Z_STRVAL_P(member), value ? (xmlChar *)Z_STRVAL_P(value) : NULL);
  661: 			}
  662: 		}
  663: 	}
  664: 
  665: 	if (member == &tmp_zv) {
  666: 		zval_dtor(&tmp_zv);
  667: 	}
  668: 	if (pnewnode) {
  669: 		*pnewnode = newnode;
  670: 	}
  671: 	if (value && value == &value_copy) {
  672: 		zval_dtor(value);
  673: 	}
  674: 	if (new_value) {
  675: 		zval_ptr_dtor(&value);
  676: 	}
  677: 	return retval;
  678: }
  679: /* }}} */
  680: 
  681: /* {{{ sxe_property_write()
  682:  */
  683: static void sxe_property_write(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
  684: {
  685: 	sxe_prop_dim_write(object, member, value, 1, 0, NULL TSRMLS_CC);
  686: }
  687: /* }}} */
  688: 
  689: /* {{{ sxe_dimension_write()
  690:  */
  691: static void sxe_dimension_write(zval *object, zval *offset, zval *value TSRMLS_DC)
  692: {
  693: 	sxe_prop_dim_write(object, offset, value, 0, 1, NULL TSRMLS_CC);
  694: }
  695: /* }}} */
  696: 
  697: static zval** sxe_property_get_adr(zval *object, zval *member, const zend_literal *key TSRMLS_DC) /* {{{ */
  698: {
  699: 	php_sxe_object *sxe;
  700: 	xmlNodePtr      node;
  701: 	zval           *return_value;
  702: 	char           *name;
  703: 	SXE_ITER        type;
  704: 
  705: 	sxe = php_sxe_fetch_object(object TSRMLS_CC);
  706: 
  707: 	GET_NODE(sxe, node);
  708: 	convert_to_string(member);
  709: 	name = Z_STRVAL_P(member);
  710: 	node = sxe_get_element_by_name(sxe, node, &name, &type TSRMLS_CC);
  711: 	if (node) {
  712: 		return NULL;
  713: 	}
  714: 	if (sxe_prop_dim_write(object, member, NULL, 1, 0, &node TSRMLS_CC) != SUCCESS) {
  715: 		return NULL;
  716: 	}
  717: 	type = SXE_ITER_NONE;
  718: 	name = NULL;
  719: 
  720: 	MAKE_STD_ZVAL(return_value);
  721: 	_node_as_zval(sxe, node, return_value, type, name, sxe->iter.nsprefix, sxe->iter.isprefix TSRMLS_CC);
  722: 
  723: 	sxe = php_sxe_fetch_object(return_value TSRMLS_CC);
  724: 	if (sxe->tmp) {
  725: 		zval_ptr_dtor(&sxe->tmp);
  726: 	}
  727: 	sxe->tmp = return_value;
  728: 	Z_SET_ISREF_P(return_value);
  729: 
  730: 	return &sxe->tmp;
  731: }
  732: /* }}} */
  733: 
  734: /* {{{ sxe_prop_dim_exists()
  735:  */
  736: static int sxe_prop_dim_exists(zval *object, zval *member, int check_empty, zend_bool elements, zend_bool attribs TSRMLS_DC)
  737: {
  738: 	php_sxe_object *sxe;
  739: 	xmlNodePtr      node;
  740: 	xmlAttrPtr      attr = NULL;
  741: 	int				exists = 0;
  742: 	int             test = 0;
  743: 	zval            tmp_zv;
  744: 
  745: 	if (Z_TYPE_P(member) != IS_STRING && Z_TYPE_P(member) != IS_LONG) {
  746: 		tmp_zv = *member;
  747: 		zval_copy_ctor(&tmp_zv);
  748: 		member = &tmp_zv;
  749: 		convert_to_string(member);
  750: 	}
  751: 
  752: 	sxe = php_sxe_fetch_object(object TSRMLS_CC);
  753: 
  754: 	GET_NODE(sxe, node);
  755: 
  756: 	if (Z_TYPE_P(member) == IS_LONG) {
  757: 		if (sxe->iter.type != SXE_ITER_ATTRLIST) {
  758: 			attribs = 0;
  759: 			elements = 1;
  760: 			if (sxe->iter.type == SXE_ITER_CHILD) {
  761: 				node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
  762: 			}
  763: 		}
  764: 	}
  765: 
  766: 	if (sxe->iter.type == SXE_ITER_ATTRLIST) {
  767: 		attribs = 1;
  768: 		elements = 0;
  769: 		node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
  770: 		attr = (xmlAttrPtr)node;
  771: 		test = sxe->iter.name != NULL;
  772: 	} else if (sxe->iter.type != SXE_ITER_CHILD) {
  773: 		node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
  774: 		attr = node ? node->properties : NULL;
  775: 		test = 0;
  776: 	}
  777: 
  778: 	if (node) {
  779: 		if (attribs) {
  780: 			if (Z_TYPE_P(member) == IS_LONG) {
  781: 				int	nodendx = 0;
  782: 
  783: 				while (attr && nodendx <= Z_LVAL_P(member)) {
  784: 					if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
  785: 						if (nodendx == Z_LVAL_P(member)) {
  786: 							exists = 1;
  787: 							break;
  788: 						}
  789: 						nodendx++;
  790: 					}
  791: 					attr = attr->next;
  792: 				}
  793: 			} else {
  794: 				while (attr) {
  795: 					if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && !xmlStrcmp(attr->name, (xmlChar *)Z_STRVAL_P(member)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
  796: 						exists = 1;
  797: 						break;
  798: 					}
  799: 
  800: 					attr = attr->next;
  801: 				}
  802: 			}
  803: 			if (exists && check_empty == 1 &&
  804: 				(!attr->children || !attr->children->content || !attr->children->content[0] || !xmlStrcmp(attr->children->content, "0")) ) {
  805: 				/* Attribute with no content in it's text node */
  806: 				exists = 0;
  807: 			}
  808: 		}
  809: 
  810: 		if (elements) {
  811: 			if (Z_TYPE_P(member) == IS_LONG) {
  812: 				if (sxe->iter.type == SXE_ITER_CHILD) {
  813: 					node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
  814: 				}
  815: 				node = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node, NULL);
  816: 			}
  817: 			else {
  818: 				node = node->children;
  819: 				while (node) {
  820: 					xmlNodePtr nnext;
  821: 					nnext = node->next;
  822: 					if ((node->type == XML_ELEMENT_NODE) && !xmlStrcmp(node->name, (xmlChar *)Z_STRVAL_P(member))) {
  823: 						break;
  824: 					}
  825: 					node = nnext;
  826: 				}
  827: 			}
  828: 			if (node) {
  829: 				exists = 1;
  830:                                 if (check_empty == 1 &&
  831: 					(!node->children || (node->children->type == XML_TEXT_NODE && !node->children->next &&
  832: 						(!node->children->content || !node->children->content[0] || !xmlStrcmp(node->children->content, "0")))) ) {
  833: 					exists = 0;
  834: 				}
  835: 			}
  836: 		}
  837: 	}
  838: 
  839: 	if (member == &tmp_zv) {
  840: 		zval_dtor(&tmp_zv);
  841: 	}
  842: 
  843: 	return exists;
  844: }
  845: /* }}} */
  846: 
  847: /* {{{ sxe_property_exists()
  848:  */
  849: static int sxe_property_exists(zval *object, zval *member, int check_empty, const zend_literal *key TSRMLS_DC)
  850: {
  851: 	return sxe_prop_dim_exists(object, member, check_empty, 1, 0 TSRMLS_CC);
  852: }
  853: /* }}} */
  854: 
  855: /* {{{ sxe_property_exists()
  856:  */
  857: static int sxe_dimension_exists(zval *object, zval *member, int check_empty TSRMLS_DC)
  858: {
  859: 	return sxe_prop_dim_exists(object, member, check_empty, 0, 1 TSRMLS_CC);
  860: }
  861: /* }}} */
  862: 
  863: /* {{{ sxe_prop_dim_delete()
  864:  */
  865: static void sxe_prop_dim_delete(zval *object, zval *member, zend_bool elements, zend_bool attribs TSRMLS_DC)
  866: {
  867: 	php_sxe_object *sxe;
  868: 	xmlNodePtr      node;
  869: 	xmlNodePtr      nnext;
  870: 	xmlAttrPtr      attr = NULL;
  871: 	xmlAttrPtr      anext;
  872: 	zval            tmp_zv;
  873: 	int             test = 0;
  874: 
  875: 	if (Z_TYPE_P(member) != IS_STRING && Z_TYPE_P(member) != IS_LONG) {
  876: 		tmp_zv = *member;
  877: 		zval_copy_ctor(&tmp_zv);
  878: 		member = &tmp_zv;
  879: 		convert_to_string(member);
  880: 	}
  881: 
  882: 	sxe = php_sxe_fetch_object(object TSRMLS_CC);
  883: 
  884: 	GET_NODE(sxe, node);
  885: 
  886: 	if (Z_TYPE_P(member) == IS_LONG) {
  887: 		if (sxe->iter.type != SXE_ITER_ATTRLIST) {
  888: 			attribs = 0;
  889: 			elements = 1;
  890: 			if (sxe->iter.type == SXE_ITER_CHILD) {
  891: 				node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
  892: 			}
  893: 		}
  894: 	}
  895: 
  896: 	if (sxe->iter.type == SXE_ITER_ATTRLIST) {
  897: 		attribs = 1;
  898: 		elements = 0;
  899: 		node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
  900: 		attr = (xmlAttrPtr)node;
  901: 		test = sxe->iter.name != NULL;
  902: 	} else if (sxe->iter.type != SXE_ITER_CHILD) {
  903: 		node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
  904: 		attr = node ? node->properties : NULL;
  905: 		test = 0;
  906: 	}
  907: 
  908: 	if (node) {
  909: 		if (attribs) {
  910: 			if (Z_TYPE_P(member) == IS_LONG) {
  911: 				int	nodendx = 0;
  912: 
  913: 				while (attr && nodendx <= Z_LVAL_P(member)) {
  914: 					if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
  915: 						if (nodendx == Z_LVAL_P(member)) {
  916: 							xmlUnlinkNode((xmlNodePtr) attr);
  917: 							php_libxml_node_free_resource((xmlNodePtr) attr TSRMLS_CC);
  918: 							break;
  919: 						}
  920: 						nodendx++;
  921: 					}
  922: 					attr = attr->next;
  923: 				}
  924: 			} else {
  925: 				while (attr) {
  926: 					anext = attr->next;
  927: 					if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && !xmlStrcmp(attr->name, (xmlChar *)Z_STRVAL_P(member)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
  928: 						xmlUnlinkNode((xmlNodePtr) attr);
  929: 						php_libxml_node_free_resource((xmlNodePtr) attr TSRMLS_CC);
  930: 						break;
  931: 					}
  932: 					attr = anext;
  933: 				}
  934: 			}
  935: 		}
  936: 
  937: 		if (elements) {
  938: 			if (Z_TYPE_P(member) == IS_LONG) {
  939: 				if (sxe->iter.type == SXE_ITER_CHILD) {
  940: 					node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
  941: 				}
  942: 				node = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node, NULL);
  943: 				if (node) {
  944: 					xmlUnlinkNode(node);
  945: 					php_libxml_node_free_resource(node TSRMLS_CC);
  946: 				}
  947: 			} else {
  948: 				node = node->children;
  949: 				while (node) {
  950: 					nnext = node->next;
  951: 
  952: 					SKIP_TEXT(node);
  953: 
  954: 					if (!xmlStrcmp(node->name, (xmlChar *)Z_STRVAL_P(member))) {
  955: 						xmlUnlinkNode(node);
  956: 						php_libxml_node_free_resource(node TSRMLS_CC);
  957: 					}
  958: 
  959: next_iter:
  960: 					node = nnext;
  961: 				}
  962: 			}
  963: 		}
  964: 	}
  965: 
  966: 	if (member == &tmp_zv) {
  967: 		zval_dtor(&tmp_zv);
  968: 	}
  969: }
  970: /* }}} */
  971: 
  972: /* {{{ sxe_property_delete()
  973:  */
  974: static void sxe_property_delete(zval *object, zval *member, const zend_literal *key TSRMLS_DC)
  975: {
  976: 	sxe_prop_dim_delete(object, member, 1, 0 TSRMLS_CC);
  977: }
  978: /* }}} */
  979: 
  980: /* {{{ sxe_dimension_unset()
  981:  */
  982: static void sxe_dimension_delete(zval *object, zval *offset TSRMLS_DC)
  983: {
  984: 	sxe_prop_dim_delete(object, offset, 0, 1 TSRMLS_CC);
  985: }
  986: /* }}} */
  987: 
  988: static inline char * sxe_xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) /* {{{ */
  989: {
  990: 	xmlChar *tmp = xmlNodeListGetString(doc, list, inLine);
  991: 	char    *res;
  992: 	
  993: 	if (tmp) {
  994: 		res = estrdup((char*)tmp);
  995: 		xmlFree(tmp);
  996: 	} else {
  997: 		res = STR_EMPTY_ALLOC();
  998: 	}
  999: 
 1000: 	return res;
 1001: }
 1002: /* }}} */
 1003: 
 1004: /* {{{ _get_base_node_value()
 1005:  */
 1006: static void _get_base_node_value(php_sxe_object *sxe_ref, xmlNodePtr node, zval **value, xmlChar *nsprefix, int isprefix TSRMLS_DC)
 1007: {
 1008: 	php_sxe_object *subnode;
 1009: 	xmlChar        *contents;
 1010: 
 1011: 	MAKE_STD_ZVAL(*value);
 1012: 
 1013: 	if (node->children && node->children->type == XML_TEXT_NODE && !xmlIsBlankNode(node->children)) {
 1014: 		contents = xmlNodeListGetString(node->doc, node->children, 1);
 1015: 		if (contents) {
 1016: 			ZVAL_STRING(*value, (char *)contents, 1);
 1017: 			xmlFree(contents);
 1018: 		}
 1019: 	} else {
 1020: 		subnode = php_sxe_object_new(sxe_ref->zo.ce TSRMLS_CC);
 1021: 		subnode->document = sxe_ref->document;
 1022: 		subnode->document->refcount++;
 1023: 		if (nsprefix && *nsprefix) {
 1024: 			subnode->iter.nsprefix = xmlStrdup((xmlChar *)nsprefix);
 1025: 			subnode->iter.isprefix = isprefix;
 1026: 		}
 1027: 		php_libxml_increment_node_ptr((php_libxml_node_object *)subnode, node, NULL TSRMLS_CC);
 1028: 
 1029: 		(*value)->type = IS_OBJECT;
 1030: 		(*value)->value.obj = php_sxe_register_object(subnode TSRMLS_CC);
 1031: 		/*zval_add_ref(value);*/
 1032: 	}
 1033: }
 1034: /* }}} */
 1035: 
 1036: static void sxe_properties_add(HashTable *rv, char *name, int namelen, zval *value TSRMLS_DC) /* {{{ */
 1037: {
 1038: 	zval  **data_ptr;
 1039: 	zval  *newptr;
 1040: 	ulong h = zend_hash_func(name, namelen);
 1041: 
 1042: 	if (zend_hash_quick_find(rv, name, namelen, h, (void **) &data_ptr) == SUCCESS) {
 1043: 		if (Z_TYPE_PP(data_ptr) == IS_ARRAY) {
 1044: 			zend_hash_next_index_insert(Z_ARRVAL_PP(data_ptr), &value, sizeof(zval *), NULL);
 1045: 		} else {
 1046: 			MAKE_STD_ZVAL(newptr);
 1047: 			array_init(newptr);
 1048: 
 1049: 			zval_add_ref(data_ptr);
 1050: 			zend_hash_next_index_insert(Z_ARRVAL_P(newptr), data_ptr, sizeof(zval *), NULL);
 1051: 			zend_hash_next_index_insert(Z_ARRVAL_P(newptr), &value, sizeof(zval *), NULL);
 1052: 
 1053: 			zend_hash_quick_update(rv, name, namelen, h, &newptr, sizeof(zval *), NULL);
 1054: 		}
 1055: 	} else {
 1056: 		zend_hash_quick_update(rv, name, namelen, h, &value, sizeof(zval *), NULL);
 1057: 	}
 1058: }
 1059: /* }}} */
 1060: 
 1061: static HashTable * sxe_get_prop_hash(zval *object, int is_debug TSRMLS_DC) /* {{{ */
 1062: {
 1063: 	zval            *value;
 1064: 	zval            *zattr;
 1065: 	HashTable       *rv;
 1066: 	php_sxe_object  *sxe;
 1067: 	char            *name;
 1068: 	xmlNodePtr       node;
 1069: 	xmlAttrPtr       attr;
 1070: 	int              namelen;
 1071: 	int              test;
 1072: 	char 		 use_iter;
 1073: 	zval            *iter_data = NULL;
 1074: 
 1075: 	use_iter = 0;
 1076: 
 1077: 	sxe = php_sxe_fetch_object(object TSRMLS_CC);
 1078: 
 1079: 	if (is_debug) {
 1080: 		ALLOC_HASHTABLE(rv);
 1081: 		zend_hash_init(rv, 0, NULL, ZVAL_PTR_DTOR, 0);
 1082: 	}
 1083: 	else if (sxe->properties) {
 1084: 		zend_hash_clean(sxe->properties);
 1085: 		rv = sxe->properties;
 1086: 	} else {
 1087: 		ALLOC_HASHTABLE(rv);
 1088: 		zend_hash_init(rv, 0, NULL, ZVAL_PTR_DTOR, 0);
 1089: 		sxe->properties = rv;
 1090: 	}
 1091: 
 1092: 	GET_NODE(sxe, node);
 1093: 	if (!node) {
 1094: 		return rv;
 1095: 	}
 1096: 	if (is_debug || sxe->iter.type != SXE_ITER_CHILD) {
 1097: 		if (sxe->iter.type == SXE_ITER_ELEMENT) {
 1098: 			node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
 1099: 		}
 1100: 		if (!node || node->type != XML_ENTITY_DECL) {
 1101: 			attr = node ? (xmlAttrPtr)node->properties : NULL;
 1102: 			zattr = NULL;
 1103: 			test = sxe->iter.name && sxe->iter.type == SXE_ITER_ATTRLIST;
 1104: 			while (attr) {
 1105: 				if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && match_ns(sxe, (xmlNodePtr)attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
 1106: 					MAKE_STD_ZVAL(value);
 1107: 					ZVAL_STRING(value, sxe_xmlNodeListGetString((xmlDocPtr) sxe->document->ptr, attr->children, 1), 0);
 1108: 					namelen = xmlStrlen(attr->name) + 1;
 1109: 					if (!zattr) {
 1110: 						MAKE_STD_ZVAL(zattr);
 1111: 						array_init(zattr);
 1112: 						sxe_properties_add(rv, "@attributes", sizeof("@attributes"), zattr TSRMLS_CC);
 1113: 					}
 1114: 					add_assoc_zval_ex(zattr, (char*)attr->name, namelen, value);
 1115: 				}
 1116: 				attr = attr->next;
 1117: 			}
 1118: 		}
 1119: 	}
 1120: 
 1121: 	GET_NODE(sxe, node);
 1122: 	node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
 1123: 
 1124: 	if (node && sxe->iter.type != SXE_ITER_ATTRLIST) {
 1125: 		if (node->type == XML_ATTRIBUTE_NODE) {
 1126: 			MAKE_STD_ZVAL(value);
 1127: 			ZVAL_STRING(value, sxe_xmlNodeListGetString(node->doc, node->children, 1), 0);
 1128: 			zend_hash_next_index_insert(rv, &value, sizeof(zval *), NULL);
 1129: 			node = NULL;
 1130: 		} else if (sxe->iter.type != SXE_ITER_CHILD) {
 1131: 
 1132: 			if ( !node->children || !node->parent || !node->next || node->children->next || node->children->children || node->parent->children == node->parent->last ) {
 1133: 				node = node->children;
 1134: 			} else {
 1135: 				iter_data = sxe->iter.data;
 1136: 				sxe->iter.data = NULL;
 1137: 
 1138: 				node = php_sxe_reset_iterator(sxe, 0 TSRMLS_CC);
 1139: 
 1140: 				use_iter = 1;
 1141: 			}
 1142: 		}
 1143: 
 1144: 		while (node) {
 1145: 			if (node->children != NULL || node->prev != NULL || node->next != NULL) {
 1146: 				SKIP_TEXT(node);
 1147: 			} else {
 1148: 				if (node->type == XML_TEXT_NODE) {
 1149: 					const xmlChar *cur = node->content;
 1150: 					
 1151: 					if (*cur != 0) {
 1152: 						MAKE_STD_ZVAL(value);
 1153: 						ZVAL_STRING(value, sxe_xmlNodeListGetString(node->doc, node, 1), 0);
 1154: 						zend_hash_next_index_insert(rv, &value, sizeof(zval *), NULL);
 1155: 					}
 1156: 					goto next_iter;
 1157: 				}
 1158: 			}
 1159: 
 1160: 			if (node->type == XML_ELEMENT_NODE && (! match_ns(sxe, node, sxe->iter.nsprefix, sxe->iter.isprefix))) {
 1161: 				goto next_iter;
 1162: 			}
 1163: 
 1164: 			name = (char *) node->name;
 1165: 			if (!name) {
 1166: 				goto next_iter;
 1167: 			} else {
 1168: 				namelen = xmlStrlen(node->name) + 1;
 1169: 			}
 1170: 
 1171: 			_get_base_node_value(sxe, node, &value, sxe->iter.nsprefix, sxe->iter.isprefix TSRMLS_CC);
 1172: 
 1173: 			if ( use_iter ) {
 1174: 				zend_hash_next_index_insert(rv, &value, sizeof(zval *), NULL);
 1175: 			} else {
 1176: 				sxe_properties_add(rv, name, namelen, value TSRMLS_CC);
 1177: 			}
 1178: next_iter:
 1179: 			if ( use_iter ) {
 1180: 				node = php_sxe_iterator_fetch(sxe, node->next, 0 TSRMLS_CC);
 1181: 			} else {
 1182: 				node = node->next;
 1183: 			}
 1184: 		}
 1185: 	}
 1186: 
 1187: 	if ( use_iter ) {
 1188: 		if (sxe->iter.data) {
 1189: 			zval_ptr_dtor(&sxe->iter.data);
 1190: 		}
 1191: 		sxe->iter.data = iter_data;
 1192: 	}
 1193: 
 1194: 	return rv;
 1195: }
 1196: /* }}} */
 1197: 
 1198: static HashTable * sxe_get_gc(zval *object, zval ***table, int *n TSRMLS_DC) /* {{{ */ {
 1199: 	php_sxe_object  *sxe;
 1200: 	sxe = php_sxe_fetch_object(object TSRMLS_CC);
 1201: 	
 1202: 	*table = NULL;
 1203: 	*n = 0;
 1204: 	return sxe->properties;
 1205: }
 1206: /* }}} */
 1207: 
 1208: static HashTable * sxe_get_properties(zval *object TSRMLS_DC) /* {{{ */
 1209: {
 1210: 	return sxe_get_prop_hash(object, 0 TSRMLS_CC);
 1211: }
 1212: /* }}} */
 1213: 
 1214: static HashTable * sxe_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */
 1215: {
 1216: 	*is_temp = 1;
 1217: 	return sxe_get_prop_hash(object, 1 TSRMLS_CC);
 1218: }
 1219: /* }}} */
 1220: 
 1221: static int sxe_objects_compare(zval *object1, zval *object2 TSRMLS_DC) /* {{{ */
 1222: {
 1223: 	php_sxe_object *sxe1;
 1224: 	php_sxe_object *sxe2;
 1225: 
 1226: 	sxe1 = php_sxe_fetch_object(object1 TSRMLS_CC);
 1227: 	sxe2 = php_sxe_fetch_object(object2 TSRMLS_CC);
 1228: 
 1229: 	if (sxe1->node == NULL) {
 1230: 		if (sxe2->node) {
 1231: 			return 1;
 1232: 		} else if (sxe1->document->ptr == sxe2->document->ptr) {
 1233: 			return 0;
 1234: 		}
 1235: 	} else {
 1236: 		return !(sxe1->node == sxe2->node);
 1237: 	}
 1238: 	return 1;
 1239: }
 1240: /* }}} */
 1241: 
 1242: /* {{{ proto array SimpleXMLElement::xpath(string path)
 1243:    Runs XPath query on the XML data */
 1244: SXE_METHOD(xpath)
 1245: {
 1246: 	php_sxe_object    *sxe;
 1247: 	zval              *value;
 1248: 	char              *query;
 1249: 	int                query_len;
 1250: 	int                i;
 1251: 	int                nsnbr = 0;
 1252: 	xmlNsPtr          *ns = NULL;
 1253: 	xmlXPathObjectPtr  retval;
 1254: 	xmlNodeSetPtr      result;
 1255: 	xmlNodePtr		   nodeptr;
 1256: 
 1257: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &query, &query_len) == FAILURE) {
 1258: 		return;
 1259: 	}
 1260: 
 1261: 	sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
 1262: 
 1263: 	if (sxe->iter.type == SXE_ITER_ATTRLIST) {
 1264: 		return; /* attributes don't have attributes */
 1265: 	}
 1266: 
 1267: 	if (!sxe->xpath) {
 1268: 		sxe->xpath = xmlXPathNewContext((xmlDocPtr) sxe->document->ptr);
 1269: 	}
 1270: 	if (!sxe->node) {
 1271: 		php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement((xmlDocPtr) sxe->document->ptr), NULL TSRMLS_CC);
 1272: 		if (!sxe->node) {
 1273: 			RETURN_FALSE;
 1274: 		}
 1275: 	}
 1276: 
 1277: 	nodeptr = php_sxe_get_first_node(sxe, sxe->node->node TSRMLS_CC);
 1278: 
 1279: 	sxe->xpath->node = nodeptr;
 1280: 
 1281:  	ns = xmlGetNsList((xmlDocPtr) sxe->document->ptr, nodeptr);
 1282: 	if (ns != NULL) {
 1283: 		while (ns[nsnbr] != NULL) {
 1284: 			nsnbr++;
 1285: 		}
 1286: 	}
 1287: 
 1288: 	sxe->xpath->namespaces = ns;
 1289: 	sxe->xpath->nsNr = nsnbr;
 1290: 
 1291: 	retval = xmlXPathEval((xmlChar *)query, sxe->xpath);
 1292: 	if (ns != NULL) {
 1293: 		xmlFree(ns);
 1294: 		sxe->xpath->namespaces = NULL;
 1295: 		sxe->xpath->nsNr = 0;
 1296: 	}
 1297: 
 1298: 	if (!retval) {
 1299: 		RETURN_FALSE;
 1300: 	}
 1301: 
 1302: 	result = retval->nodesetval;
 1303: 
 1304: 	array_init(return_value);
 1305: 		
 1306: 	if (result != NULL) {
 1307: 		for (i = 0; i < result->nodeNr; ++i) {
 1308: 			nodeptr = result->nodeTab[i];
 1309: 			if (nodeptr->type == XML_TEXT_NODE || nodeptr->type == XML_ELEMENT_NODE || nodeptr->type == XML_ATTRIBUTE_NODE) {
 1310: 				MAKE_STD_ZVAL(value);
 1311: 				/**
 1312: 				 * Detect the case where the last selector is text(), simplexml
 1313: 				 * always accesses the text() child by default, therefore we assign
 1314: 				 * to the parent node.
 1315: 				 */
 1316: 				if (nodeptr->type == XML_TEXT_NODE) {
 1317: 					_node_as_zval(sxe, nodeptr->parent, value, SXE_ITER_NONE, NULL, NULL, 0 TSRMLS_CC);
 1318: 				} else if (nodeptr->type == XML_ATTRIBUTE_NODE) {
 1319: 					_node_as_zval(sxe, nodeptr->parent, value, SXE_ITER_ATTRLIST, (char*)nodeptr->name, nodeptr->ns ? (xmlChar *)nodeptr->ns->href : NULL, 0 TSRMLS_CC);
 1320: 				} else {
 1321: 					_node_as_zval(sxe, nodeptr, value, SXE_ITER_NONE, NULL, NULL, 0 TSRMLS_CC);
 1322: 				}
 1323: 
 1324: 				add_next_index_zval(return_value, value);
 1325: 			}
 1326: 		}
 1327: 	}
 1328: 
 1329: 	xmlXPathFreeObject(retval);
 1330: }
 1331: /* }}} */
 1332: 
 1333: /* {{{ proto bool SimpleXMLElement::registerXPathNamespace(string prefix, string ns)
 1334:    Creates a prefix/ns context for the next XPath query */
 1335: SXE_METHOD(registerXPathNamespace)
 1336: {
 1337: 	php_sxe_object    *sxe;
 1338: 	int prefix_len, ns_uri_len;
 1339: 	char *prefix, *ns_uri;
 1340: 
 1341: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &prefix, &prefix_len, &ns_uri, &ns_uri_len) == FAILURE) {
 1342: 		return;
 1343: 	}
 1344: 
 1345: 	sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
 1346: 	if (!sxe->xpath) {
 1347: 		sxe->xpath = xmlXPathNewContext((xmlDocPtr) sxe->document->ptr);
 1348: 	}
 1349: 
 1350: 	if (xmlXPathRegisterNs(sxe->xpath, (xmlChar *)prefix, (xmlChar *)ns_uri) != 0) {
 1351: 		RETURN_FALSE
 1352: 	}
 1353: 	RETURN_TRUE;
 1354: }
 1355: 
 1356: /* }}} */
 1357: 
 1358: /* {{{ proto string SimpleXMLElement::asXML([string filename])
 1359:    Return a well-formed XML string based on SimpleXML element */
 1360: SXE_METHOD(asXML)
 1361: {
 1362: 	php_sxe_object     *sxe;
 1363: 	xmlNodePtr          node;
 1364: 	xmlOutputBufferPtr  outbuf;
 1365: 	xmlChar            *strval;
 1366: 	int                 strval_len;
 1367: 	char               *filename;
 1368: 	int                 filename_len;
 1369: 
 1370: 	if (ZEND_NUM_ARGS() > 1) {
 1371: 		RETURN_FALSE;
 1372: 	}
 1373: 
 1374: 	if (ZEND_NUM_ARGS() == 1) {
 1375: 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
 1376: 			RETURN_FALSE;
 1377: 		}
 1378: 
 1379: 		sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
 1380: 		GET_NODE(sxe, node);
 1381: 		node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
 1382: 
 1383: 		if (node) {
 1384: 			if (node->parent && (XML_DOCUMENT_NODE == node->parent->type)) {
 1385: 				int bytes;
 1386: 				bytes = xmlSaveFile(filename, (xmlDocPtr) sxe->document->ptr);
 1387: 				if (bytes == -1) {
 1388: 					RETURN_FALSE;
 1389: 				} else {
 1390: 					RETURN_TRUE;
 1391: 				}
 1392: 			} else {
 1393: 				outbuf = xmlOutputBufferCreateFilename(filename, NULL, 0);
 1394: 
 1395: 				if (outbuf == NULL) {
 1396: 					RETURN_FALSE;
 1397: 				}
 1398: 
 1399: 				xmlNodeDumpOutput(outbuf, (xmlDocPtr) sxe->document->ptr, node, 0, 0, NULL);
 1400: 				xmlOutputBufferClose(outbuf);
 1401: 				RETURN_TRUE;
 1402: 			}
 1403: 		} else {
 1404: 			RETURN_FALSE;
 1405: 		}
 1406: 	}
 1407: 
 1408: 	sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
 1409: 	GET_NODE(sxe, node);
 1410: 	node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
 1411: 
 1412: 	if (node) {
 1413: 		if (node->parent && (XML_DOCUMENT_NODE == node->parent->type)) {
 1414: 			xmlDocDumpMemoryEnc((xmlDocPtr) sxe->document->ptr, &strval, &strval_len, ((xmlDocPtr) sxe->document->ptr)->encoding);
 1415: 			RETVAL_STRINGL((char *)strval, strval_len, 1);
 1416: 			xmlFree(strval);
 1417: 		} else {
 1418: 			/* Should we be passing encoding information instead of NULL? */
 1419: 			outbuf = xmlAllocOutputBuffer(NULL);
 1420: 
 1421: 			if (outbuf == NULL) {
 1422: 				RETURN_FALSE;
 1423: 			}
 1424: 
 1425: 			xmlNodeDumpOutput(outbuf, (xmlDocPtr) sxe->document->ptr, node, 0, 0, ((xmlDocPtr) sxe->document->ptr)->encoding);
 1426: 			xmlOutputBufferFlush(outbuf);
 1427: #ifdef LIBXML2_NEW_BUFFER
 1428: 			RETVAL_STRINGL((char *)xmlOutputBufferGetContent(outbuf), xmlOutputBufferGetSize(outbuf), 1);
 1429: #else
 1430: 			RETVAL_STRINGL((char *)outbuf->buffer->content, outbuf->buffer->use, 1);
 1431: #endif
 1432: 			xmlOutputBufferClose(outbuf);
 1433: 		}
 1434: 	} else {
 1435: 		RETVAL_FALSE;
 1436: 	}
 1437: }
 1438: /* }}} */
 1439: 
 1440: #define SXE_NS_PREFIX(ns) (ns->prefix ? (char*)ns->prefix : "")
 1441: 
 1442: static inline void sxe_add_namespace_name(zval *return_value, xmlNsPtr ns) /* {{{ */
 1443: {
 1444: 	char *prefix = SXE_NS_PREFIX(ns);
 1445: 	if (zend_hash_exists(Z_ARRVAL_P(return_value), prefix, strlen(prefix) + 1) == 0) {
 1446: 		add_assoc_string(return_value, prefix, (char*)ns->href, 1);
 1447: 	}
 1448: }
 1449: /* }}} */
 1450: 
 1451: static void sxe_add_namespaces(php_sxe_object *sxe, xmlNodePtr node, zend_bool recursive, zval *return_value TSRMLS_DC) /* {{{ */
 1452: {
 1453: 	xmlAttrPtr  attr;
 1454: 
 1455: 	if (node->ns) {
 1456: 		sxe_add_namespace_name(return_value, node->ns);
 1457: 	}
 1458: 
 1459: 	attr = node->properties;
 1460: 	while (attr) {
 1461: 		if (attr->ns) {
 1462: 			sxe_add_namespace_name(return_value, attr->ns);
 1463: 		}
 1464: 		attr = attr->next;
 1465: 	}
 1466: 
 1467: 	if (recursive) {
 1468: 		node = node->children;
 1469: 		while (node) {
 1470: 			if (node->type == XML_ELEMENT_NODE) {
 1471: 				sxe_add_namespaces(sxe, node, recursive, return_value TSRMLS_CC);
 1472: 			}
 1473: 			node = node->next;
 1474: 		}
 1475: 	}
 1476: } /* }}} */
 1477: 
 1478: /* {{{ proto string SimpleXMLElement::getNamespaces([bool recursve])
 1479:    Return all namespaces in use */
 1480: SXE_METHOD(getNamespaces)
 1481: {
 1482: 	zend_bool           recursive = 0;
 1483: 	php_sxe_object     *sxe;
 1484: 	xmlNodePtr          node;
 1485: 
 1486: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &recursive) == FAILURE) {
 1487: 		return;
 1488: 	}
 1489: 
 1490: 	array_init(return_value);
 1491: 
 1492: 	sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
 1493: 	GET_NODE(sxe, node);
 1494: 	node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
 1495: 
 1496: 	if (node) {
 1497: 		if (node->type == XML_ELEMENT_NODE) {
 1498: 			sxe_add_namespaces(sxe, node, recursive, return_value TSRMLS_CC);
 1499: 		} else if (node->type == XML_ATTRIBUTE_NODE && node->ns) {
 1500: 			sxe_add_namespace_name(return_value, node->ns);
 1501: 		}
 1502: 	}
 1503: }
 1504: /* }}} */
 1505: 
 1506: static void sxe_add_registered_namespaces(php_sxe_object *sxe, xmlNodePtr node, zend_bool recursive, zval *return_value TSRMLS_DC) /* {{{ */
 1507: {
 1508: 	xmlNsPtr ns;
 1509: 
 1510: 	if (node->type == XML_ELEMENT_NODE) {
 1511: 		ns = node->nsDef;
 1512: 		while (ns != NULL) {
 1513: 			sxe_add_namespace_name(return_value, ns);
 1514: 			ns = ns->next;
 1515: 		}
 1516: 		if (recursive) {
 1517: 			node = node->children;
 1518: 			while (node) {
 1519: 				sxe_add_registered_namespaces(sxe, node, recursive, return_value TSRMLS_CC);
 1520: 				node = node->next;
 1521: 			}
 1522: 		}
 1523: 	}
 1524: }
 1525: /* }}} */
 1526: 
 1527: /* {{{ proto string SimpleXMLElement::getDocNamespaces([bool recursive [, bool from_root])
 1528:    Return all namespaces registered with document */
 1529: SXE_METHOD(getDocNamespaces)
 1530: {
 1531: 	zend_bool           recursive = 0, from_root = 1;
 1532: 	php_sxe_object     *sxe;
 1533: 	xmlNodePtr          node;
 1534: 
 1535: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bb", &recursive, &from_root) == FAILURE) {
 1536: 		return;
 1537: 	}
 1538: 
 1539: 	sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
 1540: 	if(from_root){
 1541: 		node = xmlDocGetRootElement((xmlDocPtr)sxe->document->ptr);
 1542: 	}else{
 1543: 		GET_NODE(sxe, node);
 1544: 	}
 1545: 	
 1546: 	if (node == NULL) {
 1547: 		RETURN_FALSE;
 1548: 	}
 1549: 	
 1550: 	array_init(return_value);
 1551: 	sxe_add_registered_namespaces(sxe, node, recursive, return_value TSRMLS_CC);
 1552: }
 1553: /* }}} */
 1554: 
 1555: /* {{{ proto object SimpleXMLElement::children([string ns [, bool is_prefix]])
 1556:    Finds children of given node */
 1557: SXE_METHOD(children)
 1558: {
 1559: 	php_sxe_object *sxe;
 1560: 	char           *nsprefix = NULL;
 1561: 	int             nsprefix_len = 0;
 1562: 	xmlNodePtr      node;
 1563: 	zend_bool       isprefix = 0;
 1564: 
 1565: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!b", &nsprefix, &nsprefix_len, &isprefix) == FAILURE) {
 1566: 		return;
 1567: 	}
 1568: 
 1569: 	sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
 1570: 
 1571: 	if (sxe->iter.type == SXE_ITER_ATTRLIST) {
 1572: 		return; /* attributes don't have attributes */
 1573: 	}
 1574: 
 1575: 	GET_NODE(sxe, node);
 1576: 	node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
 1577: 
 1578: 	_node_as_zval(sxe, node, return_value, SXE_ITER_CHILD, NULL, (xmlChar *)nsprefix, isprefix TSRMLS_CC);
 1579: 
 1580: }
 1581: /* }}} */
 1582: 
 1583: /* {{{ proto object SimpleXMLElement::getName()
 1584:    Finds children of given node */
 1585: SXE_METHOD(getName)
 1586: {
 1587: 	php_sxe_object *sxe;
 1588: 	xmlNodePtr      node;
 1589: 	int             namelen;
 1590: 
 1591: 	sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
 1592: 
 1593: 	GET_NODE(sxe, node);
 1594: 	node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
 1595: 	if (node) {
 1596: 		namelen = xmlStrlen(node->name);
 1597: 		RETURN_STRINGL((char*)node->name, namelen, 1);
 1598: 	} else {
 1599: 		RETURN_EMPTY_STRING();
 1600: 	}
 1601: }
 1602: /* }}} */
 1603: 
 1604: /* {{{ proto array SimpleXMLElement::attributes([string ns [, bool is_prefix]])
 1605:    Identifies an element's attributes */
 1606: SXE_METHOD(attributes)
 1607: {
 1608: 	php_sxe_object *sxe;
 1609: 	char           *nsprefix = NULL;
 1610: 	int             nsprefix_len = 0;
 1611: 	xmlNodePtr      node;
 1612: 	zend_bool       isprefix = 0;
 1613: 
 1614: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!b", &nsprefix, &nsprefix_len, &isprefix) == FAILURE) {
 1615: 		return;
 1616: 	}
 1617: 
 1618: 	sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
 1619: 	GET_NODE(sxe, node);
 1620: 
 1621: 	if (sxe->iter.type == SXE_ITER_ATTRLIST) {
 1622: 		return; /* attributes don't have attributes */
 1623: 	}
 1624: 
 1625: 	node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
 1626: 
 1627: 	_node_as_zval(sxe, node, return_value, SXE_ITER_ATTRLIST, NULL, (xmlChar *)nsprefix, isprefix TSRMLS_CC);
 1628: }
 1629: /* }}} */
 1630: 
 1631: /* {{{ proto void SimpleXMLElement::addChild(string qName [, string value [, string ns]])
 1632:    Add Element with optional namespace information */
 1633: SXE_METHOD(addChild)
 1634: {
 1635: 	php_sxe_object *sxe;
 1636: 	char           *qname, *value = NULL, *nsuri = NULL;
 1637: 	int             qname_len, value_len = 0, nsuri_len = 0;
 1638: 	xmlNodePtr      node, newnode;
 1639: 	xmlNsPtr        nsptr = NULL;
 1640: 	xmlChar        *localname, *prefix = NULL;
 1641: 
 1642: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!s!",
 1643: 		&qname, &qname_len, &value, &value_len, &nsuri, &nsuri_len) == FAILURE) {
 1644: 		return;
 1645: 	}
 1646: 
 1647: 	if (qname_len == 0) {
 1648: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Element name is required");
 1649: 		return;
 1650: 	}
 1651: 
 1652: 	sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
 1653: 	GET_NODE(sxe, node);
 1654: 
 1655: 	if (sxe->iter.type == SXE_ITER_ATTRLIST) {
 1656: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot add element to attributes");
 1657: 		return;
 1658: 	}
 1659: 
 1660: 	node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
 1661: 
 1662: 	if (node == NULL) {
 1663: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot add child. Parent is not a permanent member of the XML tree");
 1664: 		return;
 1665: 	}
 1666: 
 1667: 	localname = xmlSplitQName2((xmlChar *)qname, &prefix);
 1668: 	if (localname == NULL) {
 1669: 		localname = xmlStrdup((xmlChar *)qname);
 1670: 	}
 1671: 
 1672: 	newnode = xmlNewChild(node, NULL, localname, (xmlChar *)value);
 1673: 
 1674: 	if (nsuri != NULL) {
 1675: 		if (nsuri_len == 0) {
 1676: 			newnode->ns = NULL;
 1677: 			nsptr = xmlNewNs(newnode, (xmlChar *)nsuri, prefix);
 1678: 		} else {
 1679: 			nsptr = xmlSearchNsByHref(node->doc, node, (xmlChar *)nsuri);
 1680: 			if (nsptr == NULL) {
 1681: 				nsptr = xmlNewNs(newnode, (xmlChar *)nsuri, prefix);
 1682: 			}
 1683: 			newnode->ns = nsptr;
 1684: 		}
 1685: 	}
 1686: 
 1687: 	_node_as_zval(sxe, newnode, return_value, SXE_ITER_NONE, (char *)localname, prefix, 0 TSRMLS_CC);
 1688: 
 1689: 	xmlFree(localname);
 1690: 	if (prefix != NULL) {
 1691: 		xmlFree(prefix);
 1692: 	}
 1693: }
 1694: /* }}} */
 1695: 
 1696: /* {{{ proto void SimpleXMLElement::addAttribute(string qName, string value [,string ns])
 1697:    Add Attribute with optional namespace information */
 1698: SXE_METHOD(addAttribute)
 1699: {
 1700: 	php_sxe_object *sxe;
 1701: 	char           *qname, *value = NULL, *nsuri = NULL;
 1702: 	int             qname_len, value_len = 0, nsuri_len = 0;
 1703: 	xmlNodePtr      node;
 1704: 	xmlAttrPtr      attrp = NULL;
 1705: 	xmlNsPtr        nsptr = NULL;
 1706: 	xmlChar        *localname, *prefix = NULL;
 1707: 
 1708: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s!",
 1709: 		&qname, &qname_len, &value, &value_len, &nsuri, &nsuri_len) == FAILURE) {
 1710: 		return;
 1711: 	}
 1712: 
 1713: 	if (qname_len == 0) {
 1714: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attribute name is required");
 1715: 		return;
 1716: 	}
 1717: 
 1718: 	sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
 1719: 	GET_NODE(sxe, node);
 1720: 
 1721: 	node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
 1722: 
 1723: 	if (node && node->type != XML_ELEMENT_NODE) {
 1724: 		node = node->parent;
 1725: 	}
 1726: 
 1727: 	if (node == NULL) {
 1728: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to locate parent Element");
 1729: 		return;
 1730: 	}
 1731: 
 1732: 	localname = xmlSplitQName2((xmlChar *)qname, &prefix);
 1733: 	if (localname == NULL) {
 1734: 		if (nsuri_len > 0) {
 1735: 			if (prefix != NULL) {
 1736: 				xmlFree(prefix);
 1737: 			}
 1738: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attribute requires prefix for namespace");
 1739: 			return;
 1740: 		}
 1741: 		localname = xmlStrdup((xmlChar *)qname);
 1742: 	}
 1743: 
 1744: 	attrp = xmlHasNsProp(node, localname, (xmlChar *)nsuri);
 1745: 	if (attrp != NULL && attrp->type != XML_ATTRIBUTE_DECL) {
 1746: 		xmlFree(localname);
 1747: 		if (prefix != NULL) {
 1748: 			xmlFree(prefix);
 1749: 		}
 1750: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attribute already exists");
 1751: 		return;
 1752: 	}
 1753: 
 1754: 	if (nsuri != NULL) {
 1755: 		nsptr = xmlSearchNsByHref(node->doc, node, (xmlChar *)nsuri);
 1756: 		if (nsptr == NULL) {
 1757: 			nsptr = xmlNewNs(node, (xmlChar *)nsuri, prefix);
 1758: 		}
 1759: 	}
 1760: 
 1761: 	attrp = xmlNewNsProp(node, nsptr, localname, (xmlChar *)value);
 1762: 
 1763: 	xmlFree(localname);
 1764: 	if (prefix != NULL) {
 1765: 		xmlFree(prefix);
 1766: 	}
 1767: }
 1768: /* }}} */
 1769: 
 1770: /* {{{ cast_object()
 1771:  */
 1772: static int cast_object(zval *object, int type, char *contents TSRMLS_DC)
 1773: {
 1774: 	if (contents) {
 1775: 		ZVAL_STRINGL(object, contents, strlen(contents), 1);
 1776: 	} else {
 1777: 		ZVAL_NULL(object);
 1778: 	}
 1779: 	Z_SET_REFCOUNT_P(object, 1);
 1780: 	Z_UNSET_ISREF_P(object);
 1781: 
 1782: 	switch (type) {
 1783: 		case IS_STRING:
 1784: 			convert_to_string(object);
 1785: 			break;
 1786: 		case IS_BOOL:
 1787: 			convert_to_boolean(object);
 1788: 			break;
 1789: 		case IS_LONG:
 1790: 			convert_to_long(object);
 1791: 			break;
 1792: 		case IS_DOUBLE:
 1793: 			convert_to_double(object);
 1794: 			break;
 1795: 		default:
 1796: 			return FAILURE;
 1797: 	}
 1798: 	return SUCCESS;
 1799: }
 1800: /* }}} */
 1801: 
 1802: /* {{{ sxe_object_cast()
 1803:  */
 1804: static int sxe_object_cast(zval *readobj, zval *writeobj, int type TSRMLS_DC)
 1805: {
 1806: 	php_sxe_object *sxe;
 1807: 	xmlChar           *contents = NULL;
 1808: 	xmlNodePtr	    node;
 1809: 	int rv;
 1810: 	HashTable      *prop_hash;
 1811: 
 1812: 	sxe = php_sxe_fetch_object(readobj TSRMLS_CC);
 1813: 
 1814: 	if (type == IS_BOOL) {
 1815: 		node = php_sxe_get_first_node(sxe, NULL TSRMLS_CC);
 1816: 		prop_hash = sxe_get_prop_hash(readobj, 1 TSRMLS_CC);
 1817: 		INIT_PZVAL(writeobj);
 1818: 		ZVAL_BOOL(writeobj, node != NULL || zend_hash_num_elements(prop_hash) > 0);
 1819: 		zend_hash_destroy(prop_hash);
 1820: 		efree(prop_hash);
 1821: 		return SUCCESS;
 1822: 	}
 1823: 
 1824: 	if (sxe->iter.type != SXE_ITER_NONE) {
 1825: 		node = php_sxe_get_first_node(sxe, NULL TSRMLS_CC);
 1826: 		if (node) {
 1827: 			contents = xmlNodeListGetString((xmlDocPtr) sxe->document->ptr, node->children, 1);
 1828: 		}
 1829: 	} else {
 1830: 		if (!sxe->node) {
 1831: 			if (sxe->document) {
 1832: 				php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement((xmlDocPtr) sxe->document->ptr), NULL TSRMLS_CC);
 1833: 			}
 1834: 		}
 1835: 
 1836: 		if (sxe->node && sxe->node->node) {
 1837: 			if (sxe->node->node->children) {
 1838: 				contents = xmlNodeListGetString((xmlDocPtr) sxe->document->ptr, sxe->node->node->children, 1);
 1839: 			}
 1840: 		}
 1841: 	}
 1842: 
 1843: 	if (readobj == writeobj) {
 1844: 		INIT_PZVAL(writeobj);
 1845: 		zval_dtor(readobj);
 1846: 	}
 1847: 
 1848: 	rv = cast_object(writeobj, type, (char *)contents TSRMLS_CC);
 1849: 
 1850: 	if (contents) {
 1851: 		xmlFree(contents);
 1852: 	}
 1853: 	return rv;
 1854: }
 1855: /* }}} */
 1856: 
 1857: /* {{{ proto object SimpleXMLElement::__toString() U
 1858:    Returns the string content */
 1859: SXE_METHOD(__toString)
 1860: {
 1861: 	zval           *result;
 1862: 
 1863: 	ALLOC_INIT_ZVAL(result);
 1864: 
 1865: 	if (sxe_object_cast(getThis(), result, IS_STRING TSRMLS_CC) == SUCCESS) {
 1866: 		RETURN_ZVAL(result, 1, 1);
 1867: 	} else {
 1868: 		zval_ptr_dtor(&result);
 1869: 		RETURN_EMPTY_STRING();
 1870: 	}
 1871: }
 1872: /* }}} */
 1873: 
 1874: static int php_sxe_count_elements_helper(php_sxe_object *sxe, long *count TSRMLS_DC) /* {{{ */
 1875: {
 1876: 	xmlNodePtr       node;
 1877: 	zval            *data;
 1878: 
 1879: 	*count = 0;
 1880: 
 1881: 	data = sxe->iter.data;
 1882: 	sxe->iter.data = NULL;
 1883: 
 1884: 	node = php_sxe_reset_iterator(sxe, 0 TSRMLS_CC);
 1885: 
 1886: 	while (node)
 1887: 	{
 1888: 		(*count)++;
 1889: 		node = php_sxe_iterator_fetch(sxe, node->next, 0 TSRMLS_CC);
 1890: 	}
 1891: 
 1892: 	if (sxe->iter.data) {
 1893: 		zval_ptr_dtor(&sxe->iter.data);
 1894: 	}
 1895: 	sxe->iter.data = data;
 1896: 
 1897: 	return SUCCESS;
 1898: }
 1899: /* }}} */
 1900: 
 1901: static int sxe_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */
 1902: {
 1903: 	php_sxe_object  *intern;
 1904: 	intern = php_sxe_fetch_object(object TSRMLS_CC);
 1905: 	if (intern->fptr_count) {
 1906: 		zval *rv;
 1907: 		zend_call_method_with_0_params(&object, intern->zo.ce, &intern->fptr_count, "count", &rv);
 1908: 		if (rv) {
 1909: 			if (intern->tmp) {
 1910: 				zval_ptr_dtor(&intern->tmp);
 1911: 			}
 1912: 			MAKE_STD_ZVAL(intern->tmp);
 1913: 			ZVAL_ZVAL(intern->tmp, rv, 1, 1);
 1914: 			convert_to_long(intern->tmp);
 1915: 			*count = (long) Z_LVAL_P(intern->tmp);
 1916: 			return SUCCESS;
 1917: 		}
 1918: 		return FAILURE;
 1919: 	}
 1920: 	return php_sxe_count_elements_helper(intern, count TSRMLS_CC);
 1921: }
 1922: /* }}} */
 1923: 
 1924: /* {{{ proto int SimpleXMLElement::count()
 1925:  Get number of child elements */
 1926: SXE_METHOD(count)
 1927: {
 1928: 	long count = 0;
 1929: 	php_sxe_object *sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
 1930: 
 1931: 	if (zend_parse_parameters_none() == FAILURE) {
 1932: 		return;
 1933: 	}
 1934: 
 1935: 	php_sxe_count_elements_helper(sxe, &count TSRMLS_CC);
 1936: 	
 1937: 	RETURN_LONG(count);
 1938: }
 1939: /* }}} */
 1940: 
 1941: static zval *sxe_get_value(zval *z TSRMLS_DC) /* {{{ */
 1942: {
 1943: 	zval *retval;
 1944: 
 1945: 	MAKE_STD_ZVAL(retval);
 1946: 
 1947: 	if (sxe_object_cast(z, retval, IS_STRING TSRMLS_CC)==FAILURE) {
 1948: 		zend_error(E_ERROR, "Unable to cast node to string");
 1949: 		/* FIXME: Should not be fatal */
 1950: 	}
 1951: 
 1952: 	Z_SET_REFCOUNT_P(retval, 0);
 1953: 	return retval;
 1954: }
 1955: /* }}} */
 1956: 
 1957: static zend_object_handlers sxe_object_handlers = { /* {{{ */
 1958: 	ZEND_OBJECTS_STORE_HANDLERS,
 1959: 	sxe_property_read,
 1960: 	sxe_property_write,
 1961: 	sxe_dimension_read,
 1962: 	sxe_dimension_write,
 1963: 	sxe_property_get_adr,
 1964: 	sxe_get_value,			/* get */
 1965: 	NULL,
 1966: 	sxe_property_exists,
 1967: 	sxe_property_delete,
 1968: 	sxe_dimension_exists,
 1969: 	sxe_dimension_delete,
 1970: 	sxe_get_properties,
 1971: 	NULL, /* zend_get_std_object_handlers()->get_method,*/
 1972: 	NULL, /* zend_get_std_object_handlers()->call_method,*/
 1973: 	NULL, /* zend_get_std_object_handlers()->get_constructor, */
 1974: 	NULL, /* zend_get_std_object_handlers()->get_class_entry,*/
 1975: 	NULL, /* zend_get_std_object_handlers()->get_class_name,*/
 1976: 	sxe_objects_compare,
 1977: 	sxe_object_cast,
 1978: 	sxe_count_elements,
 1979: 	sxe_get_debug_info,
 1980: 	NULL,
 1981: 	sxe_get_gc
 1982: };
 1983: /* }}} */
 1984: 
 1985: /* {{{ sxe_object_clone()
 1986:  */
 1987: static void
 1988: sxe_object_clone(void *object, void **clone_ptr TSRMLS_DC)
 1989: {
 1990: 	php_sxe_object *sxe = (php_sxe_object *) object;
 1991: 	php_sxe_object *clone;
 1992: 	xmlNodePtr nodep = NULL;
 1993: 	xmlDocPtr docp = NULL;
 1994: 
 1995: 	clone = php_sxe_object_new(sxe->zo.ce TSRMLS_CC);
 1996: 	clone->document = sxe->document;
 1997: 	if (clone->document) {
 1998: 		clone->document->refcount++;
 1999: 		docp = clone->document->ptr;
 2000: 	}
 2001: 
 2002: 	clone->iter.isprefix = sxe->iter.isprefix;
 2003: 	if (sxe->iter.name != NULL) {
 2004: 		clone->iter.name = xmlStrdup((xmlChar *)sxe->iter.name);
 2005: 	}
 2006: 	if (sxe->iter.nsprefix != NULL) {
 2007: 		clone->iter.nsprefix = xmlStrdup((xmlChar *)sxe->iter.nsprefix);
 2008: 	}
 2009: 	clone->iter.type = sxe->iter.type;
 2010: 
 2011: 	if (sxe->node) {
 2012: 		nodep = xmlDocCopyNode(sxe->node->node, docp, 1);
 2013: 	}
 2014: 
 2015: 	php_libxml_increment_node_ptr((php_libxml_node_object *)clone, nodep, NULL TSRMLS_CC);
 2016: 
 2017: 	*clone_ptr = (void *) clone;
 2018: }
 2019: /* }}} */
 2020: 
 2021: /* {{{ sxe_object_dtor()
 2022:  */
 2023: static void sxe_object_dtor(void *object, zend_object_handle handle TSRMLS_DC)
 2024: {
 2025: 	/* dtor required to cleanup iterator related data properly */
 2026: 
 2027: 	php_sxe_object *sxe;
 2028: 
 2029: 	sxe = (php_sxe_object *) object;
 2030: 
 2031: 	if (sxe->iter.data) {
 2032: 		zval_ptr_dtor(&sxe->iter.data);
 2033: 		sxe->iter.data = NULL;
 2034: 	}
 2035: 
 2036: 	if (sxe->iter.name) {
 2037: 		xmlFree(sxe->iter.name);
 2038: 		sxe->iter.name = NULL;
 2039: 	}
 2040: 	if (sxe->iter.nsprefix) {
 2041: 		xmlFree(sxe->iter.nsprefix);
 2042: 		sxe->iter.nsprefix = NULL;
 2043: 	}
 2044: 	if (sxe->tmp) {
 2045: 		zval_ptr_dtor(&sxe->tmp);
 2046: 		sxe->tmp = NULL;
 2047: 	}
 2048: }
 2049: /* }}} */
 2050: 
 2051: /* {{{ sxe_object_free_storage()
 2052:  */
 2053: static void sxe_object_free_storage(void *object TSRMLS_DC)
 2054: {
 2055: 	php_sxe_object *sxe;
 2056: 
 2057: 	sxe = (php_sxe_object *) object;
 2058: 
 2059: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1 && PHP_RELEASE_VERSION > 2) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
 2060: 	zend_object_std_dtor(&sxe->zo TSRMLS_CC);
 2061: #else
 2062: 	if (sxe->zo.guards) {
 2063: 		zend_hash_destroy(sxe->zo.guards);
 2064: 		FREE_HASHTABLE(sxe->zo.guards);
 2065: 	}
 2066: 
 2067: 	if (sxe->zo.properties) {
 2068: 		zend_hash_destroy(sxe->zo.properties);
 2069: 		FREE_HASHTABLE(sxe->zo.properties);
 2070: 	}
 2071: #endif
 2072: 
 2073: 	php_libxml_node_decrement_resource((php_libxml_node_object *)sxe TSRMLS_CC);
 2074: 
 2075: 	if (sxe->xpath) {
 2076: 		xmlXPathFreeContext(sxe->xpath);
 2077: 	}
 2078: 
 2079: 	if (sxe->properties) {
 2080: 		zend_hash_destroy(sxe->properties);
 2081: 		FREE_HASHTABLE(sxe->properties);
 2082: 	}
 2083: 
 2084: 	efree(object);
 2085: }
 2086: /* }}} */
 2087: 
 2088: /* {{{ php_sxe_object_new()
 2089:  */
 2090: static php_sxe_object* php_sxe_object_new(zend_class_entry *ce TSRMLS_DC)
 2091: {
 2092: 	php_sxe_object *intern;
 2093: 	zend_class_entry     *parent = ce;
 2094: 	int inherited = 0;
 2095: 
 2096: 	intern = ecalloc(1, sizeof(php_sxe_object));
 2097: 
 2098: 	intern->iter.type = SXE_ITER_NONE;
 2099: 	intern->iter.nsprefix = NULL;
 2100: 	intern->iter.name = NULL;
 2101: 	intern->fptr_count = NULL;
 2102: 
 2103: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1 && PHP_RELEASE_VERSION > 2) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
 2104: 	zend_object_std_init(&intern->zo, ce TSRMLS_CC);
 2105: #else
 2106: 	ALLOC_HASHTABLE(intern->zo.properties);
 2107: 	zend_hash_init(intern->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
 2108: 
 2109: 	intern->zo.ce = ce;
 2110: 	intern->zo.guards = NULL;
 2111: #endif
 2112: 
 2113: 	while (parent) {
 2114: 		if (parent == sxe_class_entry) {
 2115: 			break;
 2116: 		}
 2117: 
 2118: 		parent = parent->parent;
 2119: 		inherited = 1;
 2120: 	}
 2121: 
 2122: 	if (inherited) {
 2123: 		zend_hash_find(&ce->function_table, "count", sizeof("count"),(void **) &intern->fptr_count);
 2124: 		if (intern->fptr_count->common.scope == parent) {
 2125: 			intern->fptr_count = NULL;
 2126: 		}
 2127: 	}
 2128: 
 2129: 	return intern;
 2130: }
 2131: /* }}} */
 2132: 
 2133: /* {{{ php_sxe_register_object
 2134:  */
 2135: static zend_object_value
 2136: php_sxe_register_object(php_sxe_object *intern TSRMLS_DC)
 2137: {
 2138: 	zend_object_value rv;
 2139: 
 2140: 	rv.handle = zend_objects_store_put(intern, sxe_object_dtor, (zend_objects_free_object_storage_t)sxe_object_free_storage, sxe_object_clone TSRMLS_CC);
 2141: 	rv.handlers = (zend_object_handlers *) &sxe_object_handlers;
 2142: 
 2143: 	return rv;
 2144: }
 2145: /* }}} */
 2146: 
 2147: /* {{{ sxe_object_new()
 2148:  */
 2149: PHP_SXE_API zend_object_value
 2150: sxe_object_new(zend_class_entry *ce TSRMLS_DC)
 2151: {
 2152: 	php_sxe_object    *intern;
 2153: 
 2154: 	intern = php_sxe_object_new(ce TSRMLS_CC);
 2155: 	return php_sxe_register_object(intern TSRMLS_CC);
 2156: }
 2157: /* }}} */
 2158: 
 2159: /* {{{ proto simplemxml_element simplexml_load_file(string filename [, string class_name [, int options [, string ns [, bool is_prefix]]]])
 2160:    Load a filename and return a simplexml_element object to allow for processing */
 2161: PHP_FUNCTION(simplexml_load_file)
 2162: {
 2163: 	php_sxe_object *sxe;
 2164: 	char           *filename;
 2165: 	int             filename_len;
 2166: 	xmlDocPtr       docp;
 2167: 	char           *ns = NULL;
 2168: 	int             ns_len = 0;
 2169: 	long            options = 0;
 2170: 	zend_class_entry *ce= sxe_class_entry;
 2171: 	zend_bool       isprefix = 0;
 2172: 
 2173: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|C!lsb", &filename, &filename_len, &ce, &options, &ns, &ns_len, &isprefix) == FAILURE) {
 2174: 		return;
 2175: 	}
 2176: 
 2177: 	docp = xmlReadFile(filename, NULL, options);
 2178: 
 2179: 	if (! docp) {
 2180: 		RETURN_FALSE;
 2181: 	}
 2182: 
 2183: 	if (!ce) {
 2184: 		ce = sxe_class_entry;
 2185: 	}
 2186: 	sxe = php_sxe_object_new(ce TSRMLS_CC);
 2187: 	sxe->iter.nsprefix = ns_len ? xmlStrdup((xmlChar *)ns) : NULL;
 2188: 	sxe->iter.isprefix = isprefix;
 2189: 	php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, docp TSRMLS_CC);
 2190: 	php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement(docp), NULL TSRMLS_CC);
 2191: 
 2192: 	return_value->type = IS_OBJECT;
 2193: 	return_value->value.obj = php_sxe_register_object(sxe TSRMLS_CC);
 2194: }
 2195: /* }}} */
 2196: 
 2197: /* {{{ proto simplemxml_element simplexml_load_string(string data [, string class_name [, int options [, string ns [, bool is_prefix]]]])
 2198:    Load a string and return a simplexml_element object to allow for processing */
 2199: PHP_FUNCTION(simplexml_load_string)
 2200: {
 2201: 	php_sxe_object *sxe;
 2202: 	char           *data;
 2203: 	int             data_len;
 2204: 	xmlDocPtr       docp;
 2205: 	char           *ns = NULL;
 2206: 	int             ns_len = 0;
 2207: 	long            options = 0;
 2208: 	zend_class_entry *ce= sxe_class_entry;
 2209: 	zend_bool       isprefix = 0;
 2210: 
 2211: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|C!lsb", &data, &data_len, &ce, &options, &ns, &ns_len, &isprefix) == FAILURE) {
 2212: 		return;
 2213: 	}
 2214: 
 2215: 	docp = xmlReadMemory(data, data_len, NULL, NULL, options);
 2216: 
 2217: 	if (! docp) {
 2218: 		RETURN_FALSE;
 2219: 	}
 2220: 
 2221: 	if (!ce) {
 2222: 		ce = sxe_class_entry;
 2223: 	}
 2224: 	sxe = php_sxe_object_new(ce TSRMLS_CC);
 2225: 	sxe->iter.nsprefix = ns_len ? xmlStrdup((xmlChar *)ns) : NULL;
 2226: 	sxe->iter.isprefix = isprefix;
 2227: 	php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, docp TSRMLS_CC);
 2228: 	php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement(docp), NULL TSRMLS_CC);
 2229: 
 2230: 	return_value->type = IS_OBJECT;
 2231: 	return_value->value.obj = php_sxe_register_object(sxe TSRMLS_CC);
 2232: }
 2233: /* }}} */
 2234: 
 2235: /* {{{ proto SimpleXMLElement::__construct(string data [, int options [, bool data_is_url [, string ns [, bool is_prefix]]]])
 2236:    SimpleXMLElement constructor */
 2237: SXE_METHOD(__construct)
 2238: {
 2239: 	php_sxe_object *sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
 2240: 	char           *data, *ns = NULL;
 2241: 	int             data_len, ns_len = 0;
 2242: 	xmlDocPtr       docp;
 2243: 	long            options = 0;
 2244: 	zend_bool       is_url = 0, isprefix = 0;
 2245: 	zend_error_handling error_handling;
 2246: 
 2247: 	zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC);
 2248: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lbsb", &data, &data_len, &options, &is_url, &ns, &ns_len, &isprefix) == FAILURE) {
 2249: 		zend_restore_error_handling(&error_handling TSRMLS_CC);
 2250: 		return;
 2251: 	}
 2252: 
 2253: 	zend_restore_error_handling(&error_handling TSRMLS_CC);
 2254: 
 2255: 	docp = is_url ? xmlReadFile(data, NULL, options) : xmlReadMemory(data, data_len, NULL, NULL, options);
 2256: 
 2257: 	if (!docp) {
 2258: 		((php_libxml_node_object *)sxe)->document = NULL;
 2259: 		zend_throw_exception(zend_exception_get_default(TSRMLS_C), "String could not be parsed as XML", 0 TSRMLS_CC);
 2260: 		return;
 2261: 	}
 2262: 
 2263: 	sxe->iter.nsprefix = ns_len ? xmlStrdup((xmlChar *)ns) : NULL;
 2264: 	sxe->iter.isprefix = isprefix;
 2265: 	php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, docp TSRMLS_CC);
 2266: 	php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement(docp), NULL TSRMLS_CC);
 2267: }
 2268: /* }}} */
 2269: 
 2270: zend_object_iterator_funcs php_sxe_iterator_funcs = { /* {{{ */
 2271: 	php_sxe_iterator_dtor,
 2272: 	php_sxe_iterator_valid,
 2273: 	php_sxe_iterator_current_data,
 2274: 	php_sxe_iterator_current_key,
 2275: 	php_sxe_iterator_move_forward,
 2276: 	php_sxe_iterator_rewind,
 2277: };
 2278: /* }}} */
 2279: 
 2280: static xmlNodePtr php_sxe_iterator_fetch(php_sxe_object *sxe, xmlNodePtr node, int use_data TSRMLS_DC) /* {{{ */
 2281: {
 2282: 	xmlChar *prefix  = sxe->iter.nsprefix;
 2283: 	int isprefix  = sxe->iter.isprefix;
 2284: 	int test_elem = sxe->iter.type == SXE_ITER_ELEMENT  && sxe->iter.name;
 2285: 	int test_attr = sxe->iter.type == SXE_ITER_ATTRLIST && sxe->iter.name;
 2286: 
 2287: 	while (node) {
 2288: 		SKIP_TEXT(node);
 2289: 		if (sxe->iter.type != SXE_ITER_ATTRLIST && node->type == XML_ELEMENT_NODE) {
 2290: 			if ((!test_elem || !xmlStrcmp(node->name, sxe->iter.name)) && match_ns(sxe, node, prefix, isprefix)) {
 2291: 				break;
 2292: 			}
 2293: 		} else if (node->type == XML_ATTRIBUTE_NODE) {
 2294: 			if ((!test_attr || !xmlStrcmp(node->name, sxe->iter.name)) && match_ns(sxe, node, prefix, isprefix)) {
 2295: 				break;
 2296: 			}
 2297: 		}
 2298: next_iter:
 2299: 		node = node->next;
 2300: 	}
 2301: 
 2302: 	if (node && use_data) {
 2303: 		ALLOC_INIT_ZVAL(sxe->iter.data);
 2304: 		_node_as_zval(sxe, node, sxe->iter.data, SXE_ITER_NONE, NULL, prefix, isprefix TSRMLS_CC);
 2305: 	}
 2306: 
 2307: 	return node;
 2308: }
 2309: /* }}} */
 2310: 
 2311: static xmlNodePtr php_sxe_reset_iterator(php_sxe_object *sxe, int use_data TSRMLS_DC) /* {{{ */
 2312: {
 2313: 	xmlNodePtr node;
 2314: 
 2315: 	if (sxe->iter.data) {
 2316: 		zval_ptr_dtor(&sxe->iter.data);
 2317: 		sxe->iter.data = NULL;
 2318: 	}
 2319: 
 2320: 	GET_NODE(sxe, node)
 2321: 
 2322: 	if (node) {
 2323: 		switch (sxe->iter.type) {
 2324: 			case SXE_ITER_ELEMENT:
 2325: 			case SXE_ITER_CHILD:
 2326: 			case SXE_ITER_NONE:
 2327: 				node = node->children;
 2328: 				break;
 2329: 			case SXE_ITER_ATTRLIST:
 2330: 				node = (xmlNodePtr) node->properties;
 2331: 		}
 2332: 		return php_sxe_iterator_fetch(sxe, node, use_data TSRMLS_CC);
 2333: 	}
 2334: 	return NULL;
 2335: }
 2336: /* }}} */
 2337: 
 2338: zend_object_iterator *php_sxe_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */
 2339: {
 2340: 	php_sxe_iterator *iterator;
 2341: 
 2342: 	if (by_ref) {
 2343: 		zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
 2344: 	}
 2345: 	iterator = emalloc(sizeof(php_sxe_iterator));
 2346: 
 2347: 	Z_ADDREF_P(object);
 2348: 	iterator->intern.data = (void*)object;
 2349: 	iterator->intern.funcs = &php_sxe_iterator_funcs;
 2350: 	iterator->sxe = php_sxe_fetch_object(object TSRMLS_CC);
 2351: 
 2352: 	return (zend_object_iterator*)iterator;
 2353: }
 2354: /* }}} */
 2355: 
 2356: static void php_sxe_iterator_dtor(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
 2357: {
 2358: 	php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
 2359: 
 2360: 	/* cleanup handled in sxe_object_dtor as we dont always have an iterator wrapper */
 2361: 	if (iterator->intern.data) {
 2362: 		zval_ptr_dtor((zval**)&iterator->intern.data);
 2363: 	}
 2364: 
 2365: 	efree(iterator);
 2366: }
 2367: /* }}} */
 2368: 
 2369: static int php_sxe_iterator_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
 2370: {
 2371: 	php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
 2372: 
 2373: 	return iterator->sxe->iter.data ? SUCCESS : FAILURE;
 2374: }
 2375: /* }}} */
 2376: 
 2377: static void php_sxe_iterator_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */
 2378: {
 2379: 	php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
 2380: 
 2381: 	*data = &iterator->sxe->iter.data;
 2382: }
 2383: /* }}} */
 2384: 
 2385: static int php_sxe_iterator_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */
 2386: {
 2387: 	zval *curobj;
 2388: 	xmlNodePtr curnode = NULL;
 2389: 	php_sxe_object *intern;
 2390: 	int namelen;
 2391: 
 2392: 	php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
 2393: 	curobj = iterator->sxe->iter.data;
 2394: 
 2395: 	intern = (php_sxe_object *)zend_object_store_get_object(curobj TSRMLS_CC);
 2396: 	if (intern != NULL && intern->node != NULL) {
 2397: 		curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->node)->node;
 2398: 	}
 2399: 	if (!curnode) {
 2400: 		return HASH_KEY_NON_EXISTANT;
 2401: 	}
 2402: 
 2403: 	namelen = xmlStrlen(curnode->name);
 2404: 	*str_key = estrndup((char *)curnode->name, namelen);
 2405: 	*str_key_len = namelen + 1;
 2406: 	return HASH_KEY_IS_STRING;
 2407: 
 2408: }
 2409: /* }}} */
 2410: 
 2411: PHP_SXE_API void php_sxe_move_forward_iterator(php_sxe_object *sxe TSRMLS_DC) /* {{{ */
 2412: {
 2413: 	xmlNodePtr      node = NULL;
 2414: 	php_sxe_object  *intern;
 2415: 
 2416: 	if (sxe->iter.data) {
 2417: 		intern = (php_sxe_object *)zend_object_store_get_object(sxe->iter.data TSRMLS_CC);
 2418: 		GET_NODE(intern, node)
 2419: 		zval_ptr_dtor(&sxe->iter.data);
 2420: 		sxe->iter.data = NULL;
 2421: 	}
 2422: 
 2423: 	if (node) {
 2424: 		php_sxe_iterator_fetch(sxe, node->next, 1 TSRMLS_CC);
 2425: 	}
 2426: }
 2427: /* }}} */
 2428: 
 2429: static void php_sxe_iterator_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
 2430: {
 2431: 	php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
 2432: 	php_sxe_move_forward_iterator(iterator->sxe TSRMLS_CC);
 2433: }
 2434: /* }}} */
 2435: 
 2436: static void php_sxe_iterator_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
 2437: {
 2438: 	php_sxe_object	*sxe;
 2439: 
 2440: 	php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
 2441: 	sxe = iterator->sxe;
 2442: 
 2443: 	php_sxe_reset_iterator(sxe, 1 TSRMLS_CC);
 2444: }
 2445: /* }}} */
 2446: 
 2447: void *simplexml_export_node(zval *object TSRMLS_DC) /* {{{ */
 2448: {
 2449: 	php_sxe_object *sxe;
 2450: 	xmlNodePtr node;
 2451: 
 2452: 	sxe = php_sxe_fetch_object(object TSRMLS_CC);
 2453: 	GET_NODE(sxe, node);
 2454: 	return php_sxe_get_first_node(sxe, node TSRMLS_CC);
 2455: }
 2456: /* }}} */
 2457: 
 2458: /* {{{ proto simplemxml_element simplexml_import_dom(domNode node [, string class_name])
 2459:    Get a simplexml_element object from dom to allow for processing */
 2460: PHP_FUNCTION(simplexml_import_dom)
 2461: {
 2462: 	php_sxe_object *sxe;
 2463: 	zval *node;
 2464: 	php_libxml_node_object *object;
 2465: 	xmlNodePtr		nodep = NULL;
 2466: 	zend_class_entry *ce= sxe_class_entry;
 2467: 
 2468: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o|C!", &node, &ce) == FAILURE) {
 2469: 		return;
 2470: 	}
 2471: 
 2472: 	object = (php_libxml_node_object *)zend_object_store_get_object(node TSRMLS_CC);
 2473: 
 2474: 	nodep = php_libxml_import_node(node TSRMLS_CC);
 2475: 
 2476: 	if (nodep) {
 2477: 		if (nodep->doc == NULL) {
 2478: 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Imported Node must have associated Document");
 2479: 			RETURN_NULL();
 2480: 		}
 2481: 		if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) {
 2482: 			nodep = xmlDocGetRootElement((xmlDocPtr) nodep);
 2483: 		}
 2484: 	}
 2485: 
 2486: 	if (nodep && nodep->type == XML_ELEMENT_NODE) {
 2487: 		if (!ce) {
 2488: 			ce = sxe_class_entry;
 2489: 		}
 2490: 		sxe = php_sxe_object_new(ce TSRMLS_CC);
 2491: 		sxe->document = object->document;
 2492: 		php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, nodep->doc TSRMLS_CC);
 2493: 		php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, nodep, NULL TSRMLS_CC);
 2494: 
 2495: 		return_value->type = IS_OBJECT;
 2496: 		return_value->value.obj = php_sxe_register_object(sxe TSRMLS_CC);
 2497: 	} else {
 2498: 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Nodetype to import");
 2499: 		RETVAL_NULL();
 2500: 	}
 2501: }
 2502: /* }}} */
 2503: 
 2504: /* {{{ arginfo */
 2505: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexml_load_file, 0, 0, 1)
 2506: 	ZEND_ARG_INFO(0, filename)
 2507: 	ZEND_ARG_INFO(0, class_name)
 2508: 	ZEND_ARG_INFO(0, options)
 2509: 	ZEND_ARG_INFO(0, ns)
 2510: 	ZEND_ARG_INFO(0, is_prefix)
 2511: ZEND_END_ARG_INFO()
 2512: 
 2513: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexml_load_string, 0, 0, 1)
 2514: 	ZEND_ARG_INFO(0, data)
 2515: 	ZEND_ARG_INFO(0, class_name)
 2516: 	ZEND_ARG_INFO(0, options)
 2517: 	ZEND_ARG_INFO(0, ns)
 2518: 	ZEND_ARG_INFO(0, is_prefix)
 2519: ZEND_END_ARG_INFO()
 2520: 
 2521: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexml_import_dom, 0, 0, 1)
 2522: 	ZEND_ARG_INFO(0, node)
 2523: 	ZEND_ARG_INFO(0, class_name)
 2524: ZEND_END_ARG_INFO()
 2525: 
 2526: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_xpath, 0, 0, 1)
 2527: 	ZEND_ARG_INFO(0, path)
 2528: ZEND_END_ARG_INFO()
 2529: 
 2530: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_registerxpathnamespace, 0, 0, 2)
 2531: 	ZEND_ARG_INFO(0, prefix)
 2532: 	ZEND_ARG_INFO(0, ns)
 2533: ZEND_END_ARG_INFO()
 2534: 
 2535: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_asxml, 0, 0, 0)
 2536: 	ZEND_ARG_INFO(0, filename)
 2537: ZEND_END_ARG_INFO()
 2538: 
 2539: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_getnamespaces, 0, 0, 0)
 2540: 	ZEND_ARG_INFO(0, recursve)
 2541: ZEND_END_ARG_INFO()
 2542: 
 2543: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_getdocnamespaces, 0, 0, 0)
 2544: 	ZEND_ARG_INFO(0, recursve)
 2545: 	ZEND_ARG_INFO(0, from_root)
 2546: ZEND_END_ARG_INFO()
 2547: 
 2548: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_children, 0, 0, 0)
 2549: 	ZEND_ARG_INFO(0, ns)
 2550: 	ZEND_ARG_INFO(0, is_prefix)
 2551: ZEND_END_ARG_INFO()
 2552: 
 2553: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement__construct, 0, 0, 1)
 2554: 	ZEND_ARG_INFO(0, data)
 2555: 	ZEND_ARG_INFO(0, options)
 2556: 	ZEND_ARG_INFO(0, data_is_url)
 2557: 	ZEND_ARG_INFO(0, ns)
 2558: 	ZEND_ARG_INFO(0, is_prefix)
 2559: ZEND_END_ARG_INFO()
 2560: 
 2561: ZEND_BEGIN_ARG_INFO(arginfo_simplexmlelement__void, 0)
 2562: ZEND_END_ARG_INFO()
 2563: 
 2564: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_addchild, 0, 0, 1)
 2565: 	ZEND_ARG_INFO(0, name)
 2566: 	ZEND_ARG_INFO(0, value)
 2567: 	ZEND_ARG_INFO(0, ns)
 2568: ZEND_END_ARG_INFO()
 2569: /* }}} */
 2570: 
 2571: const zend_function_entry simplexml_functions[] = { /* {{{ */
 2572: 	PHP_FE(simplexml_load_file, 	arginfo_simplexml_load_file)
 2573: 	PHP_FE(simplexml_load_string,	arginfo_simplexml_load_string)
 2574: 	PHP_FE(simplexml_import_dom,	arginfo_simplexml_import_dom)
 2575: 	PHP_FE_END
 2576: };
 2577: /* }}} */
 2578: 
 2579: static const zend_module_dep simplexml_deps[] = { /* {{{ */
 2580: 	ZEND_MOD_REQUIRED("libxml")
 2581: 	ZEND_MOD_REQUIRED("spl")
 2582: 	ZEND_MOD_END
 2583: };
 2584: /* }}} */
 2585: 
 2586: zend_module_entry simplexml_module_entry = { /* {{{ */
 2587: 	STANDARD_MODULE_HEADER_EX, NULL,
 2588: 	simplexml_deps,
 2589: 	"SimpleXML",
 2590: 	simplexml_functions,
 2591: 	PHP_MINIT(simplexml),
 2592: 	PHP_MSHUTDOWN(simplexml),
 2593: 	NULL,
 2594: 	NULL,
 2595: 	PHP_MINFO(simplexml),
 2596: 	"0.1",
 2597: 	STANDARD_MODULE_PROPERTIES
 2598: };
 2599: /* }}} */
 2600: 
 2601: #ifdef COMPILE_DL_SIMPLEXML
 2602: ZEND_GET_MODULE(simplexml)
 2603: #endif
 2604: 
 2605: /* the method table */
 2606: /* each method can have its own parameters and visibility */
 2607: static const zend_function_entry sxe_functions[] = { /* {{{ */
 2608: 	SXE_ME(__construct,            arginfo_simplexmlelement__construct, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) /* must be called */
 2609: 	SXE_ME(asXML,                  arginfo_simplexmlelement_asxml, ZEND_ACC_PUBLIC)
 2610: 	SXE_MALIAS(saveXML, asXML,	   arginfo_simplexmlelement_asxml, ZEND_ACC_PUBLIC)
 2611: 	SXE_ME(xpath,                  arginfo_simplexmlelement_xpath, ZEND_ACC_PUBLIC)
 2612: 	SXE_ME(registerXPathNamespace, arginfo_simplexmlelement_registerxpathnamespace, ZEND_ACC_PUBLIC)
 2613: 	SXE_ME(attributes,             arginfo_simplexmlelement_children, ZEND_ACC_PUBLIC)
 2614: 	SXE_ME(children,               arginfo_simplexmlelement_children, ZEND_ACC_PUBLIC)
 2615: 	SXE_ME(getNamespaces,          arginfo_simplexmlelement_getnamespaces, ZEND_ACC_PUBLIC)
 2616: 	SXE_ME(getDocNamespaces,       arginfo_simplexmlelement_getdocnamespaces, ZEND_ACC_PUBLIC)
 2617: 	SXE_ME(getName,                arginfo_simplexmlelement__void, ZEND_ACC_PUBLIC)
 2618: 	SXE_ME(addChild,               arginfo_simplexmlelement_addchild, ZEND_ACC_PUBLIC)
 2619: 	SXE_ME(addAttribute,           arginfo_simplexmlelement_addchild, ZEND_ACC_PUBLIC)
 2620: 	SXE_ME(__toString,             arginfo_simplexmlelement__void, ZEND_ACC_PUBLIC)
 2621: 	SXE_ME(count,                  arginfo_simplexmlelement__void, ZEND_ACC_PUBLIC)
 2622: 	PHP_FE_END
 2623: };
 2624: /* }}} */
 2625: 
 2626: /* {{{ PHP_MINIT_FUNCTION(simplexml)
 2627:  */
 2628: PHP_MINIT_FUNCTION(simplexml)
 2629: {
 2630: 	zend_class_entry sxe;
 2631: 
 2632: 	INIT_CLASS_ENTRY(sxe, "SimpleXMLElement", sxe_functions);
 2633: 	sxe.create_object = sxe_object_new;
 2634: 	sxe_class_entry = zend_register_internal_class(&sxe TSRMLS_CC);
 2635: 	sxe_class_entry->get_iterator = php_sxe_get_iterator;
 2636: 	sxe_class_entry->iterator_funcs.funcs = &php_sxe_iterator_funcs;
 2637: 	zend_class_implements(sxe_class_entry TSRMLS_CC, 1, zend_ce_traversable);
 2638: 	sxe_object_handlers.get_method = zend_get_std_object_handlers()->get_method;
 2639: 	sxe_object_handlers.get_constructor = zend_get_std_object_handlers()->get_constructor;
 2640: 	sxe_object_handlers.get_class_entry = zend_get_std_object_handlers()->get_class_entry;
 2641: 	sxe_object_handlers.get_class_name = zend_get_std_object_handlers()->get_class_name;
 2642: 	sxe_class_entry->serialize = zend_class_serialize_deny;
 2643: 	sxe_class_entry->unserialize = zend_class_unserialize_deny;
 2644: 
 2645: 	php_libxml_register_export(sxe_class_entry, simplexml_export_node);
 2646: 
 2647: 	PHP_MINIT(sxe)(INIT_FUNC_ARGS_PASSTHRU);
 2648: 
 2649: 	return SUCCESS;
 2650: }
 2651: /* }}} */
 2652: 
 2653: /* {{{ PHP_MSHUTDOWN_FUNCTION(simplexml)
 2654:  */
 2655: PHP_MSHUTDOWN_FUNCTION(simplexml)
 2656: {
 2657: 	sxe_class_entry = NULL;
 2658: 	return SUCCESS;
 2659: }
 2660: /* }}} */
 2661: 
 2662: /* {{{ PHP_MINFO_FUNCTION(simplexml)
 2663:  */
 2664: PHP_MINFO_FUNCTION(simplexml)
 2665: {
 2666: 	php_info_print_table_start();
 2667: 	php_info_print_table_header(2, "Simplexml support", "enabled");
 2668: 	php_info_print_table_row(2, "Revision", "$Id: simplexml.c,v 1.1.1.5 2014/06/15 20:03:55 misho Exp $");
 2669: 	php_info_print_table_row(2, "Schema support",
 2670: #ifdef LIBXML_SCHEMAS_ENABLED
 2671: 		"enabled");
 2672: #else
 2673: 		"not available");
 2674: #endif
 2675: 	php_info_print_table_end();
 2676: }
 2677: /* }}} */
 2678: 
 2679: #endif
 2680: 
 2681: /**
 2682:  * Local Variables:
 2683:  * c-basic-offset: 4
 2684:  * tab-width: 4
 2685:  * indent-tabs-mode: t
 2686:  * End:
 2687:  * vim600: fdm=marker
 2688:  * vim: noet sw=4 ts=4
 2689:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>