From: Rob Richards Date: Mon, 6 Mar 2006 20:16:03 +0000 (+0000) Subject: implement addChild() and addAttribute() methods X-Git-Tag: RELEASE_1_3~521 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=032edbfb9288baf45190ab690b9bacb73445f978;p=php implement addChild() and addAttribute() methods add test --- diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 56cd5ddadc..d8708e04b3 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -751,10 +751,10 @@ 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 && Z_TYPE_P(member) != IS_LONG) { tmp_zv = *member; @@ -1411,6 +1411,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) @@ -2126,6 +2249,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} }; diff --git a/ext/simplexml/tests/031.phpt b/ext/simplexml/tests/031.phpt new file mode 100644 index 0000000000..3d6a57127a --- /dev/null +++ b/ext/simplexml/tests/031.phpt @@ -0,0 +1,68 @@ +--TEST-- +SimpleXML: addChild and addAttribute +--SKIPIF-- + +--FILE-- + + test + test 2 + + +EOF; + +$sxe = simplexml_load_string($xml); + +/* Add new attribute in a new namespace */ +$sxe->addAttribute('v:att11', 'xxx', 'urn::test-v'); + +/* Try to add attribute again -> display warning as method is for new Attr only */ +$sxe->addAttribute('v:att11', 'xxx', 'urn::test-v'); + +/* Add new attribute w/o namespace */ +$sxe->addAttribute('att2', 'no-ns'); + +$d = $sxe->attributes(); +/* Try to add element to attribute -> display warning and do not add */ +$d->addChild('m:test', 'myval', 'urn::test'); + + +/* Test adding elements in various configurations */ +$sxe->addChild('m:test1', 'myval', 'urn::test'); + +/* New namespace test */ +$n = $sxe->addChild('m:test2', 'myval', 'urn::testnew'); + +$sxe->addChild('test3', 'myval', 'urn::testnew'); +$sxe->addChild('test4', 'myval'); + +/* Does not add prefix here although name is valid (but discouraged) - change behavior? */ +$sxe->addChild('s:test5', 'myval'); + +echo $sxe->asXML(); +?> +===DONE=== +--EXPECTF-- +Warning: SimpleXMLElement::addAttribute(): Attribute already exists in %s031.php on line %d + +Warning: SimpleXMLElement::addChild(): Cannot add element to attributes in %s031.php on line %d + + + test + test 2 + +myvalmyvalmyvalmyvalmyval +===DONE=== +--UEXPECTF-- +unicode(3) "Joe" +int(3) +int(0) +unicode(4) "John" +int(3) +int(1) +unicode(4) "Jane" +int(3) +int(0) +===DONE=== \ No newline at end of file