Annotation of embedaddon/php/ext/simplexml/simplexml.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:   +----------------------------------------------------------------------+
                      3:   | PHP Version 5                                                        |
                      4:   +----------------------------------------------------------------------+
                      5:   | Copyright (c) 1997-2012 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 321634 2012-01-01 13:15:04Z felipe $ */
                     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 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 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 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 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 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: 
                   1073:        sxe = php_sxe_fetch_object(object TSRMLS_CC);
                   1074: 
                   1075:        if (is_debug) {
                   1076:                ALLOC_HASHTABLE(rv);
                   1077:                zend_hash_init(rv, 0, NULL, ZVAL_PTR_DTOR, 0);
                   1078:        }
                   1079:        else if (sxe->properties) {
                   1080:                if (GC_G(gc_active)) {
                   1081:                        return sxe->properties;
                   1082:                }
                   1083:                zend_hash_clean(sxe->properties);
                   1084:                rv = sxe->properties;
                   1085:        } else {
                   1086:                if (GC_G(gc_active)) {
                   1087:                        return NULL;
                   1088:                }
                   1089:                ALLOC_HASHTABLE(rv);
                   1090:                zend_hash_init(rv, 0, NULL, ZVAL_PTR_DTOR, 0);
                   1091:                sxe->properties = rv;
                   1092:        }
                   1093: 
                   1094:        GET_NODE(sxe, node);
                   1095:        if (!node) {
                   1096:                return rv;
                   1097:        }
                   1098:        if (is_debug || sxe->iter.type != SXE_ITER_CHILD) {
                   1099:                if (sxe->iter.type == SXE_ITER_ELEMENT) {
                   1100:                        node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                   1101:                }
                   1102:                if (!node || node->type != XML_ENTITY_DECL) {
                   1103:                        attr = node ? (xmlAttrPtr)node->properties : NULL;
                   1104:                        zattr = NULL;
                   1105:                        test = sxe->iter.name && sxe->iter.type == SXE_ITER_ATTRLIST;
                   1106:                        while (attr) {
                   1107:                                if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && match_ns(sxe, (xmlNodePtr)attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
                   1108:                                        MAKE_STD_ZVAL(value);
                   1109:                                        ZVAL_STRING(value, sxe_xmlNodeListGetString((xmlDocPtr) sxe->document->ptr, attr->children, 1), 0);
                   1110:                                        namelen = xmlStrlen(attr->name) + 1;
                   1111:                                        if (!zattr) {
                   1112:                                                MAKE_STD_ZVAL(zattr);
                   1113:                                                array_init(zattr);
                   1114:                                                sxe_properties_add(rv, "@attributes", sizeof("@attributes"), zattr TSRMLS_CC);
                   1115:                                        }
                   1116:                                        add_assoc_zval_ex(zattr, (char*)attr->name, namelen, value);
                   1117:                                }
                   1118:                                attr = attr->next;
                   1119:                        }
                   1120:                }
                   1121:        }
                   1122: 
                   1123:        GET_NODE(sxe, node);
                   1124:        node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                   1125:        if (node && sxe->iter.type != SXE_ITER_ATTRLIST) {
                   1126:                if (node->type == XML_ATTRIBUTE_NODE) {
                   1127:                        MAKE_STD_ZVAL(value);
                   1128:                        ZVAL_STRING(value, sxe_xmlNodeListGetString(node->doc, node->children, 1), 0);
                   1129:                        zend_hash_next_index_insert(rv, &value, sizeof(zval *), NULL);
                   1130:                        node = NULL;
                   1131:                } else if (sxe->iter.type != SXE_ITER_CHILD) {
                   1132:                        node = node->children;
                   1133:                }
                   1134: 
                   1135:                while (node) {
                   1136:                        if (node->children != NULL || node->prev != NULL || node->next != NULL) {
                   1137:                                SKIP_TEXT(node);
                   1138:                        } else {
                   1139:                                if (node->type == XML_TEXT_NODE) {
                   1140:                                        const xmlChar *cur = node->content;
                   1141:                                        
                   1142:                                        if (*cur != 0) {
                   1143:                                                MAKE_STD_ZVAL(value);
                   1144:                                                ZVAL_STRING(value, sxe_xmlNodeListGetString(node->doc, node, 1), 0);
                   1145:                                                zend_hash_next_index_insert(rv, &value, sizeof(zval *), NULL);
                   1146:                                        }
                   1147:                                        goto next_iter;
                   1148:                                }
                   1149:                        }
                   1150: 
                   1151:                        if (node->type == XML_ELEMENT_NODE && (! match_ns(sxe, node, sxe->iter.nsprefix, sxe->iter.isprefix))) {
                   1152:                                goto next_iter;
                   1153:                        }
                   1154: 
                   1155:                        name = (char *) node->name;
                   1156:                        if (!name) {
                   1157:                                goto next_iter;
                   1158:                        } else {
                   1159:                                namelen = xmlStrlen(node->name) + 1;
                   1160:                        }
                   1161: 
                   1162:                        _get_base_node_value(sxe, node, &value, sxe->iter.nsprefix, sxe->iter.isprefix TSRMLS_CC);
                   1163: 
                   1164:                        sxe_properties_add(rv, name, namelen, value TSRMLS_CC);
                   1165: next_iter:
                   1166:                        node = node->next;
                   1167:                }
                   1168:        }
                   1169: 
                   1170:        return rv;
                   1171: }
                   1172: /* }}} */
                   1173: 
                   1174: static HashTable * sxe_get_properties(zval *object TSRMLS_DC) /* {{{ */
                   1175: {
                   1176:        return sxe_get_prop_hash(object, 0 TSRMLS_CC);
                   1177: }
                   1178: /* }}} */
                   1179: 
                   1180: static HashTable * sxe_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */
                   1181: {
                   1182:        *is_temp = 1;
                   1183:        return sxe_get_prop_hash(object, 1 TSRMLS_CC);
                   1184: }
                   1185: /* }}} */
                   1186: 
                   1187: static int sxe_objects_compare(zval *object1, zval *object2 TSRMLS_DC) /* {{{ */
                   1188: {
                   1189:        php_sxe_object *sxe1;
                   1190:        php_sxe_object *sxe2;
                   1191: 
                   1192:        sxe1 = php_sxe_fetch_object(object1 TSRMLS_CC);
                   1193:        sxe2 = php_sxe_fetch_object(object2 TSRMLS_CC);
                   1194: 
                   1195:        if (sxe1->node == NULL) {
                   1196:                if (sxe2->node) {
                   1197:                        return 1;
                   1198:                } else if (sxe1->document->ptr == sxe2->document->ptr) {
                   1199:                        return 0;
                   1200:                }
                   1201:        } else {
                   1202:                return !(sxe1->node == sxe2->node);
                   1203:        }
                   1204:        return 1;
                   1205: }
                   1206: /* }}} */
                   1207: 
                   1208: /* {{{ proto array SimpleXMLElement::xpath(string path)
                   1209:    Runs XPath query on the XML data */
                   1210: SXE_METHOD(xpath)
                   1211: {
                   1212:        php_sxe_object    *sxe;
                   1213:        zval              *value;
                   1214:        char              *query;
                   1215:        int                query_len;
                   1216:        int                i;
                   1217:        int                nsnbr = 0;
                   1218:        xmlNsPtr          *ns = NULL;
                   1219:        xmlXPathObjectPtr  retval;
                   1220:        xmlNodeSetPtr      result;
                   1221:        xmlNodePtr                 nodeptr;
                   1222: 
                   1223:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &query, &query_len) == FAILURE) {
                   1224:                return;
                   1225:        }
                   1226: 
                   1227:        sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   1228: 
                   1229:        if (sxe->iter.type == SXE_ITER_ATTRLIST) {
                   1230:                return; /* attributes don't have attributes */
                   1231:        }
                   1232: 
                   1233:        if (!sxe->xpath) {
                   1234:                sxe->xpath = xmlXPathNewContext((xmlDocPtr) sxe->document->ptr);
                   1235:        }
                   1236:        if (!sxe->node) {
                   1237:                php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement((xmlDocPtr) sxe->document->ptr), NULL TSRMLS_CC);
                   1238:        }
                   1239: 
                   1240:        nodeptr = php_sxe_get_first_node(sxe, sxe->node->node TSRMLS_CC);
                   1241: 
                   1242:        sxe->xpath->node = nodeptr;
                   1243: 
                   1244:        ns = xmlGetNsList((xmlDocPtr) sxe->document->ptr, nodeptr);
                   1245:        if (ns != NULL) {
                   1246:                while (ns[nsnbr] != NULL) {
                   1247:                        nsnbr++;
                   1248:                }
                   1249:        }
                   1250: 
                   1251:        sxe->xpath->namespaces = ns;
                   1252:        sxe->xpath->nsNr = nsnbr;
                   1253: 
                   1254:        retval = xmlXPathEval((xmlChar *)query, sxe->xpath);
                   1255:        if (ns != NULL) {
                   1256:                xmlFree(ns);
                   1257:                sxe->xpath->namespaces = NULL;
                   1258:                sxe->xpath->nsNr = 0;
                   1259:        }
                   1260: 
                   1261:        if (!retval) {
                   1262:                RETURN_FALSE;
                   1263:        }
                   1264: 
                   1265:        result = retval->nodesetval;
                   1266: 
                   1267:        array_init(return_value);
                   1268:                
                   1269:        if (result != NULL) {
                   1270:                for (i = 0; i < result->nodeNr; ++i) {
                   1271:                        nodeptr = result->nodeTab[i];
                   1272:                        if (nodeptr->type == XML_TEXT_NODE || nodeptr->type == XML_ELEMENT_NODE || nodeptr->type == XML_ATTRIBUTE_NODE) {
                   1273:                                MAKE_STD_ZVAL(value);
                   1274:                                /**
                   1275:                                 * Detect the case where the last selector is text(), simplexml
                   1276:                                 * always accesses the text() child by default, therefore we assign
                   1277:                                 * to the parent node.
                   1278:                                 */
                   1279:                                if (nodeptr->type == XML_TEXT_NODE) {
                   1280:                                        _node_as_zval(sxe, nodeptr->parent, value, SXE_ITER_NONE, NULL, NULL, 0 TSRMLS_CC);
                   1281:                                } else if (nodeptr->type == XML_ATTRIBUTE_NODE) {
                   1282:                                        _node_as_zval(sxe, nodeptr->parent, value, SXE_ITER_ATTRLIST, (char*)nodeptr->name, nodeptr->ns ? (xmlChar *)nodeptr->ns->href : NULL, 0 TSRMLS_CC);
                   1283:                                } else {
                   1284:                                        _node_as_zval(sxe, nodeptr, value, SXE_ITER_NONE, NULL, NULL, 0 TSRMLS_CC);
                   1285:                                }
                   1286: 
                   1287:                                add_next_index_zval(return_value, value);
                   1288:                        }
                   1289:                }
                   1290:        }
                   1291: 
                   1292:        xmlXPathFreeObject(retval);
                   1293: }
                   1294: /* }}} */
                   1295: 
                   1296: /* {{{ proto bool SimpleXMLElement::registerXPathNamespace(string prefix, string ns)
                   1297:    Creates a prefix/ns context for the next XPath query */
                   1298: SXE_METHOD(registerXPathNamespace)
                   1299: {
                   1300:        php_sxe_object    *sxe;
                   1301:        int prefix_len, ns_uri_len;
                   1302:        char *prefix, *ns_uri;
                   1303: 
                   1304:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &prefix, &prefix_len, &ns_uri, &ns_uri_len) == FAILURE) {
                   1305:                return;
                   1306:        }
                   1307: 
                   1308:        sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   1309:        if (!sxe->xpath) {
                   1310:                sxe->xpath = xmlXPathNewContext((xmlDocPtr) sxe->document->ptr);
                   1311:        }
                   1312: 
                   1313:        if (xmlXPathRegisterNs(sxe->xpath, (xmlChar *)prefix, (xmlChar *)ns_uri) != 0) {
                   1314:                RETURN_FALSE
                   1315:        }
                   1316:        RETURN_TRUE;
                   1317: }
                   1318: 
                   1319: /* }}} */
                   1320: 
                   1321: /* {{{ proto string SimpleXMLElement::asXML([string filename])
                   1322:    Return a well-formed XML string based on SimpleXML element */
                   1323: SXE_METHOD(asXML)
                   1324: {
                   1325:        php_sxe_object     *sxe;
                   1326:        xmlNodePtr          node;
                   1327:        xmlOutputBufferPtr  outbuf;
                   1328:        xmlChar            *strval;
                   1329:        int                 strval_len;
                   1330:        char               *filename;
                   1331:        int                 filename_len;
                   1332: 
                   1333:        if (ZEND_NUM_ARGS() > 1) {
                   1334:                RETURN_FALSE;
                   1335:        }
                   1336: 
                   1337:        if (ZEND_NUM_ARGS() == 1) {
                   1338:                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
                   1339:                        RETURN_FALSE;
                   1340:                }
                   1341: 
                   1342:                sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   1343:                GET_NODE(sxe, node);
                   1344:                node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                   1345: 
                   1346:                if (node) {
                   1347:                        if (node->parent && (XML_DOCUMENT_NODE == node->parent->type)) {
                   1348:                                int bytes;
                   1349:                                bytes = xmlSaveFile(filename, (xmlDocPtr) sxe->document->ptr);
                   1350:                                if (bytes == -1) {
                   1351:                                        RETURN_FALSE;
                   1352:                                } else {
                   1353:                                        RETURN_TRUE;
                   1354:                                }
                   1355:                        } else {
                   1356:                                outbuf = xmlOutputBufferCreateFilename(filename, NULL, 0);
                   1357: 
                   1358:                                if (outbuf == NULL) {
                   1359:                                        RETURN_FALSE;
                   1360:                                }
                   1361: 
                   1362:                                xmlNodeDumpOutput(outbuf, (xmlDocPtr) sxe->document->ptr, node, 0, 0, NULL);
                   1363:                                xmlOutputBufferClose(outbuf);
                   1364:                                RETURN_TRUE;
                   1365:                        }
                   1366:                } else {
                   1367:                        RETURN_FALSE;
                   1368:                }
                   1369:        }
                   1370: 
                   1371:        sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   1372:        GET_NODE(sxe, node);
                   1373:        node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                   1374: 
                   1375:        if (node) {
                   1376:                if (node->parent && (XML_DOCUMENT_NODE == node->parent->type)) {
                   1377:                        xmlDocDumpMemoryEnc((xmlDocPtr) sxe->document->ptr, &strval, &strval_len, ((xmlDocPtr) sxe->document->ptr)->encoding);
                   1378:                        RETVAL_STRINGL((char *)strval, strval_len, 1);
                   1379:                        xmlFree(strval);
                   1380:                } else {
                   1381:                        /* Should we be passing encoding information instead of NULL? */
                   1382:                        outbuf = xmlAllocOutputBuffer(NULL);
                   1383: 
                   1384:                        if (outbuf == NULL) {
                   1385:                                RETURN_FALSE;
                   1386:                        }
                   1387: 
                   1388:                        xmlNodeDumpOutput(outbuf, (xmlDocPtr) sxe->document->ptr, node, 0, 0, ((xmlDocPtr) sxe->document->ptr)->encoding);
                   1389:                        xmlOutputBufferFlush(outbuf);
                   1390:                        RETVAL_STRINGL((char *)outbuf->buffer->content, outbuf->buffer->use, 1);
                   1391:                        xmlOutputBufferClose(outbuf);
                   1392:                }
                   1393:        } else {
                   1394:                RETVAL_FALSE;
                   1395:        }
                   1396: }
                   1397: /* }}} */
                   1398: 
                   1399: #define SXE_NS_PREFIX(ns) (ns->prefix ? (char*)ns->prefix : "")
                   1400: 
                   1401: static inline void sxe_add_namespace_name(zval *return_value, xmlNsPtr ns) /* {{{ */
                   1402: {
                   1403:        char *prefix = SXE_NS_PREFIX(ns);
                   1404:        if (zend_hash_exists(Z_ARRVAL_P(return_value), prefix, strlen(prefix) + 1) == 0) {
                   1405:                add_assoc_string(return_value, prefix, (char*)ns->href, 1);
                   1406:        }
                   1407: }
                   1408: /* }}} */
                   1409: 
                   1410: static void sxe_add_namespaces(php_sxe_object *sxe, xmlNodePtr node, zend_bool recursive, zval *return_value TSRMLS_DC) /* {{{ */
                   1411: {
                   1412:        xmlAttrPtr  attr;
                   1413: 
                   1414:        if (node->ns) {
                   1415:                sxe_add_namespace_name(return_value, node->ns);
                   1416:        }
                   1417: 
                   1418:        attr = node->properties;
                   1419:        while (attr) {
                   1420:                if (attr->ns) {
                   1421:                        sxe_add_namespace_name(return_value, attr->ns);
                   1422:                }
                   1423:                attr = attr->next;
                   1424:        }
                   1425: 
                   1426:        if (recursive) {
                   1427:                node = node->children;
                   1428:                while (node) {
                   1429:                        if (node->type == XML_ELEMENT_NODE) {
                   1430:                                sxe_add_namespaces(sxe, node, recursive, return_value TSRMLS_CC);
                   1431:                        }
                   1432:                        node = node->next;
                   1433:                }
                   1434:        }
                   1435: } /* }}} */
                   1436: 
                   1437: /* {{{ proto string SimpleXMLElement::getNamespaces([bool recursve])
                   1438:    Return all namespaces in use */
                   1439: SXE_METHOD(getNamespaces)
                   1440: {
                   1441:        zend_bool           recursive = 0;
                   1442:        php_sxe_object     *sxe;
                   1443:        xmlNodePtr          node;
                   1444: 
                   1445:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &recursive) == FAILURE) {
                   1446:                return;
                   1447:        }
                   1448: 
                   1449:        array_init(return_value);
                   1450: 
                   1451:        sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   1452:        GET_NODE(sxe, node);
                   1453:        node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                   1454: 
                   1455:        if (node) {
                   1456:                if (node->type == XML_ELEMENT_NODE) {
                   1457:                        sxe_add_namespaces(sxe, node, recursive, return_value TSRMLS_CC);
                   1458:                } else if (node->type == XML_ATTRIBUTE_NODE && node->ns) {
                   1459:                        sxe_add_namespace_name(return_value, node->ns);
                   1460:                }
                   1461:        }
                   1462: }
                   1463: /* }}} */
                   1464: 
                   1465: static void sxe_add_registered_namespaces(php_sxe_object *sxe, xmlNodePtr node, zend_bool recursive, zval *return_value TSRMLS_DC) /* {{{ */
                   1466: {
                   1467:        xmlNsPtr ns;
                   1468: 
                   1469:        if (node->type == XML_ELEMENT_NODE) {
                   1470:                ns = node->nsDef;
                   1471:                while (ns != NULL) {
                   1472:                        sxe_add_namespace_name(return_value, ns);
                   1473:                        ns = ns->next;
                   1474:                }
                   1475:                if (recursive) {
                   1476:                        node = node->children;
                   1477:                        while (node) {
                   1478:                                sxe_add_registered_namespaces(sxe, node, recursive, return_value TSRMLS_CC);
                   1479:                                node = node->next;
                   1480:                        }
                   1481:                }
                   1482:        }
                   1483: }
                   1484: /* }}} */
                   1485: 
                   1486: /* {{{ proto string SimpleXMLElement::getDocNamespaces([bool recursive])
                   1487:    Return all namespaces registered with document */
                   1488: SXE_METHOD(getDocNamespaces)
                   1489: {
                   1490:        zend_bool           recursive = 0;
                   1491:        php_sxe_object     *sxe;
                   1492: 
                   1493:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &recursive) == FAILURE) {
                   1494:                return;
                   1495:        }
                   1496: 
                   1497:        array_init(return_value);
                   1498: 
                   1499:        sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   1500: 
                   1501:        sxe_add_registered_namespaces(sxe, xmlDocGetRootElement((xmlDocPtr)sxe->document->ptr), recursive, return_value TSRMLS_CC);
                   1502: }
                   1503: /* }}} */
                   1504: 
                   1505: /* {{{ proto object SimpleXMLElement::children([string ns [, bool is_prefix]])
                   1506:    Finds children of given node */
                   1507: SXE_METHOD(children)
                   1508: {
                   1509:        php_sxe_object *sxe;
                   1510:        char           *nsprefix = NULL;
                   1511:        int             nsprefix_len = 0;
                   1512:        xmlNodePtr      node;
                   1513:        zend_bool       isprefix = 0;
                   1514: 
                   1515:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!b", &nsprefix, &nsprefix_len, &isprefix) == FAILURE) {
                   1516:                return;
                   1517:        }
                   1518: 
                   1519:        sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   1520: 
                   1521:        if (sxe->iter.type == SXE_ITER_ATTRLIST) {
                   1522:                return; /* attributes don't have attributes */
                   1523:        }
                   1524: 
                   1525:        GET_NODE(sxe, node);
                   1526:        node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                   1527: 
                   1528:        _node_as_zval(sxe, node, return_value, SXE_ITER_CHILD, NULL, (xmlChar *)nsprefix, isprefix TSRMLS_CC);
                   1529: 
                   1530: }
                   1531: /* }}} */
                   1532: 
                   1533: /* {{{ proto object SimpleXMLElement::getName()
                   1534:    Finds children of given node */
                   1535: SXE_METHOD(getName)
                   1536: {
                   1537:        php_sxe_object *sxe;
                   1538:        xmlNodePtr      node;
                   1539:        int             namelen;
                   1540: 
                   1541:        sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   1542: 
                   1543:        GET_NODE(sxe, node);
                   1544:        node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                   1545:        if (node) {
                   1546:                namelen = xmlStrlen(node->name);
                   1547:                RETURN_STRINGL((char*)node->name, namelen, 1);
                   1548:        } else {
                   1549:                RETURN_EMPTY_STRING();
                   1550:        }
                   1551: }
                   1552: /* }}} */
                   1553: 
                   1554: /* {{{ proto array SimpleXMLElement::attributes([string ns [, bool is_prefix]])
                   1555:    Identifies an element's attributes */
                   1556: SXE_METHOD(attributes)
                   1557: {
                   1558:        php_sxe_object *sxe;
                   1559:        char           *nsprefix = NULL;
                   1560:        int             nsprefix_len = 0;
                   1561:        xmlNodePtr      node;
                   1562:        zend_bool       isprefix = 0;
                   1563: 
                   1564:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!b", &nsprefix, &nsprefix_len, &isprefix) == FAILURE) {
                   1565:                return;
                   1566:        }
                   1567: 
                   1568:        sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   1569:        GET_NODE(sxe, node);
                   1570: 
                   1571:        if (sxe->iter.type == SXE_ITER_ATTRLIST) {
                   1572:                return; /* attributes don't have attributes */
                   1573:        }
                   1574: 
                   1575:        node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                   1576: 
                   1577:        _node_as_zval(sxe, node, return_value, SXE_ITER_ATTRLIST, NULL, (xmlChar *)nsprefix, isprefix TSRMLS_CC);
                   1578: }
                   1579: /* }}} */
                   1580: 
                   1581: /* {{{ proto void SimpleXMLElement::addChild(string qName [, string value [, string ns]])
                   1582:    Add Element with optional namespace information */
                   1583: SXE_METHOD(addChild)
                   1584: {
                   1585:        php_sxe_object *sxe;
                   1586:        char           *qname, *value = NULL, *nsuri = NULL;
                   1587:        int             qname_len, value_len = 0, nsuri_len = 0;
                   1588:        xmlNodePtr      node, newnode;
                   1589:        xmlNsPtr        nsptr = NULL;
                   1590:        xmlChar        *localname, *prefix = NULL;
                   1591: 
                   1592:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!s!",
                   1593:                &qname, &qname_len, &value, &value_len, &nsuri, &nsuri_len) == FAILURE) {
                   1594:                return;
                   1595:        }
                   1596: 
                   1597:        if (qname_len == 0) {
                   1598:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Element name is required");
                   1599:                return;
                   1600:        }
                   1601: 
                   1602:        sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   1603:        GET_NODE(sxe, node);
                   1604: 
                   1605:        if (sxe->iter.type == SXE_ITER_ATTRLIST) {
                   1606:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot add element to attributes");
                   1607:                return;
                   1608:        }
                   1609: 
                   1610:        node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                   1611: 
                   1612:        if (node == NULL) {
                   1613:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot add child. Parent is not a permanent member of the XML tree");
                   1614:                return;
                   1615:        }
                   1616: 
                   1617:        localname = xmlSplitQName2((xmlChar *)qname, &prefix);
                   1618:        if (localname == NULL) {
                   1619:                localname = xmlStrdup((xmlChar *)qname);
                   1620:        }
                   1621: 
                   1622:        newnode = xmlNewChild(node, NULL, localname, (xmlChar *)value);
                   1623: 
                   1624:        if (nsuri != NULL) {
                   1625:                if (nsuri_len == 0) {
                   1626:                        newnode->ns = NULL;
                   1627:                        nsptr = xmlNewNs(newnode, (xmlChar *)nsuri, prefix);
                   1628:                } else {
                   1629:                        nsptr = xmlSearchNsByHref(node->doc, node, (xmlChar *)nsuri);
                   1630:                        if (nsptr == NULL) {
                   1631:                                nsptr = xmlNewNs(newnode, (xmlChar *)nsuri, prefix);
                   1632:                        }
                   1633:                        newnode->ns = nsptr;
                   1634:                }
                   1635:        }
                   1636: 
                   1637:        _node_as_zval(sxe, newnode, return_value, SXE_ITER_NONE, (char *)localname, prefix, 0 TSRMLS_CC);
                   1638: 
                   1639:        xmlFree(localname);
                   1640:        if (prefix != NULL) {
                   1641:                xmlFree(prefix);
                   1642:        }
                   1643: }
                   1644: /* }}} */
                   1645: 
                   1646: /* {{{ proto void SimpleXMLElement::addAttribute(string qName, string value [,string ns])
                   1647:    Add Attribute with optional namespace information */
                   1648: SXE_METHOD(addAttribute)
                   1649: {
                   1650:        php_sxe_object *sxe;
                   1651:        char           *qname, *value = NULL, *nsuri = NULL;
                   1652:        int             qname_len, value_len = 0, nsuri_len = 0;
                   1653:        xmlNodePtr      node;
                   1654:        xmlAttrPtr      attrp = NULL;
                   1655:        xmlNsPtr        nsptr = NULL;
                   1656:        xmlChar        *localname, *prefix = NULL;
                   1657: 
                   1658:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s!",
                   1659:                &qname, &qname_len, &value, &value_len, &nsuri, &nsuri_len) == FAILURE) {
                   1660:                return;
                   1661:        }
                   1662: 
                   1663:        if (qname_len == 0) {
                   1664:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attribute name is required");
                   1665:                return;
                   1666:        }
                   1667: 
                   1668:        sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   1669:        GET_NODE(sxe, node);
                   1670: 
                   1671:        node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                   1672: 
                   1673:        if (node && node->type != XML_ELEMENT_NODE) {
                   1674:                node = node->parent;
                   1675:        }
                   1676: 
                   1677:        if (node == NULL) {
                   1678:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to locate parent Element");
                   1679:                return;
                   1680:        }
                   1681: 
                   1682:        localname = xmlSplitQName2((xmlChar *)qname, &prefix);
                   1683:        if (localname == NULL) {
                   1684:                if (nsuri_len > 0) {
                   1685:                        if (prefix != NULL) {
                   1686:                                xmlFree(prefix);
                   1687:                        }
                   1688:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attribute requires prefix for namespace");
                   1689:                        return;
                   1690:                }
                   1691:                localname = xmlStrdup((xmlChar *)qname);
                   1692:        }
                   1693: 
                   1694:        attrp = xmlHasNsProp(node, localname, (xmlChar *)nsuri);
                   1695:        if (attrp != NULL && attrp->type != XML_ATTRIBUTE_DECL) {
                   1696:                xmlFree(localname);
                   1697:                if (prefix != NULL) {
                   1698:                        xmlFree(prefix);
                   1699:                }
                   1700:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attribute already exists");
                   1701:                return;
                   1702:        }
                   1703: 
                   1704:        if (nsuri != NULL) {
                   1705:                nsptr = xmlSearchNsByHref(node->doc, node, (xmlChar *)nsuri);
                   1706:                if (nsptr == NULL) {
                   1707:                        nsptr = xmlNewNs(node, (xmlChar *)nsuri, prefix);
                   1708:                }
                   1709:        }
                   1710: 
                   1711:        attrp = xmlNewNsProp(node, nsptr, localname, (xmlChar *)value);
                   1712: 
                   1713:        xmlFree(localname);
                   1714:        if (prefix != NULL) {
                   1715:                xmlFree(prefix);
                   1716:        }
                   1717: }
                   1718: /* }}} */
                   1719: 
                   1720: /* {{{ cast_object()
                   1721:  */
                   1722: static int cast_object(zval *object, int type, char *contents TSRMLS_DC)
                   1723: {
                   1724:        if (contents) {
                   1725:                ZVAL_STRINGL(object, contents, strlen(contents), 1);
                   1726:        } else {
                   1727:                ZVAL_NULL(object);
                   1728:        }
                   1729:        Z_SET_REFCOUNT_P(object, 1);
                   1730:        Z_UNSET_ISREF_P(object);
                   1731: 
                   1732:        switch (type) {
                   1733:                case IS_STRING:
                   1734:                        convert_to_string(object);
                   1735:                        break;
                   1736:                case IS_BOOL:
                   1737:                        convert_to_boolean(object);
                   1738:                        break;
                   1739:                case IS_LONG:
                   1740:                        convert_to_long(object);
                   1741:                        break;
                   1742:                case IS_DOUBLE:
                   1743:                        convert_to_double(object);
                   1744:                        break;
                   1745:                default:
                   1746:                        return FAILURE;
                   1747:        }
                   1748:        return SUCCESS;
                   1749: }
                   1750: /* }}} */
                   1751: 
                   1752: /* {{{ sxe_object_cast()
                   1753:  */
                   1754: static int sxe_object_cast(zval *readobj, zval *writeobj, int type TSRMLS_DC)
                   1755: {
                   1756:        php_sxe_object *sxe;
                   1757:        xmlChar           *contents = NULL;
                   1758:        xmlNodePtr          node;
                   1759:        int rv;
                   1760:        HashTable      *prop_hash;
                   1761: 
                   1762:        sxe = php_sxe_fetch_object(readobj TSRMLS_CC);
                   1763: 
                   1764:        if (type == IS_BOOL) {
                   1765:                node = php_sxe_get_first_node(sxe, NULL TSRMLS_CC);
                   1766:                prop_hash = sxe_get_prop_hash(readobj, 1 TSRMLS_CC);
                   1767:                INIT_PZVAL(writeobj);
                   1768:                ZVAL_BOOL(writeobj, node != NULL || zend_hash_num_elements(prop_hash) > 0);
                   1769:                zend_hash_destroy(prop_hash);
                   1770:                efree(prop_hash);
                   1771:                return SUCCESS;
                   1772:        }
                   1773: 
                   1774:        if (sxe->iter.type != SXE_ITER_NONE) {
                   1775:                node = php_sxe_get_first_node(sxe, NULL TSRMLS_CC);
                   1776:                if (node) {
                   1777:                        contents = xmlNodeListGetString((xmlDocPtr) sxe->document->ptr, node->children, 1);
                   1778:                }
                   1779:        } else {
                   1780:                if (!sxe->node) {
                   1781:                        if (sxe->document) {
                   1782:                                php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement((xmlDocPtr) sxe->document->ptr), NULL TSRMLS_CC);
                   1783:                        }
                   1784:                }
                   1785: 
                   1786:                if (sxe->node && sxe->node->node) {
                   1787:                        if (sxe->node->node->children) {
                   1788:                                contents = xmlNodeListGetString((xmlDocPtr) sxe->document->ptr, sxe->node->node->children, 1);
                   1789:                        }
                   1790:                }
                   1791:        }
                   1792: 
                   1793:        if (readobj == writeobj) {
                   1794:                INIT_PZVAL(writeobj);
                   1795:                zval_dtor(readobj);
                   1796:        }
                   1797: 
                   1798:        rv = cast_object(writeobj, type, (char *)contents TSRMLS_CC);
                   1799: 
                   1800:        if (contents) {
                   1801:                xmlFree(contents);
                   1802:        }
                   1803:        return rv;
                   1804: }
                   1805: /* }}} */
                   1806: 
                   1807: /* {{{ proto object SimpleXMLElement::__toString() U
                   1808:    Returns the string content */
                   1809: SXE_METHOD(__toString)
                   1810: {
                   1811:        zval           *result;
                   1812: 
                   1813:        ALLOC_INIT_ZVAL(result);
                   1814: 
                   1815:        if (sxe_object_cast(getThis(), result, IS_STRING TSRMLS_CC) == SUCCESS) {
                   1816:                RETURN_ZVAL(result, 1, 1);
                   1817:        } else {
                   1818:                zval_ptr_dtor(&result);
                   1819:                RETURN_EMPTY_STRING();
                   1820:        }
                   1821: }
                   1822: /* }}} */
                   1823: 
                   1824: static int php_sxe_count_elements_helper(php_sxe_object *sxe, long *count TSRMLS_DC) /* {{{ */
                   1825: {
                   1826:        xmlNodePtr       node;
                   1827:        zval            *data;
                   1828: 
                   1829:        *count = 0;
                   1830: 
                   1831:        data = sxe->iter.data;
                   1832:        sxe->iter.data = NULL;
                   1833: 
                   1834:        node = php_sxe_reset_iterator(sxe, 0 TSRMLS_CC);
                   1835: 
                   1836:        while (node)
                   1837:        {
                   1838:                (*count)++;
                   1839:                node = php_sxe_iterator_fetch(sxe, node->next, 0 TSRMLS_CC);
                   1840:        }
                   1841: 
                   1842:        if (sxe->iter.data) {
                   1843:                zval_ptr_dtor(&sxe->iter.data);
                   1844:        }
                   1845:        sxe->iter.data = data;
                   1846: 
                   1847:        return SUCCESS;
                   1848: }
                   1849: /* }}} */
                   1850: 
                   1851: static int sxe_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */
                   1852: {
                   1853:        php_sxe_object  *intern;
                   1854:        intern = php_sxe_fetch_object(object TSRMLS_CC);
                   1855:        if (intern->fptr_count) {
                   1856:                zval *rv;
                   1857:                zend_call_method_with_0_params(&object, intern->zo.ce, &intern->fptr_count, "count", &rv);
                   1858:                if (rv) {
                   1859:                        if (intern->tmp) {
                   1860:                                zval_ptr_dtor(&intern->tmp);
                   1861:                        }
                   1862:                        MAKE_STD_ZVAL(intern->tmp);
                   1863:                        ZVAL_ZVAL(intern->tmp, rv, 1, 1);
                   1864:                        convert_to_long(intern->tmp);
                   1865:                        *count = (long) Z_LVAL_P(intern->tmp);
                   1866:                        return SUCCESS;
                   1867:                }
                   1868:                return FAILURE;
                   1869:        }
                   1870:        return php_sxe_count_elements_helper(intern, count TSRMLS_CC);
                   1871: }
                   1872: /* }}} */
                   1873: 
                   1874: /* {{{ proto int SimpleXMLElement::count()
                   1875:  Get number of child elements */
                   1876: SXE_METHOD(count)
                   1877: {
                   1878:        long count = 0;
                   1879:        php_sxe_object *sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   1880: 
                   1881:        if (zend_parse_parameters_none() == FAILURE) {
                   1882:                return;
                   1883:        }
                   1884: 
                   1885:        php_sxe_count_elements_helper(sxe, &count TSRMLS_CC);
                   1886:        
                   1887:        RETURN_LONG(count);
                   1888: }
                   1889: /* }}} */
                   1890: 
                   1891: static zval *sxe_get_value(zval *z TSRMLS_DC) /* {{{ */
                   1892: {
                   1893:        zval *retval;
                   1894: 
                   1895:        MAKE_STD_ZVAL(retval);
                   1896: 
                   1897:        if (sxe_object_cast(z, retval, IS_STRING TSRMLS_CC)==FAILURE) {
                   1898:                zend_error(E_ERROR, "Unable to cast node to string");
                   1899:                /* FIXME: Should not be fatal */
                   1900:        }
                   1901: 
                   1902:        Z_SET_REFCOUNT_P(retval, 0);
                   1903:        return retval;
                   1904: }
                   1905: /* }}} */
                   1906: 
                   1907: static zend_object_handlers sxe_object_handlers = { /* {{{ */
                   1908:        ZEND_OBJECTS_STORE_HANDLERS,
                   1909:        sxe_property_read,
                   1910:        sxe_property_write,
                   1911:        sxe_dimension_read,
                   1912:        sxe_dimension_write,
                   1913:        sxe_property_get_adr,
                   1914:        sxe_get_value,                  /* get */
                   1915:        NULL,
                   1916:        sxe_property_exists,
                   1917:        sxe_property_delete,
                   1918:        sxe_dimension_exists,
                   1919:        sxe_dimension_delete,
                   1920:        sxe_get_properties,
                   1921:        NULL, /* zend_get_std_object_handlers()->get_method,*/
                   1922:        NULL, /* zend_get_std_object_handlers()->call_method,*/
                   1923:        NULL, /* zend_get_std_object_handlers()->get_constructor, */
                   1924:        NULL, /* zend_get_std_object_handlers()->get_class_entry,*/
                   1925:        NULL, /* zend_get_std_object_handlers()->get_class_name,*/
                   1926:        sxe_objects_compare,
                   1927:        sxe_object_cast,
                   1928:        sxe_count_elements,
                   1929:        sxe_get_debug_info
                   1930: };
                   1931: /* }}} */
                   1932: 
                   1933: /* {{{ sxe_object_clone()
                   1934:  */
                   1935: static void
                   1936: sxe_object_clone(void *object, void **clone_ptr TSRMLS_DC)
                   1937: {
                   1938:        php_sxe_object *sxe = (php_sxe_object *) object;
                   1939:        php_sxe_object *clone;
                   1940:        xmlNodePtr nodep = NULL;
                   1941:        xmlDocPtr docp = NULL;
                   1942: 
                   1943:        clone = php_sxe_object_new(sxe->zo.ce TSRMLS_CC);
                   1944:        clone->document = sxe->document;
                   1945:        if (clone->document) {
                   1946:                clone->document->refcount++;
                   1947:                docp = clone->document->ptr;
                   1948:        }
                   1949: 
                   1950:        clone->iter.isprefix = sxe->iter.isprefix;
                   1951:        if (sxe->iter.name != NULL) {
                   1952:                clone->iter.name = xmlStrdup((xmlChar *)sxe->iter.name);
                   1953:        }
                   1954:        if (sxe->iter.nsprefix != NULL) {
                   1955:                clone->iter.nsprefix = xmlStrdup((xmlChar *)sxe->iter.nsprefix);
                   1956:        }
                   1957:        clone->iter.type = sxe->iter.type;
                   1958: 
                   1959:        if (sxe->node) {
                   1960:                nodep = xmlDocCopyNode(sxe->node->node, docp, 1);
                   1961:        }
                   1962: 
                   1963:        php_libxml_increment_node_ptr((php_libxml_node_object *)clone, nodep, NULL TSRMLS_CC);
                   1964: 
                   1965:        *clone_ptr = (void *) clone;
                   1966: }
                   1967: /* }}} */
                   1968: 
                   1969: /* {{{ sxe_object_dtor()
                   1970:  */
                   1971: static void sxe_object_dtor(void *object, zend_object_handle handle TSRMLS_DC)
                   1972: {
                   1973:        /* dtor required to cleanup iterator related data properly */
                   1974: 
                   1975:        php_sxe_object *sxe;
                   1976: 
                   1977:        sxe = (php_sxe_object *) object;
                   1978: 
                   1979:        if (sxe->iter.data) {
                   1980:                zval_ptr_dtor(&sxe->iter.data);
                   1981:                sxe->iter.data = NULL;
                   1982:        }
                   1983: 
                   1984:        if (sxe->iter.name) {
                   1985:                xmlFree(sxe->iter.name);
                   1986:                sxe->iter.name = NULL;
                   1987:        }
                   1988:        if (sxe->iter.nsprefix) {
                   1989:                xmlFree(sxe->iter.nsprefix);
                   1990:                sxe->iter.nsprefix = NULL;
                   1991:        }
                   1992:        if (sxe->tmp) {
                   1993:                zval_ptr_dtor(&sxe->tmp);
                   1994:                sxe->tmp = NULL;
                   1995:        }
                   1996: }
                   1997: /* }}} */
                   1998: 
                   1999: /* {{{ sxe_object_free_storage()
                   2000:  */
                   2001: static void sxe_object_free_storage(void *object TSRMLS_DC)
                   2002: {
                   2003:        php_sxe_object *sxe;
                   2004: 
                   2005:        sxe = (php_sxe_object *) object;
                   2006: 
                   2007: #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)
                   2008:        zend_object_std_dtor(&sxe->zo TSRMLS_CC);
                   2009: #else
                   2010:        if (sxe->zo.guards) {
                   2011:                zend_hash_destroy(sxe->zo.guards);
                   2012:                FREE_HASHTABLE(sxe->zo.guards);
                   2013:        }
                   2014: 
                   2015:        if (sxe->zo.properties) {
                   2016:                zend_hash_destroy(sxe->zo.properties);
                   2017:                FREE_HASHTABLE(sxe->zo.properties);
                   2018:        }
                   2019: #endif
                   2020: 
                   2021:        php_libxml_node_decrement_resource((php_libxml_node_object *)sxe TSRMLS_CC);
                   2022: 
                   2023:        if (sxe->xpath) {
                   2024:                xmlXPathFreeContext(sxe->xpath);
                   2025:        }
                   2026: 
                   2027:        if (sxe->properties) {
                   2028:                zend_hash_destroy(sxe->properties);
                   2029:                FREE_HASHTABLE(sxe->properties);
                   2030:        }
                   2031: 
                   2032:        efree(object);
                   2033: }
                   2034: /* }}} */
                   2035: 
                   2036: /* {{{ php_sxe_object_new()
                   2037:  */
                   2038: static php_sxe_object* php_sxe_object_new(zend_class_entry *ce TSRMLS_DC)
                   2039: {
                   2040:        php_sxe_object *intern;
                   2041:        zend_class_entry     *parent = ce;
                   2042:        int inherited = 0;
                   2043: 
                   2044:        intern = ecalloc(1, sizeof(php_sxe_object));
                   2045: 
                   2046:        intern->iter.type = SXE_ITER_NONE;
                   2047:        intern->iter.nsprefix = NULL;
                   2048:        intern->iter.name = NULL;
                   2049:        intern->fptr_count = NULL;
                   2050: 
                   2051: #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)
                   2052:        zend_object_std_init(&intern->zo, ce TSRMLS_CC);
                   2053: #else
                   2054:        ALLOC_HASHTABLE(intern->zo.properties);
                   2055:        zend_hash_init(intern->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
                   2056: 
                   2057:        intern->zo.ce = ce;
                   2058:        intern->zo.guards = NULL;
                   2059: #endif
                   2060: 
                   2061:        while (parent) {
                   2062:                if (parent == sxe_class_entry) {
                   2063:                        break;
                   2064:                }
                   2065: 
                   2066:                parent = parent->parent;
                   2067:                inherited = 1;
                   2068:        }
                   2069: 
                   2070:        if (inherited) {
                   2071:                zend_hash_find(&ce->function_table, "count", sizeof("count"),(void **) &intern->fptr_count);
                   2072:                if (intern->fptr_count->common.scope == parent) {
                   2073:                        intern->fptr_count = NULL;
                   2074:                }
                   2075:        }
                   2076: 
                   2077:        return intern;
                   2078: }
                   2079: /* }}} */
                   2080: 
                   2081: /* {{{ php_sxe_register_object
                   2082:  */
                   2083: static zend_object_value
                   2084: php_sxe_register_object(php_sxe_object *intern TSRMLS_DC)
                   2085: {
                   2086:        zend_object_value rv;
                   2087: 
                   2088:        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);
                   2089:        rv.handlers = (zend_object_handlers *) &sxe_object_handlers;
                   2090: 
                   2091:        return rv;
                   2092: }
                   2093: /* }}} */
                   2094: 
                   2095: /* {{{ sxe_object_new()
                   2096:  */
                   2097: PHP_SXE_API zend_object_value
                   2098: sxe_object_new(zend_class_entry *ce TSRMLS_DC)
                   2099: {
                   2100:        php_sxe_object    *intern;
                   2101: 
                   2102:        intern = php_sxe_object_new(ce TSRMLS_CC);
                   2103:        return php_sxe_register_object(intern TSRMLS_CC);
                   2104: }
                   2105: /* }}} */
                   2106: 
                   2107: /* {{{ proto simplemxml_element simplexml_load_file(string filename [, string class_name [, int options [, string ns [, bool is_prefix]]]])
                   2108:    Load a filename and return a simplexml_element object to allow for processing */
                   2109: PHP_FUNCTION(simplexml_load_file)
                   2110: {
                   2111:        php_sxe_object *sxe;
                   2112:        char           *filename;
                   2113:        int             filename_len;
                   2114:        xmlDocPtr       docp;
                   2115:        char           *ns = NULL;
                   2116:        int             ns_len = 0;
                   2117:        long            options = 0;
                   2118:        zend_class_entry *ce= sxe_class_entry;
                   2119:        zend_bool       isprefix = 0;
                   2120: 
                   2121:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|C!lsb", &filename, &filename_len, &ce, &options, &ns, &ns_len, &isprefix) == FAILURE) {
                   2122:                return;
                   2123:        }
                   2124: 
                   2125:        docp = xmlReadFile(filename, NULL, options);
                   2126: 
                   2127:        if (! docp) {
                   2128:                RETURN_FALSE;
                   2129:        }
                   2130: 
                   2131:        if (!ce) {
                   2132:                ce = sxe_class_entry;
                   2133:        }
                   2134:        sxe = php_sxe_object_new(ce TSRMLS_CC);
                   2135:        sxe->iter.nsprefix = ns_len ? xmlStrdup((xmlChar *)ns) : NULL;
                   2136:        sxe->iter.isprefix = isprefix;
                   2137:        php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, docp TSRMLS_CC);
                   2138:        php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement(docp), NULL TSRMLS_CC);
                   2139: 
                   2140:        return_value->type = IS_OBJECT;
                   2141:        return_value->value.obj = php_sxe_register_object(sxe TSRMLS_CC);
                   2142: }
                   2143: /* }}} */
                   2144: 
                   2145: /* {{{ proto simplemxml_element simplexml_load_string(string data [, string class_name [, int options [, string ns [, bool is_prefix]]]])
                   2146:    Load a string and return a simplexml_element object to allow for processing */
                   2147: PHP_FUNCTION(simplexml_load_string)
                   2148: {
                   2149:        php_sxe_object *sxe;
                   2150:        char           *data;
                   2151:        int             data_len;
                   2152:        xmlDocPtr       docp;
                   2153:        char           *ns = NULL;
                   2154:        int             ns_len = 0;
                   2155:        long            options = 0;
                   2156:        zend_class_entry *ce= sxe_class_entry;
                   2157:        zend_bool       isprefix = 0;
                   2158: 
                   2159:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|C!lsb", &data, &data_len, &ce, &options, &ns, &ns_len, &isprefix) == FAILURE) {
                   2160:                return;
                   2161:        }
                   2162: 
                   2163:        docp = xmlReadMemory(data, data_len, NULL, NULL, options);
                   2164: 
                   2165:        if (! docp) {
                   2166:                RETURN_FALSE;
                   2167:        }
                   2168: 
                   2169:        if (!ce) {
                   2170:                ce = sxe_class_entry;
                   2171:        }
                   2172:        sxe = php_sxe_object_new(ce TSRMLS_CC);
                   2173:        sxe->iter.nsprefix = ns_len ? xmlStrdup((xmlChar *)ns) : NULL;
                   2174:        sxe->iter.isprefix = isprefix;
                   2175:        php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, docp TSRMLS_CC);
                   2176:        php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement(docp), NULL TSRMLS_CC);
                   2177: 
                   2178:        return_value->type = IS_OBJECT;
                   2179:        return_value->value.obj = php_sxe_register_object(sxe TSRMLS_CC);
                   2180: }
                   2181: /* }}} */
                   2182: 
                   2183: /* {{{ proto SimpleXMLElement::__construct(string data [, int options [, bool data_is_url [, string ns [, bool is_prefix]]]])
                   2184:    SimpleXMLElement constructor */
                   2185: SXE_METHOD(__construct)
                   2186: {
                   2187:        php_sxe_object *sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   2188:        char           *data, *ns = NULL;
                   2189:        int             data_len, ns_len = 0;
                   2190:        xmlDocPtr       docp;
                   2191:        long            options = 0;
                   2192:        zend_bool       is_url = 0, isprefix = 0;
                   2193:        zend_error_handling error_handling;
                   2194: 
                   2195:        zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC);
                   2196:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lbsb", &data, &data_len, &options, &is_url, &ns, &ns_len, &isprefix) == FAILURE) {
                   2197:                zend_restore_error_handling(&error_handling TSRMLS_CC);
                   2198:                return;
                   2199:        }
                   2200: 
                   2201:        zend_restore_error_handling(&error_handling TSRMLS_CC);
                   2202: 
                   2203:        docp = is_url ? xmlReadFile(data, NULL, options) : xmlReadMemory(data, data_len, NULL, NULL, options);
                   2204: 
                   2205:        if (!docp) {
                   2206:                ((php_libxml_node_object *)sxe)->document = NULL;
                   2207:                zend_throw_exception(zend_exception_get_default(TSRMLS_C), "String could not be parsed as XML", 0 TSRMLS_CC);
                   2208:                return;
                   2209:        }
                   2210: 
                   2211:        sxe->iter.nsprefix = ns_len ? xmlStrdup((xmlChar *)ns) : NULL;
                   2212:        sxe->iter.isprefix = isprefix;
                   2213:        php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, docp TSRMLS_CC);
                   2214:        php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement(docp), NULL TSRMLS_CC);
                   2215: }
                   2216: /* }}} */
                   2217: 
                   2218: zend_object_iterator_funcs php_sxe_iterator_funcs = { /* {{{ */
                   2219:        php_sxe_iterator_dtor,
                   2220:        php_sxe_iterator_valid,
                   2221:        php_sxe_iterator_current_data,
                   2222:        php_sxe_iterator_current_key,
                   2223:        php_sxe_iterator_move_forward,
                   2224:        php_sxe_iterator_rewind,
                   2225: };
                   2226: /* }}} */
                   2227: 
                   2228: static xmlNodePtr php_sxe_iterator_fetch(php_sxe_object *sxe, xmlNodePtr node, int use_data TSRMLS_DC) /* {{{ */
                   2229: {
                   2230:        xmlChar *prefix  = sxe->iter.nsprefix;
                   2231:        int isprefix  = sxe->iter.isprefix;
                   2232:        int test_elem = sxe->iter.type == SXE_ITER_ELEMENT  && sxe->iter.name;
                   2233:        int test_attr = sxe->iter.type == SXE_ITER_ATTRLIST && sxe->iter.name;
                   2234: 
                   2235:        while (node) {
                   2236:                SKIP_TEXT(node);
                   2237:                if (sxe->iter.type != SXE_ITER_ATTRLIST && node->type == XML_ELEMENT_NODE) {
                   2238:                        if ((!test_elem || !xmlStrcmp(node->name, sxe->iter.name)) && match_ns(sxe, node, prefix, isprefix)) {
                   2239:                                break;
                   2240:                        }
                   2241:                } else if (node->type == XML_ATTRIBUTE_NODE) {
                   2242:                        if ((!test_attr || !xmlStrcmp(node->name, sxe->iter.name)) && match_ns(sxe, node, prefix, isprefix)) {
                   2243:                                break;
                   2244:                        }
                   2245:                }
                   2246: next_iter:
                   2247:                node = node->next;
                   2248:        }
                   2249: 
                   2250:        if (node && use_data) {
                   2251:                ALLOC_INIT_ZVAL(sxe->iter.data);
                   2252:                _node_as_zval(sxe, node, sxe->iter.data, SXE_ITER_NONE, NULL, prefix, isprefix TSRMLS_CC);
                   2253:        }
                   2254: 
                   2255:        return node;
                   2256: }
                   2257: /* }}} */
                   2258: 
                   2259: static xmlNodePtr php_sxe_reset_iterator(php_sxe_object *sxe, int use_data TSRMLS_DC) /* {{{ */
                   2260: {
                   2261:        xmlNodePtr node;
                   2262: 
                   2263:        if (sxe->iter.data) {
                   2264:                zval_ptr_dtor(&sxe->iter.data);
                   2265:                sxe->iter.data = NULL;
                   2266:        }
                   2267: 
                   2268:        GET_NODE(sxe, node)
                   2269: 
                   2270:        if (node) {
                   2271:                switch (sxe->iter.type) {
                   2272:                        case SXE_ITER_ELEMENT:
                   2273:                        case SXE_ITER_CHILD:
                   2274:                        case SXE_ITER_NONE:
                   2275:                                node = node->children;
                   2276:                                break;
                   2277:                        case SXE_ITER_ATTRLIST:
                   2278:                                node = (xmlNodePtr) node->properties;
                   2279:                }
                   2280:                return php_sxe_iterator_fetch(sxe, node, use_data TSRMLS_CC);
                   2281:        }
                   2282:        return NULL;
                   2283: }
                   2284: /* }}} */
                   2285: 
                   2286: zend_object_iterator *php_sxe_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */
                   2287: {
                   2288:        php_sxe_iterator *iterator;
                   2289: 
                   2290:        if (by_ref) {
                   2291:                zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
                   2292:        }
                   2293:        iterator = emalloc(sizeof(php_sxe_iterator));
                   2294: 
                   2295:        Z_ADDREF_P(object);
                   2296:        iterator->intern.data = (void*)object;
                   2297:        iterator->intern.funcs = &php_sxe_iterator_funcs;
                   2298:        iterator->sxe = php_sxe_fetch_object(object TSRMLS_CC);
                   2299: 
                   2300:        return (zend_object_iterator*)iterator;
                   2301: }
                   2302: /* }}} */
                   2303: 
                   2304: static void php_sxe_iterator_dtor(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
                   2305: {
                   2306:        php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
                   2307: 
                   2308:        /* cleanup handled in sxe_object_dtor as we dont always have an iterator wrapper */
                   2309:        if (iterator->intern.data) {
                   2310:                zval_ptr_dtor((zval**)&iterator->intern.data);
                   2311:        }
                   2312: 
                   2313:        efree(iterator);
                   2314: }
                   2315: /* }}} */
                   2316: 
                   2317: static int php_sxe_iterator_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
                   2318: {
                   2319:        php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
                   2320: 
                   2321:        return iterator->sxe->iter.data ? SUCCESS : FAILURE;
                   2322: }
                   2323: /* }}} */
                   2324: 
                   2325: static void php_sxe_iterator_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */
                   2326: {
                   2327:        php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
                   2328: 
                   2329:        *data = &iterator->sxe->iter.data;
                   2330: }
                   2331: /* }}} */
                   2332: 
                   2333: static int php_sxe_iterator_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */
                   2334: {
                   2335:        zval *curobj;
                   2336:        xmlNodePtr curnode = NULL;
                   2337:        php_sxe_object *intern;
                   2338:        int namelen;
                   2339: 
                   2340:        php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
                   2341:        curobj = iterator->sxe->iter.data;
                   2342: 
                   2343:        intern = (php_sxe_object *)zend_object_store_get_object(curobj TSRMLS_CC);
                   2344:        if (intern != NULL && intern->node != NULL) {
                   2345:                curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->node)->node;
                   2346:        }
                   2347:        if (!curnode) {
                   2348:                return HASH_KEY_NON_EXISTANT;
                   2349:        }
                   2350: 
                   2351:        namelen = xmlStrlen(curnode->name);
                   2352:        *str_key = estrndup((char *)curnode->name, namelen);
                   2353:        *str_key_len = namelen + 1;
                   2354:        return HASH_KEY_IS_STRING;
                   2355: 
                   2356: }
                   2357: /* }}} */
                   2358: 
                   2359: PHP_SXE_API void php_sxe_move_forward_iterator(php_sxe_object *sxe TSRMLS_DC) /* {{{ */
                   2360: {
                   2361:        xmlNodePtr      node = NULL;
                   2362:        php_sxe_object  *intern;
                   2363: 
                   2364:        if (sxe->iter.data) {
                   2365:                intern = (php_sxe_object *)zend_object_store_get_object(sxe->iter.data TSRMLS_CC);
                   2366:                GET_NODE(intern, node)
                   2367:                zval_ptr_dtor(&sxe->iter.data);
                   2368:                sxe->iter.data = NULL;
                   2369:        }
                   2370: 
                   2371:        if (node) {
                   2372:                php_sxe_iterator_fetch(sxe, node->next, 1 TSRMLS_CC);
                   2373:        }
                   2374: }
                   2375: /* }}} */
                   2376: 
                   2377: static void php_sxe_iterator_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
                   2378: {
                   2379:        php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
                   2380:        php_sxe_move_forward_iterator(iterator->sxe TSRMLS_CC);
                   2381: }
                   2382: /* }}} */
                   2383: 
                   2384: static void php_sxe_iterator_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
                   2385: {
                   2386:        php_sxe_object  *sxe;
                   2387: 
                   2388:        php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
                   2389:        sxe = iterator->sxe;
                   2390: 
                   2391:        php_sxe_reset_iterator(sxe, 1 TSRMLS_CC);
                   2392: }
                   2393: /* }}} */
                   2394: 
                   2395: void *simplexml_export_node(zval *object TSRMLS_DC) /* {{{ */
                   2396: {
                   2397:        php_sxe_object *sxe;
                   2398:        xmlNodePtr node;
                   2399: 
                   2400:        sxe = php_sxe_fetch_object(object TSRMLS_CC);
                   2401:        GET_NODE(sxe, node);
                   2402:        return php_sxe_get_first_node(sxe, node TSRMLS_CC);
                   2403: }
                   2404: /* }}} */
                   2405: 
                   2406: /* {{{ proto simplemxml_element simplexml_import_dom(domNode node [, string class_name])
                   2407:    Get a simplexml_element object from dom to allow for processing */
                   2408: PHP_FUNCTION(simplexml_import_dom)
                   2409: {
                   2410:        php_sxe_object *sxe;
                   2411:        zval *node;
                   2412:        php_libxml_node_object *object;
                   2413:        xmlNodePtr              nodep = NULL;
                   2414:        zend_class_entry *ce= sxe_class_entry;
                   2415: 
                   2416:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o|C!", &node, &ce) == FAILURE) {
                   2417:                return;
                   2418:        }
                   2419: 
                   2420:        object = (php_libxml_node_object *)zend_object_store_get_object(node TSRMLS_CC);
                   2421: 
                   2422:        nodep = php_libxml_import_node(node TSRMLS_CC);
                   2423: 
                   2424:        if (nodep) {
                   2425:                if (nodep->doc == NULL) {
                   2426:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Imported Node must have associated Document");
                   2427:                        RETURN_NULL();
                   2428:                }
                   2429:                if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) {
                   2430:                        nodep = xmlDocGetRootElement((xmlDocPtr) nodep);
                   2431:                }
                   2432:        }
                   2433: 
                   2434:        if (nodep && nodep->type == XML_ELEMENT_NODE) {
                   2435:                if (!ce) {
                   2436:                        ce = sxe_class_entry;
                   2437:                }
                   2438:                sxe = php_sxe_object_new(ce TSRMLS_CC);
                   2439:                sxe->document = object->document;
                   2440:                php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, nodep->doc TSRMLS_CC);
                   2441:                php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, nodep, NULL TSRMLS_CC);
                   2442: 
                   2443:                return_value->type = IS_OBJECT;
                   2444:                return_value->value.obj = php_sxe_register_object(sxe TSRMLS_CC);
                   2445:        } else {
                   2446:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Nodetype to import");
                   2447:                RETVAL_NULL();
                   2448:        }
                   2449: }
                   2450: /* }}} */
                   2451: 
                   2452: /* {{{ arginfo */
                   2453: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexml_load_file, 0, 0, 1)
                   2454:        ZEND_ARG_INFO(0, filename)
                   2455:        ZEND_ARG_INFO(0, class_name)
                   2456:        ZEND_ARG_INFO(0, options)
                   2457:        ZEND_ARG_INFO(0, ns)
                   2458:        ZEND_ARG_INFO(0, is_prefix)
                   2459: ZEND_END_ARG_INFO()
                   2460: 
                   2461: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexml_load_string, 0, 0, 1)
                   2462:        ZEND_ARG_INFO(0, data)
                   2463:        ZEND_ARG_INFO(0, class_name)
                   2464:        ZEND_ARG_INFO(0, options)
                   2465:        ZEND_ARG_INFO(0, ns)
                   2466:        ZEND_ARG_INFO(0, is_prefix)
                   2467: ZEND_END_ARG_INFO()
                   2468: 
                   2469: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexml_import_dom, 0, 0, 1)
                   2470:        ZEND_ARG_INFO(0, node)
                   2471:        ZEND_ARG_INFO(0, class_name)
                   2472: ZEND_END_ARG_INFO()
                   2473: 
                   2474: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_xpath, 0, 0, 1)
                   2475:        ZEND_ARG_INFO(0, path)
                   2476: ZEND_END_ARG_INFO()
                   2477: 
                   2478: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_registerxpathnamespace, 0, 0, 2)
                   2479:        ZEND_ARG_INFO(0, prefix)
                   2480:        ZEND_ARG_INFO(0, ns)
                   2481: ZEND_END_ARG_INFO()
                   2482: 
                   2483: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_asxml, 0, 0, 0)
                   2484:        ZEND_ARG_INFO(0, filename)
                   2485: ZEND_END_ARG_INFO()
                   2486: 
                   2487: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_getnamespaces, 0, 0, 0)
                   2488:        ZEND_ARG_INFO(0, recursve)
                   2489: ZEND_END_ARG_INFO()
                   2490: 
                   2491: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_children, 0, 0, 0)
                   2492:        ZEND_ARG_INFO(0, ns)
                   2493:        ZEND_ARG_INFO(0, is_prefix)
                   2494: ZEND_END_ARG_INFO()
                   2495: 
                   2496: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement__construct, 0, 0, 1)
                   2497:        ZEND_ARG_INFO(0, data)
                   2498:        ZEND_ARG_INFO(0, options)
                   2499:        ZEND_ARG_INFO(0, data_is_url)
                   2500:        ZEND_ARG_INFO(0, ns)
                   2501:        ZEND_ARG_INFO(0, is_prefix)
                   2502: ZEND_END_ARG_INFO()
                   2503: 
                   2504: ZEND_BEGIN_ARG_INFO(arginfo_simplexmlelement__void, 0)
                   2505: ZEND_END_ARG_INFO()
                   2506: 
                   2507: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_addchild, 0, 0, 1)
                   2508:        ZEND_ARG_INFO(0, name)
                   2509:        ZEND_ARG_INFO(0, value)
                   2510:        ZEND_ARG_INFO(0, ns)
                   2511: ZEND_END_ARG_INFO()
                   2512: /* }}} */
                   2513: 
                   2514: const zend_function_entry simplexml_functions[] = { /* {{{ */
                   2515:        PHP_FE(simplexml_load_file,     arginfo_simplexml_load_file)
                   2516:        PHP_FE(simplexml_load_string,   arginfo_simplexml_load_string)
                   2517:        PHP_FE(simplexml_import_dom,    arginfo_simplexml_import_dom)
                   2518:        PHP_FE_END
                   2519: };
                   2520: /* }}} */
                   2521: 
                   2522: static const zend_module_dep simplexml_deps[] = { /* {{{ */
                   2523:        ZEND_MOD_REQUIRED("libxml")
                   2524:        ZEND_MOD_REQUIRED("spl")
                   2525:        ZEND_MOD_END
                   2526: };
                   2527: /* }}} */
                   2528: 
                   2529: zend_module_entry simplexml_module_entry = { /* {{{ */
                   2530:        STANDARD_MODULE_HEADER_EX, NULL,
                   2531:        simplexml_deps,
                   2532:        "SimpleXML",
                   2533:        simplexml_functions,
                   2534:        PHP_MINIT(simplexml),
                   2535:        PHP_MSHUTDOWN(simplexml),
                   2536:        NULL,
                   2537:        NULL,
                   2538:        PHP_MINFO(simplexml),
                   2539:        "0.1",
                   2540:        STANDARD_MODULE_PROPERTIES
                   2541: };
                   2542: /* }}} */
                   2543: 
                   2544: #ifdef COMPILE_DL_SIMPLEXML
                   2545: ZEND_GET_MODULE(simplexml)
                   2546: #endif
                   2547: 
                   2548: /* the method table */
                   2549: /* each method can have its own parameters and visibility */
                   2550: static const zend_function_entry sxe_functions[] = { /* {{{ */
                   2551:        SXE_ME(__construct,            arginfo_simplexmlelement__construct, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) /* must be called */
                   2552:        SXE_ME(asXML,                  arginfo_simplexmlelement_asxml, ZEND_ACC_PUBLIC)
                   2553:        SXE_MALIAS(saveXML, asXML,         arginfo_simplexmlelement_asxml, ZEND_ACC_PUBLIC)
                   2554:        SXE_ME(xpath,                  arginfo_simplexmlelement_xpath, ZEND_ACC_PUBLIC)
                   2555:        SXE_ME(registerXPathNamespace, arginfo_simplexmlelement_registerxpathnamespace, ZEND_ACC_PUBLIC)
                   2556:        SXE_ME(attributes,             arginfo_simplexmlelement_children, ZEND_ACC_PUBLIC)
                   2557:        SXE_ME(children,               arginfo_simplexmlelement_children, ZEND_ACC_PUBLIC)
                   2558:        SXE_ME(getNamespaces,          arginfo_simplexmlelement_getnamespaces, ZEND_ACC_PUBLIC)
                   2559:        SXE_ME(getDocNamespaces,       arginfo_simplexmlelement_getnamespaces, ZEND_ACC_PUBLIC)
                   2560:        SXE_ME(getName,                arginfo_simplexmlelement__void, ZEND_ACC_PUBLIC)
                   2561:        SXE_ME(addChild,               arginfo_simplexmlelement_addchild, ZEND_ACC_PUBLIC)
                   2562:        SXE_ME(addAttribute,           arginfo_simplexmlelement_addchild, ZEND_ACC_PUBLIC)
                   2563:        SXE_ME(__toString,             arginfo_simplexmlelement__void, ZEND_ACC_PUBLIC)
                   2564:        SXE_ME(count,                  arginfo_simplexmlelement__void, ZEND_ACC_PUBLIC)
                   2565:        PHP_FE_END
                   2566: };
                   2567: /* }}} */
                   2568: 
                   2569: /* {{{ PHP_MINIT_FUNCTION(simplexml)
                   2570:  */
                   2571: PHP_MINIT_FUNCTION(simplexml)
                   2572: {
                   2573:        zend_class_entry sxe;
                   2574: 
                   2575:        INIT_CLASS_ENTRY(sxe, "SimpleXMLElement", sxe_functions);
                   2576:        sxe.create_object = sxe_object_new;
                   2577:        sxe_class_entry = zend_register_internal_class(&sxe TSRMLS_CC);
                   2578:        sxe_class_entry->get_iterator = php_sxe_get_iterator;
                   2579:        sxe_class_entry->iterator_funcs.funcs = &php_sxe_iterator_funcs;
                   2580:        zend_class_implements(sxe_class_entry TSRMLS_CC, 1, zend_ce_traversable);
                   2581:        sxe_object_handlers.get_method = zend_get_std_object_handlers()->get_method;
                   2582:        sxe_object_handlers.get_constructor = zend_get_std_object_handlers()->get_constructor;
                   2583:        sxe_object_handlers.get_class_entry = zend_get_std_object_handlers()->get_class_entry;
                   2584:        sxe_object_handlers.get_class_name = zend_get_std_object_handlers()->get_class_name;
                   2585:        sxe_class_entry->serialize = zend_class_serialize_deny;
                   2586:        sxe_class_entry->unserialize = zend_class_unserialize_deny;
                   2587: 
                   2588:        php_libxml_register_export(sxe_class_entry, simplexml_export_node);
                   2589: 
                   2590:        PHP_MINIT(sxe)(INIT_FUNC_ARGS_PASSTHRU);
                   2591: 
                   2592:        return SUCCESS;
                   2593: }
                   2594: /* }}} */
                   2595: 
                   2596: /* {{{ PHP_MSHUTDOWN_FUNCTION(simplexml)
                   2597:  */
                   2598: PHP_MSHUTDOWN_FUNCTION(simplexml)
                   2599: {
                   2600:        sxe_class_entry = NULL;
                   2601:        return SUCCESS;
                   2602: }
                   2603: /* }}} */
                   2604: 
                   2605: /* {{{ PHP_MINFO_FUNCTION(simplexml)
                   2606:  */
                   2607: PHP_MINFO_FUNCTION(simplexml)
                   2608: {
                   2609:        php_info_print_table_start();
                   2610:        php_info_print_table_header(2, "Simplexml support", "enabled");
                   2611:        php_info_print_table_row(2, "Revision", "$Revision: 321634 $");
                   2612:        php_info_print_table_row(2, "Schema support",
                   2613: #ifdef LIBXML_SCHEMAS_ENABLED
                   2614:                "enabled");
                   2615: #else
                   2616:                "not available");
                   2617: #endif
                   2618:        php_info_print_table_end();
                   2619: }
                   2620: /* }}} */
                   2621: 
                   2622: #endif
                   2623: 
                   2624: /**
                   2625:  * Local Variables:
                   2626:  * c-basic-offset: 4
                   2627:  * tab-width: 4
                   2628:  * indent-tabs-mode: t
                   2629:  * End:
                   2630:  * vim600: fdm=marker
                   2631:  * vim: noet sw=4 ts=4
                   2632:  */

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