Commit 8b13fcc13ed for php.net

commit 8b13fcc13edfb49ca32f5a6c8563e7dd71ff5ed2
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date:   Sun Sep 6 10:58:53 2026 -0400

    simplexml: fix addChild() namespace filter on the returned element

    addChild() passed the caller's prefix to node_as_zval_str() with isprefix
    set to 0, so the returned element filtered its children by comparing that
    prefix against the namespace href and matched nothing. Take the prefix from
    the created node and mark it as one, but only when the caller asked for a
    namespace, so a plain addChild() keeps the unfiltered view that its
    attributes and non-namespaced children rely on.

    Closes GH-23599

diff --git a/NEWS b/NEWS
index 935583e8733..31cb928f0bd 100644
--- a/NEWS
+++ b/NEWS
@@ -133,6 +133,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 44fdef5e12d..9e5f293fe78 100644
--- a/ext/simplexml/simplexml.c
+++ b/ext/simplexml/simplexml.c
@@ -1679,6 +1679,7 @@ PHP_METHOD(SimpleXMLElement, addChild)
 	xmlNodePtr      node, newnode;
 	xmlNsPtr        nsptr = NULL;
 	xmlChar        *localname, *prefix = NULL;
+	const xmlChar  *retprefix = NULL;

 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s!s!",
 		&qname, &qname_len, &value, &value_len, &nsuri, &nsuri_len) == FAILURE) {
@@ -1727,7 +1728,11 @@ PHP_METHOD(SimpleXMLElement, addChild)
 		}
 	}

-	node_as_zval_str(sxe, newnode, return_value, SXE_ITER_NONE, localname, prefix, 0);
+	if ((prefix != NULL || nsuri != NULL) && newnode->ns != NULL) {
+		retprefix = newnode->ns->prefix;
+	}
+
+	node_as_zval_str(sxe, newnode, return_value, SXE_ITER_NONE, localname, retprefix, 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 00000000000..b0452f30182
--- /dev/null
+++ b/ext/simplexml/tests/addChild_ns_filter_returned_element.phpt
@@ -0,0 +1,56 @@
+--TEST--
+SimpleXMLElement::addChild() wrong namespace filter on returned element
+--EXTENSIONS--
+simplexml
+--FILE--
+<?php
+$x = new SimpleXMLElement('<r xmlns:a="http://example.com"/>');
+$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('<r xmlns:a="http://example.com"/>');
+$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('<r/>');
+$e = $z->addChild('a:kid');
+$e->addChild('inner', 'z');
+echo trim($z->asXML()), "\n";
+echo (string) $e->inner, "\n";
+var_dump(isset($e->inner));
+
+$q = new SimpleXMLElement('<p:r xmlns:p="http://example.com/p"/>');
+$f = $q->addChild('kid');
+$f->addAttribute('id', '7');
+echo trim($q->asXML()), "\n";
+echo (string) $f['id'], "\n";
+
+$m = new SimpleXMLElement('<r xmlns:a="http://example.com"/>');
+$g = $m->addChild('kid', null, 'http://example.com');
+$g->addAttribute('id', '8');
+echo trim($m->asXML()), "\n";
+var_dump(isset($g['id']));
+?>
+--EXPECT--
+<?xml version="1.0"?>
+<r xmlns:a="http://example.com"><a:kid><a:inner>v</a:inner></a:kid></r>
+v
+bool(true)
+<?xml version="1.0"?>
+<r xmlns:a="http://example.com"><a:kid><a:inner>w</a:inner></a:kid></r>
+w
+<?xml version="1.0"?>
+<r><kid><inner>z</inner></kid></r>
+z
+bool(true)
+<?xml version="1.0"?>
+<p:r xmlns:p="http://example.com/p"><p:kid id="7"/></p:r>
+7
+<?xml version="1.0"?>
+<r xmlns:a="http://example.com"><a:kid id="8"/></r>
+bool(false)