]> granicus.if.org Git - php/commitdiff
fix bug #38949 (Cannot get xmlns value attribute)
authorRob Richards <rrichards@php.net>
Wed, 27 Sep 2006 10:31:24 +0000 (10:31 +0000)
committerRob Richards <rrichards@php.net>
Wed, 27 Sep 2006 10:31:24 +0000 (10:31 +0000)
add test

ext/dom/element.c
ext/dom/tests/bug38949.phpt [new file with mode: 0644]
ext/dom/tests/nsdoc.xml [new file with mode: 0644]

index 0ce275a0b8f8a67c5f7d999465a723133fe1ade6..4ff3d5b025afe321c04bf181bf784de0f50ae09f 100644 (file)
@@ -188,7 +188,7 @@ int dom_element_schema_type_info_read(dom_object *obj, zval **retval TSRMLS_DC)
 
 /* }}} */
 
-static xmlAttrPtr dom_get_dom1_attribute(xmlNodePtr elem, xmlChar *name) {
+static xmlNodePtr dom_get_dom1_attribute(xmlNodePtr elem, xmlChar *name) {
     int len;
     const xmlChar *nqname;
 
@@ -196,15 +196,37 @@ static xmlAttrPtr dom_get_dom1_attribute(xmlNodePtr elem, xmlChar *name) {
        if (nqname != NULL) {
                xmlNsPtr ns;
                xmlChar *prefix = xmlStrndup(name, len);
+               if (prefix && xmlStrEqual(prefix, "xmlns")) {
+                       ns = elem->nsDef;
+                       while (ns) {
+                               if (xmlStrEqual(ns->prefix, nqname)) {
+                                       break;
+                               }
+                               ns = ns->next;
+                       }
+                       xmlFree(prefix);
+                       return (xmlNodePtr)ns;
+               }
                ns = xmlSearchNs(elem->doc, elem, prefix);
                if (prefix != NULL) {
                        xmlFree(prefix);
                }
                if (ns != NULL) {
-                       return xmlHasNsProp(elem, nqname, ns->href);
+                       return (xmlNodePtr)xmlHasNsProp(elem, nqname, ns->href);
+               }
+       } else {
+               if (xmlStrEqual(name, "xmlns")) {
+                       xmlNsPtr nsPtr = elem->nsDef;
+                       while (nsPtr) {
+                               if (nsPtr->prefix == NULL) {
+                                       return (xmlNodePtr)nsPtr;
+                               }
+                               nsPtr = nsPtr->next;
+                       }
+                       return NULL;
                }
        }
-       return xmlHasNsProp(elem, name, NULL);
+       return (xmlNodePtr)xmlHasNsProp(elem, name, NULL);
 }
 
 /* {{{ proto string dom_element_get_attribute(string name);
@@ -217,7 +239,7 @@ PHP_FUNCTION(dom_element_get_attribute)
        xmlNode *nodep;
        char *name, *value = NULL;
        dom_object *intern;
-       xmlAttrPtr attr;
+       xmlNodePtr attr;
        int name_len;
 
        if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &id, dom_element_class_entry, &name, &name_len) == FAILURE) {
@@ -228,9 +250,14 @@ PHP_FUNCTION(dom_element_get_attribute)
 
        attr = dom_get_dom1_attribute(nodep, (xmlChar *)name);
        if (attr) {
-               if (attr->type == XML_ATTRIBUTE_NODE) {
+               switch (attr->type) {
+                       case XML_ATTRIBUTE_NODE:
                        value = xmlNodeListGetString(attr->doc, attr->children, 1);
-               } else {
+                               break;
+                       case XML_NAMESPACE_DECL:
+                               value = xmlStrdup(((xmlNsPtr)attr)->href);
+                               break;
+                       default:
                        value = xmlStrdup(((xmlAttributePtr)attr)->defaultValue);
                }
        }
@@ -253,7 +280,7 @@ PHP_FUNCTION(dom_element_set_attribute)
 {
        zval *id, *rv = NULL;
        xmlNode *nodep;
-       xmlAttr *attr;
+       xmlNodePtr attr = NULL;
        int ret, name_len, value_len;
        dom_object *intern;
        char *name, *value;
@@ -275,16 +302,30 @@ PHP_FUNCTION(dom_element_set_attribute)
        }
 
        attr = dom_get_dom1_attribute(nodep, (xmlChar *)name);
-       if (attr != NULL && attr->type != XML_ATTRIBUTE_DECL) {
+       if (attr != NULL) {
+               switch (attr->type) {
+                       case XML_ATTRIBUTE_NODE:
                node_list_unlink(attr->children TSRMLS_CC);
+                               break;
+                       case XML_NAMESPACE_DECL:
+                               RETURN_FALSE;
+               }
+
+       }
+
+       if (xmlStrEqual((xmlChar *)name, "xmlns")) {
+               if (xmlNewNs(nodep, (xmlChar *)value, NULL)) {
+                       RETURN_TRUE;
+               }
+       } else {
+               attr = (xmlNodePtr)xmlSetProp(nodep, name, value);
        }
-       attr = xmlSetProp(nodep, name, value);
        if (!attr) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such attribute '%s'", name);
                RETURN_FALSE;
        }
 
-       DOM_RET_OBJ(rv, (xmlNodePtr) attr, &ret, intern);
+       DOM_RET_OBJ(rv, attr, &ret, intern);
 
 }
 /* }}} end dom_element_set_attribute */
@@ -297,8 +338,7 @@ Since:
 PHP_FUNCTION(dom_element_remove_attribute)
 {
        zval *id;
-       xmlNode *nodep;
-       xmlAttr *attrp;
+       xmlNodePtr nodep, attrp;
        dom_object *intern;
        int name_len;
        char *name;
@@ -319,14 +359,18 @@ PHP_FUNCTION(dom_element_remove_attribute)
                RETURN_FALSE;
        }
 
-       if (attrp->type != XML_ATTRIBUTE_DECL) {
-               if (php_dom_object_get_data((xmlNodePtr) attrp) == NULL) {
+       switch (attrp->type) {
+               case XML_ATTRIBUTE_NODE:
+                       if (php_dom_object_get_data(attrp) == NULL) {
                        node_list_unlink(attrp->children TSRMLS_CC);
-                       xmlUnlinkNode((xmlNodePtr) attrp);
-                       xmlFreeProp(attrp);
+                               xmlUnlinkNode(attrp);
+                               xmlFreeProp((xmlAttrPtr)attrp);
                } else {
-                       xmlUnlinkNode((xmlNodePtr) attrp);
+                               xmlUnlinkNode(attrp);
                }
+                       break;
+               case XML_NAMESPACE_DECL:
+                       RETURN_FALSE;
        }
 
        RETURN_TRUE;
@@ -341,8 +385,7 @@ Since:
 PHP_FUNCTION(dom_element_get_attribute_node)
 {
        zval *id, *rv = NULL;
-       xmlNode *nodep;
-       xmlAttr  *attrp;
+       xmlNodePtr nodep, attrp;
        int name_len, ret;
        dom_object *intern;
        char *name;
@@ -358,6 +401,25 @@ PHP_FUNCTION(dom_element_get_attribute_node)
                RETURN_FALSE;
        }
 
+       if (attrp->type == XML_NAMESPACE_DECL) {
+               xmlNsPtr curns;
+               xmlNodePtr nsparent;
+
+               nsparent = attrp->_private;
+               curns = xmlNewNs(NULL, attrp->name, NULL);
+               if (attrp->children) {
+                       curns->prefix = xmlStrdup((xmlChar *) attrp->children);
+               }
+               if (attrp->children) {
+                       attrp = xmlNewDocNode(nodep->doc, NULL, (xmlChar *) attrp->children, attrp->name);
+               } else {
+                       attrp = xmlNewDocNode(nodep->doc, NULL, "xmlns", attrp->name);
+               }
+               attrp->type = XML_NAMESPACE_DECL;
+               attrp->parent = nsparent;
+               attrp->ns = curns;
+       }
+
        DOM_RET_OBJ(rv, (xmlNodePtr) attrp, &ret, intern);
 }
 /* }}} end dom_element_get_attribute_node */
@@ -879,7 +941,7 @@ PHP_FUNCTION(dom_element_has_attribute)
        dom_object *intern;
        char *name;
        int name_len;
-       xmlAttrPtr attr;
+       xmlNodePtr attr;
 
        if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &id, dom_element_class_entry, &name, &name_len) == FAILURE) {
                return;
diff --git a/ext/dom/tests/bug38949.phpt b/ext/dom/tests/bug38949.phpt
new file mode 100644 (file)
index 0000000..ba9c8df
--- /dev/null
@@ -0,0 +1,27 @@
+--TEST--
+Bug # 38949: (Cannot get xmlns value attribute)
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+
+$doc = new DOMDocument();
+$doc->load(dirname(__FILE__)."/nsdoc.xml");
+
+$root = $doc->documentElement;
+
+echo $root->getAttribute("xmlns")."\n";
+echo $root->getAttribute("xmlns:ns2")."\n";
+
+$child = $root->firstChild->nextSibling;
+echo $child->getAttribute("xmlns")."\n";
+echo $child->getAttribute("xmlns:ns2")."\n";
+
+echo "DONE\n";
+?>
+--EXPECT--
+http://ns
+http://ns2
+
+
+DONE
diff --git a/ext/dom/tests/nsdoc.xml b/ext/dom/tests/nsdoc.xml
new file mode 100644 (file)
index 0000000..9503fd8
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<root xmlns="http://ns" xmlns:ns2="http://ns2">
+    <ns2:child />
+</root>
\ No newline at end of file