It is not possible to use SimpleXML to add a child element without a 
namespace prefix to a parent element that has a namespace element. Instead, the 
child element inherits the namespace prefix of the parent. So this XML 
fragment: 

<ns1:parent> 
<child>abc</child> 
</ns1:parent> 

is impossible to construct with SimpleXML. The SimpleXML extension would add 
the <child> element with the ns1 namespace prefix. This is a problem for me, as 
I have an XML schema that specifies that the child elements must not namespace 
qualified. 

  I looked into the SimpleXML code, and I believe this is actually a bug, as 
the code goes through some effort to distinguish between a set but blank 
namespace, and a set but not blank namespace. I believe the design intent was 
that specifying a blank namespace, would mean that no namespace would be used, 
rather than inheriting the namespace of the parent. 

<?php 
header('Content-Type: text/plain'); 

$r = new SimpleXMLElement('<r />'); 
$c1 = $r->addChild('ns1:child1', NULL, 'urn:myspace1'); 
$c1->addChild('child2'); 
echo $r->asXML(), "\n"; 

$r = new SimpleXMLElement('<r />'); 
$r->addChild('Thing1', 100, ''); 
echo $r->asXML(), "\n"; 


Expected result: 
---------------- 
<?xml version="1.0"?> 
<r><ns1:child1 xmlns:ns1="urn:myspace1"><ns1:child2/></ns1:child1></r> 

<?xml version="1.0"?> 
<r><Thing1>100</Thing1></r> 

Actual result: 
-------------- 
<?xml version="1.0"?> 
<r><ns1:child1 xmlns:ns1="urn:myspace1"><ns1:child2/></ns1:child1></r> 

<?xml version="1.0"?> 
<r><Thing1 xmlns="">100</Thing1></r> 


  The current behavior of specifying a blank namespace, is to add a literal 
blank namespace (xmlns=""), which isn't a useful result. No one would be 
depending on using a blank namepspace to get xmlns="". 

The patch is pretty simple: 

--- simplexml.c.orig 2011-04-26 16:00:31.000000000 -0700 
+++ simplexml.c 2011-04-26 16:00:41.000000000 -0700 
@@ -1619,12 +1619,14 @@ 
localname = xmlStrdup((xmlChar *)qname); 
} 

+ /* Add new child with no namespace */ 
newnode = xmlNewChild(node, NULL, localname, (xmlChar *)value); 

if (nsuri != NULL) { 
+ /* If namespace is not NULL but blank, use no namespace 
+ Use this to prevent inheriting the name space of the parent */ 
if (nsuri_len == 0) { 
newnode->ns = NULL; 
- nsptr = xmlNewNs(newnode, (xmlChar *)nsuri, prefix); 
} else { 
nsptr = xmlSearchNsByHref(node->doc, node, (xmlChar *)nsuri); 
if (nsptr == NULL) { 


(see also http://bugs.php.net/bug.php?id=54354) 


If this patch is accepted, I'll also submit patches to clarify the 
documentation and add some tests. SimpleXML with the above patch, passes the 
existing tests. It is hard to know for sure what the design intent was, as the 
code has few comments, few tests, and the documentation is pretty thin. But I 
believe the above is correct. 


Tom 

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to