]> granicus.if.org Git - php/commitdiff
implement addChild() and addAttribute() methods
authorRob Richards <rrichards@php.net>
Mon, 6 Mar 2006 20:16:03 +0000 (20:16 +0000)
committerRob Richards <rrichards@php.net>
Mon, 6 Mar 2006 20:16:03 +0000 (20:16 +0000)
add test

ext/simplexml/simplexml.c
ext/simplexml/tests/031.phpt [new file with mode: 0644]

index 56cd5ddadc5ec41dfbdddff5dc6c934ba353bd7e..d8708e04b3e36c9ec3774bad1232f1934ad4926f 100644 (file)
@@ -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 (file)
index 0000000..3d6a571
--- /dev/null
@@ -0,0 +1,68 @@
+--TEST--
+SimpleXML: addChild and addAttribute
+--SKIPIF--
+<?php if (!extension_loaded("simplexml")) print "skip"; ?>
+--FILE--
+<?php 
+$xml =<<<EOF
+<root s:att1="b" att1="a" 
+      xmlns:s="urn::test" xmlns:t="urn::test-t">
+   <child1>test</child1>
+   <child1>test 2</child1>
+   <s:child3 />
+</root>
+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
+<?xml version="1.0"?>
+<root xmlns:s="urn::test" xmlns:t="urn::test-t" xmlns:v="urn::test-v" s:att1="b" att1="a" v:att11="xxx" att2="no-ns">
+   <child1>test</child1>
+   <child1>test 2</child1>
+   <s:child3/>
+<s:test1>myval</s:test1><m:test2 xmlns:m="urn::testnew">myval</m:test2><test3 xmlns="urn::testnew">myval</test3><test4>myval</test4><test5>myval</test5></root>
+===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