From: Marcus Boerger Date: Wed, 29 Oct 2003 12:06:52 +0000 (+0000) Subject: Add simplexml array handlers that allow to explicitly work with attributes. X-Git-Tag: RELEASE_2_0_0RC1~21 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6b57bb16752e475166a43ce0a38b96b7241b1236;p=php Add simplexml array handlers that allow to explicitly work with attributes. --- diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 7fc199d41d..b2ae27872b 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -13,6 +13,7 @@ | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Sterling Hughes | + | Marcus Boerger | +----------------------------------------------------------------------+ */ @@ -115,10 +116,10 @@ match_ns(php_sxe_object *sxe, xmlNodePtr node, xmlChar *name) } /* }}} */ -/* {{{ sxe_property_read() +/* {{{ sxe_prop_dim_read() */ static zval * -sxe_property_read(zval *object, zval *member, zend_bool silent TSRMLS_DC) +sxe_prop_dim_read(zval *object, zval *member, zend_bool elements, zend_bool attribs, zend_bool silent TSRMLS_DC) { zval *return_value; zval *value = NULL; @@ -139,54 +140,58 @@ sxe_property_read(zval *object, zval *member, zend_bool silent TSRMLS_DC) GET_NODE(sxe, node); if (node) { - attr = node->properties; - while (attr) { - if (!xmlStrcmp(attr->name, name)) { - APPEND_PREV_ELEMENT(counter, value); - - MAKE_STD_ZVAL(value); - contents = xmlNodeListGetString((xmlDocPtr) sxe->document->ptr, attr->children, 1); - ZVAL_STRING(value, contents, 1); - if (contents) { - xmlFree(contents); + if (attribs) { + attr = node->properties; + while (attr) { + if (!xmlStrcmp(attr->name, name)) { + APPEND_PREV_ELEMENT(counter, value); + + MAKE_STD_ZVAL(value); + contents = xmlNodeListGetString((xmlDocPtr) sxe->document->ptr, attr->children, 1); + ZVAL_STRING(value, contents, 1); + if (contents) { + xmlFree(contents); + } + APPEND_CUR_ELEMENT(counter, value); } - APPEND_CUR_ELEMENT(counter, value); + attr = attr->next; } - attr = attr->next; } - if (!sxe->node) { - php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, node, NULL TSRMLS_CC); - } - node = node->children; - - while (node) { - SKIP_TEXT(node); - - do if (node->ns) { - if (node->parent->ns) { - if (!xmlStrcmp(node->ns->href, node->parent->ns->href)) { - break; - } - } + if (elements) { + if (!sxe->node) { + php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, node, NULL TSRMLS_CC); + } + node = node->children; + + while (node) { + SKIP_TEXT(node); - if (match_ns(sxe, node, name)) { + do if (node->ns) { + if (node->parent->ns) { + if (!xmlStrcmp(node->ns->href, node->parent->ns->href)) { + break; + } + } + + if (match_ns(sxe, node, name)) { + MAKE_STD_ZVAL(value); + _node_as_zval(sxe, node->parent, value TSRMLS_CC); + APPEND_CUR_ELEMENT(counter, value); + goto next_iter; + } + } while (0); + + if (!xmlStrcmp(node->name, name)) { + APPEND_PREV_ELEMENT(counter, value); MAKE_STD_ZVAL(value); - _node_as_zval(sxe, node->parent, value TSRMLS_CC); + _node_as_zval(sxe, node, value TSRMLS_CC); APPEND_CUR_ELEMENT(counter, value); - goto next_iter; } - } while (0); - - if (!xmlStrcmp(node->name, name)) { - APPEND_PREV_ELEMENT(counter, value); - MAKE_STD_ZVAL(value); - _node_as_zval(sxe, node, value TSRMLS_CC); - APPEND_CUR_ELEMENT(counter, value); - } - + next_iter: - node = node->next; + node = node->next; + } } /* Only one value found */ @@ -205,6 +210,24 @@ next_iter: } /* }}} */ +/* {{{ sxe_property_read() + */ +static zval * +sxe_property_read(zval *object, zval *member, zend_bool silent TSRMLS_DC) +{ + return sxe_prop_dim_read(object, member, 1, 1, silent TSRMLS_CC); +} +/* }}} */ + +/* {{{ sxe_dimension_read() + */ +static zval *sxe_dimension_read(zval *object, zval *offset TSRMLS_DC) +{ + convert_to_string_ex(&offset); + return sxe_prop_dim_read(object, offset, 0, 1, 0 TSRMLS_CC); +} +/* }}} */ + /* {{{ change_node_zval() */ static void @@ -228,15 +251,14 @@ change_node_zval(xmlNodePtr node, zval *value) /* {{{ sxe_property_write() */ -static void -sxe_property_write(zval *object, zval *member, zval *value TSRMLS_DC) +static void sxe_prop_dim_write(zval *object, zval *member, zval *value, zend_bool elements, zend_bool attribs TSRMLS_DC) { php_sxe_object *sxe; char *name; xmlNodePtr node; xmlNodePtr newnode = NULL; xmlNodePtr tempnode; - xmlAttrPtr attr; + xmlAttrPtr attr = NULL; int counter = 0; int is_attr = 0; @@ -246,27 +268,31 @@ sxe_property_write(zval *object, zval *member, zval *value TSRMLS_DC) GET_NODE(sxe, node); if (node) { - attr = node->properties; - while (attr) { - if (!xmlStrcmp(attr->name, name)) { - is_attr = 1; - ++counter; - break; + if (attribs) { + attr = node->properties; + while (attr) { + if (!xmlStrcmp(attr->name, name)) { + is_attr = 1; + ++counter; + break; + } + + attr = attr->next; } - - attr = attr->next; } - node = node->children; - while (node) { - SKIP_TEXT(node); - if (!xmlStrcmp(node->name, name)) { - newnode = node; - ++counter; - } - + if (elements) { + node = node->children; + while (node) { + SKIP_TEXT(node); + if (!xmlStrcmp(node->name, name)) { + newnode = node; + ++counter; + } + next_iter: - node = node->next; + node = node->next; + } } if (counter == 1) { @@ -280,11 +306,30 @@ next_iter: change_node_zval(newnode, value); } else if (counter > 1) { php_error(E_WARNING, "Cannot assign to an array of nodes (duplicate subnodes or attr detected)\n"); + } else { + php_error(E_WARNING, "Cannot create new atrribute\n"); } } } /* }}} */ +/* {{{ sxe_property_write() + */ +static void sxe_property_write(zval *object, zval *member, zval *value TSRMLS_DC) +{ + sxe_prop_dim_write(object, member, value, 1, 1 TSRMLS_CC); +} +/* }}} */ + +/* {{{ sxe_dimension_write() + */ +static void sxe_dimension_write(zval *object, zval *offset, zval *value TSRMLS_DC) +{ + convert_to_string_ex(&offset); + sxe_prop_dim_write(object, offset, value, 0, 1 TSRMLS_CC); +} +/* }}} */ + /* {{{ sxe_property_exists() */ static int @@ -327,10 +372,9 @@ next_iter: } /* }}} */ -/* {{{ sxe_property_delete() +/* {{{ sxe_prop_dim_delete() */ -static void -sxe_property_delete(zval *object, zval *member TSRMLS_DC) +static void sxe_prop_dim_delete(zval *object, zval *member, zend_bool elements, zend_bool attribs TSRMLS_DC) { php_sxe_object *sxe; xmlNodePtr node; @@ -343,34 +387,56 @@ sxe_property_delete(zval *object, zval *member TSRMLS_DC) GET_NODE(sxe, node); if (node) { - attr = node->properties; - while (attr) { - anext = attr->next; - if (!xmlStrcmp(attr->name, Z_STRVAL_P(member))) { - xmlUnlinkNode((xmlNodePtr) attr); - xmlFreeProp(attr); + if (attribs) { + attr = node->properties; + while (attr) { + anext = attr->next; + if (!xmlStrcmp(attr->name, Z_STRVAL_P(member))) { + xmlUnlinkNode((xmlNodePtr) attr); + xmlFreeProp(attr); + } + attr = anext; } - attr = anext; } - - node = node->children; - while (node) { - nnext = node->next; - SKIP_TEXT(node); - - if (!xmlStrcmp(node->name, Z_STRVAL_P(member))) { - xmlUnlinkNode(node); - xmlFreeNode(node); - } + if (elements) { + node = node->children; + while (node) { + nnext = node->next; + + SKIP_TEXT(node); + + if (!xmlStrcmp(node->name, Z_STRVAL_P(member))) { + xmlUnlinkNode(node); + xmlFreeNode(node); + } next_iter: - node = nnext; + node = nnext; + } } } } /* }}} */ +/* {{{ sxe_property_delete() + */ +static void +sxe_property_delete(zval *object, zval *member TSRMLS_DC) +{ + sxe_prop_dim_delete(object, member, 1, 1 TSRMLS_CC); +} +/* }}} */ + +/* {{{ sxe_dimension_unset() + */ +static void sxe_dimension_delete(zval *object, zval *offset TSRMLS_DC) +{ + convert_to_string_ex(&offset); + sxe_prop_dim_delete(object, offset, 1, 1 TSRMLS_CC); +} +/* }}} */ + /* {{{ _get_base_node_value() */ static void @@ -867,14 +933,14 @@ static zend_object_handlers sxe_object_handlers = { ZEND_OBJECTS_STORE_HANDLERS, sxe_property_read, sxe_property_write, - NULL, - NULL, + sxe_dimension_read, + sxe_dimension_write, NULL, sxe_object_get, sxe_object_set, sxe_property_exists, sxe_property_delete, - NULL, + sxe_dimension_delete, sxe_properties_get, sxe_method_get, sxe_call_method, @@ -1096,13 +1162,12 @@ static void php_sxe_iterator_current(php_sxe_iterator *iterator TSRMLS_DC) _get_base_node_value(iterator->sxe, iterator->node, &iterator->data TSRMLS_CC); - iterator->node->name = (char *) iterator->node->name; if (!iterator->node->name) { iterator->name = "CDATA"; iterator->namelen = sizeof("CDATA"); } else { iterator->namelen = xmlStrlen(iterator->node->name)+1; - iterator->name = iterator->node->name; + iterator->name = (char *) iterator->node->name; } break; next_iter: diff --git a/ext/simplexml/tests/007.phpt b/ext/simplexml/tests/007.phpt index 0d1f14e4af..023d7d3c62 100755 --- a/ext/simplexml/tests/007.phpt +++ b/ext/simplexml/tests/007.phpt @@ -7,13 +7,36 @@ SimpleXML and attributes $sxe = simplexml_load_file(dirname(__FILE__).'/sxe.xml'); +echo "===Property===\n"; var_dump($sxe->id); var_dump($sxe->elem1->attr1); - -echo "===Done===\n"; +echo "===Array===\n"; +var_dump($sxe['id']); +var_dump($sxe->elem1['attr1']); +echo "===Set===\n"; +$sxe['id'] = "Changed1"; +var_dump($sxe['id']); +$sxe->elem1['attr1'] = 12; +var_dump($sxe->elem1['attr1']); +echo "===Unset===\n"; +unset($sxe['id']); +var_dump($sxe['id']); +unset($sxe->elem1['attr1']); +var_dump($sxe->elem1['attr1']); ?> +===Done=== --EXPECT-- +===Property=== +string(5) "elem1" +string(5) "first" +===Array=== string(5) "elem1" string(5) "first" +===Set=== +string(8) "Changed1" +string(2) "12" +===Unset=== +NULL +NULL ===Done===