diff options
| author | Rob Richards <rrichards@php.net> | 2006-03-07 15:22:48 +0000 |
|---|---|---|
| committer | Rob Richards <rrichards@php.net> | 2006-03-07 15:22:48 +0000 |
| commit | 8dffbf217d9227bfe310bd71c8dca80559786aad (patch) | |
| tree | 3dd9645b4b054a71e630ddd504ffbf5358547ae4 /ext/simplexml/simplexml.c | |
| parent | 6ce1f439026af8bc431020c0c8a8b15d98d698a0 (diff) | |
| download | php-git-8dffbf217d9227bfe310bd71c8dca80559786aad.tar.gz | |
- Synch with head
Diffstat (limited to 'ext/simplexml/simplexml.c')
| -rw-r--r-- | ext/simplexml/simplexml.c | 249 |
1 files changed, 214 insertions, 35 deletions
diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 9ba1504188..30f42ae5b7 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -632,6 +632,14 @@ static int sxe_prop_dim_exists(zval *object, zval *member, int check_empty, zend xmlAttrPtr attr = NULL; int exists = 0; int test = 0; + zval tmp_zv; + + if (Z_TYPE_P(member) != IS_STRING && Z_TYPE_P(member) != IS_LONG) { + tmp_zv = *member; + zval_copy_ctor(&tmp_zv); + member = &tmp_zv; + convert_to_string(member); + } sxe = php_sxe_fetch_object(object TSRMLS_CC); @@ -661,13 +669,28 @@ static int sxe_prop_dim_exists(zval *object, zval *member, int check_empty, zend if (node) { if (attribs) { - while (attr) { - if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && !xmlStrcmp(attr->name, Z_STRVAL_P(member)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix)) { - exists = 1; - break; + if (Z_TYPE_P(member) == IS_LONG) { + int nodendx = 0; + + while (attr && nodendx <= Z_LVAL_P(member)) { + if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix)) { + if (nodendx == Z_LVAL_P(member)) { + exists = 1; + break; + } + nodendx++; + } + attr = attr->next; } + } else { + while (attr) { + if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && !xmlStrcmp(attr->name, Z_STRVAL_P(member)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix)) { + exists = 1; + break; + } - attr = attr->next; + attr = attr->next; + } } } @@ -679,14 +702,6 @@ static int sxe_prop_dim_exists(zval *object, zval *member, int check_empty, zend node = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node, NULL); } else { - zval tmp_zv; - - if (Z_TYPE_P(member) != IS_STRING) { - tmp_zv = *member; - zval_copy_ctor(&tmp_zv); - member = &tmp_zv; - convert_to_string(member); - } node = node->children; while (node) { xmlNodePtr nnext; @@ -696,9 +711,6 @@ static int sxe_prop_dim_exists(zval *object, zval *member, int check_empty, zend } node = nnext; } - if (member == &tmp_zv) { - zval_dtor(&tmp_zv); - } } if (node) { exists = 1; @@ -706,6 +718,10 @@ static int sxe_prop_dim_exists(zval *object, zval *member, int check_empty, zend } } + if (member == &tmp_zv) { + zval_dtor(&tmp_zv); + } + return exists; } /* }}} */ @@ -733,12 +749,12 @@ static void sxe_prop_dim_delete(zval *object, zval *member, zend_bool elements, php_sxe_object *sxe; xmlNodePtr node; xmlNodePtr nnext; - xmlAttrPtr attr; + xmlAttrPtr attr = NULL; xmlAttrPtr anext; zval tmp_zv; - int test; + int test = 0; - if (Z_TYPE_P(member) != IS_STRING) { + if (Z_TYPE_P(member) != IS_STRING && Z_TYPE_P(member) != IS_LONG) { tmp_zv = *member; zval_copy_ctor(&tmp_zv); member = &tmp_zv; @@ -748,13 +764,24 @@ static void sxe_prop_dim_delete(zval *object, zval *member, zend_bool elements, sxe = php_sxe_fetch_object(object TSRMLS_CC); GET_NODE(sxe, node); + + if (Z_TYPE_P(member) == IS_LONG) { + if (sxe->iter.type != SXE_ITER_ATTRLIST) { + attribs = 0; + elements = 1; + if (sxe->iter.type == SXE_ITER_CHILD) { + node = php_sxe_get_first_node(sxe, node TSRMLS_CC); + } + } + } + if (sxe->iter.type == SXE_ITER_ATTRLIST) { attribs = 1; elements = 0; node = php_sxe_get_first_node(sxe, node TSRMLS_CC); attr = (xmlAttrPtr)node; test = sxe->iter.name != NULL; - } else { + } else if (sxe->iter.type != SXE_ITER_CHILD) { node = php_sxe_get_first_node(sxe, node TSRMLS_CC); attr = node ? node->properties : NULL; test = 0; @@ -762,31 +789,58 @@ static void sxe_prop_dim_delete(zval *object, zval *member, zend_bool elements, if (node) { if (attribs) { - while (attr) { - anext = attr->next; - if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && !xmlStrcmp(attr->name, Z_STRVAL_P(member)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix)) { - xmlUnlinkNode((xmlNodePtr) attr); - php_libxml_node_free_resource((xmlNodePtr) attr TSRMLS_CC); - break; + if (Z_TYPE_P(member) == IS_LONG) { + int nodendx = 0; + + while (attr && nodendx <= Z_LVAL_P(member)) { + if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix)) { + if (nodendx == Z_LVAL_P(member)) { + xmlUnlinkNode((xmlNodePtr) attr); + php_libxml_node_free_resource((xmlNodePtr) attr TSRMLS_CC); + break; + } + nodendx++; + } + attr = attr->next; + } + } else { + while (attr) { + anext = attr->next; + if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && !xmlStrcmp(attr->name, Z_STRVAL_P(member)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix)) { + xmlUnlinkNode((xmlNodePtr) attr); + php_libxml_node_free_resource((xmlNodePtr) attr TSRMLS_CC); + break; + } + attr = anext; } - attr = anext; } } if (elements) { - node = node->children; - while (node) { - nnext = node->next; - - SKIP_TEXT(node); - - if (!xmlStrcmp(node->name, Z_STRVAL_P(member))) { + if (Z_TYPE_P(member) == IS_LONG) { + if (sxe->iter.type == SXE_ITER_CHILD) { + node = php_sxe_get_first_node(sxe, node TSRMLS_CC); + } + node = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node, NULL); + if (node) { xmlUnlinkNode(node); php_libxml_node_free_resource(node TSRMLS_CC); } + } else { + node = node->children; + while (node) { + nnext = node->next; + + SKIP_TEXT(node); + + if (!xmlStrcmp(node->name, Z_STRVAL_P(member))) { + xmlUnlinkNode(node); + php_libxml_node_free_resource(node TSRMLS_CC); + } next_iter: - node = nnext; + node = nnext; + } } } } @@ -1356,6 +1410,129 @@ SXE_METHOD(attributes) } /* }}} */ +/* {{{ proto void SimpleXMLElement::addChild(string qName [, string value [,string ns]]) + Add Element with optional namespace information */ +SXE_METHOD(addChild) +{ + php_sxe_object *sxe; + char *qname, *value = NULL, *nsuri = NULL; + int qname_len, value_len = 0, nsuri_len = 0; + xmlNodePtr node, newnode; + xmlNsPtr nsptr = NULL; + xmlChar *localname, *prefix = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!s!", + &qname, &qname_len, &value, &value_len, &nsuri, &nsuri_len) == FAILURE) { + return; + } + + if (qname_len == 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Element name is required"); + return; + } + + sxe = php_sxe_fetch_object(getThis() TSRMLS_CC); + GET_NODE(sxe, node); + + if (sxe->iter.type == SXE_ITER_ATTRLIST) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot add element to attributes"); + return; + } + + node = php_sxe_get_first_node(sxe, node TSRMLS_CC); + + localname = xmlSplitQName2(qname, &prefix); + if (localname == NULL) { + localname = xmlStrdup(qname); + } + + + newnode = xmlNewChild(node, NULL, localname, value); + + if (nsuri != NULL) { + nsptr = xmlSearchNsByHref(node->doc, node, nsuri); + if (nsptr == NULL) { + nsptr = xmlNewNs(newnode, nsuri, prefix); + } + newnode->ns = nsptr; + } + + _node_as_zval(sxe, newnode, return_value, SXE_ITER_NONE, localname, prefix TSRMLS_CC); + + xmlFree(localname); + if (prefix != NULL) { + xmlFree(prefix); + } +} +/* }}} */ + +/* {{{ proto void SimpleXMLElement::addAttribute(string qName, string value [,string ns]) + Add Attribute with optional namespace information */ +SXE_METHOD(addAttribute) +{ + php_sxe_object *sxe; + char *qname, *value = NULL, *nsuri = NULL; + int qname_len, value_len = 0, nsuri_len = 0; + xmlNodePtr node; + xmlAttrPtr attrp = NULL; + xmlNsPtr nsptr = NULL; + xmlChar *localname, *prefix = NULL; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s!", + &qname, &qname_len, &value, &value_len, &nsuri, &nsuri_len) == FAILURE) { + return; + } + + if (qname_len == 0 || value_len == 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attribute name and value are required"); + return; + } + + sxe = php_sxe_fetch_object(getThis() TSRMLS_CC); + GET_NODE(sxe, node); + + node = php_sxe_get_first_node(sxe, node TSRMLS_CC); + + if (node->type != XML_ELEMENT_NODE) { + node = node->parent; + } + + if (node == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to locate parent Element"); + return; + } + + localname = xmlSplitQName2(qname, &prefix); + if (localname == NULL) { + localname = xmlStrdup(qname); + } + + attrp = xmlHasNsProp(node, localname, nsuri); + if (attrp != NULL && attrp->type != XML_ATTRIBUTE_DECL) { + xmlFree(localname); + if (prefix != NULL) { + xmlFree(prefix); + } + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attribute already exists"); + return; + } + + if (nsuri != NULL) { + nsptr = xmlSearchNsByHref(node->doc, node, nsuri); + if (nsptr == NULL) { + nsptr = xmlNewNs(node, nsuri, prefix); + } + } + + attrp = xmlNewNsProp(node, nsptr, localname, value); + + xmlFree(localname); + if (prefix != NULL) { + xmlFree(prefix); + } +} +/* }}} */ + /* {{{ cast_object() */ static int cast_object(zval *object, int type, char *contents TSRMLS_DC) @@ -2059,6 +2236,8 @@ static zend_function_entry sxe_functions[] = { SXE_ME(getNamespaces, NULL, ZEND_ACC_PUBLIC) SXE_ME(getDocNamespaces, NULL, ZEND_ACC_PUBLIC) SXE_ME(getName, NULL, ZEND_ACC_PUBLIC) + SXE_ME(addChild, NULL, ZEND_ACC_PUBLIC) + SXE_ME(addAttribute, NULL, ZEND_ACC_PUBLIC) {NULL, NULL, NULL} }; |
