From 10af2d18fb56d51a2468f1b1c7a95762f107edeb Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sun, 6 Sep 2026 10:58:53 -0400 Subject: [PATCH] simplexml: filter addChild() result by the created element's namespace addChild() built the returned SimpleXMLElement with the prefix the caller passed in, not the one the new node ended up in, so a child added through that object was filtered against the wrong namespace and was invisible by property name. Take the prefix from newnode->ns instead. The filter keys on the prefix rather than the href because node_as_zval() installs no filter at all for a prefixless namespace, and switching to href would start filtering the default-namespace case that today has none. Closes GH-23599 --- NEWS | 3 ++ ext/simplexml/simplexml.c | 3 +- .../addChild_ns_filter_returned_element.phpt | 38 +++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 ext/simplexml/tests/addChild_ns_filter_returned_element.phpt diff --git a/NEWS b/NEWS index 1cc265f02e8d..ef5037cc1dc0 100644 --- a/NEWS +++ b/NEWS @@ -114,6 +114,9 @@ PHP NEWS - SimpleXML: . Fixed writing to a dimension of the object returned by attributes() not creating the attribute. (Ilia Alshanetsky) + . Fixed child elements of the element returned by + SimpleXMLElement::addChild() not being accessible by property name when + namespaces are involved. (Ilia Alshanetsky) - Zip: . Fixed bug GH-23276 (ZipArchive subclass storing its own stream cannot be diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 44fdef5e12d7..5a2299dde128 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -1727,7 +1727,8 @@ PHP_METHOD(SimpleXMLElement, addChild) } } - node_as_zval_str(sxe, newnode, return_value, SXE_ITER_NONE, localname, prefix, 0); + node_as_zval_str(sxe, newnode, return_value, SXE_ITER_NONE, localname, + newnode->ns ? newnode->ns->prefix : NULL, 1); xmlFree(localname); if (prefix != NULL) { diff --git a/ext/simplexml/tests/addChild_ns_filter_returned_element.phpt b/ext/simplexml/tests/addChild_ns_filter_returned_element.phpt new file mode 100644 index 000000000000..7627bca7329f --- /dev/null +++ b/ext/simplexml/tests/addChild_ns_filter_returned_element.phpt @@ -0,0 +1,38 @@ +--TEST-- +SimpleXMLElement::addChild() wrong namespace filter on returned element +--EXTENSIONS-- +simplexml +--FILE-- +'); +$c = $x->addChild('a:kid', null, 'http://example.com'); +$c->addChild('inner', 'v'); +echo trim($x->asXML()), "\n"; +echo (string) $c->inner, "\n"; +var_dump(isset($c->inner)); + +$y = new SimpleXMLElement(''); +$d = $y->addChild('kid', null, 'http://example.com'); +$d->addChild('inner', 'w'); +echo trim($y->asXML()), "\n"; +echo (string) $d->inner, "\n"; + +$z = new SimpleXMLElement(''); +$e = $z->addChild('kid'); +$e->addChild('inner', 'z'); +echo trim($z->asXML()), "\n"; +echo (string) $e->inner, "\n"; +var_dump(isset($e->inner)); +?> +--EXPECT-- + +v +v +bool(true) + +w +w + +z +z +bool(true)