diff --git a/source/FluidXml/FluidInsertionHandler.php b/source/FluidXml/FluidInsertionHandler.php
index f47fd46..23b5b21 100644
--- a/source/FluidXml/FluidInsertionHandler.php
+++ b/source/FluidXml/FluidInsertionHandler.php
@@ -269,9 +269,15 @@ protected function insertStringSimple($parent, $k, $v, $fn): array
// The user has passed an element name and an element value:
// [ 'element' => 'Element content' ]
- $el = $this->createElement($k, $v);
+ $el = $this->createElement($k);
$el = $fn($parent, $el);
+ // createTextNode escapes XML special characters (&, <, >, etc.)
+ // DOMElement's constructor does not, so we avoid passing value there.
+ if ($v !== null && $v !== '') {
+ $el->appendChild($this->dom->createTextNode((string) $v));
+ }
+
return [ $el ];
}
diff --git a/specs/FluidXml.php b/specs/FluidXml.php
index 6cac1ef..7dd9bca 100644
--- a/specs/FluidXml.php
+++ b/specs/FluidXml.php
@@ -1181,6 +1181,32 @@ function addchild($parent, $i)
assert_equal_xml($xml, $expected);
});
+ it('should escape XML special characters in text content using the argument syntax', function () {
+ $xml = new FluidXml();
+ $xml->addChild('child1', 'a & b')
+ ->addChild('parent', true)
+ ->addChild('child2', 'a < b');
+
+ $expected = "\n"
+ . " a & b\n"
+ . " \n"
+ . " a < b\n"
+ . " \n"
+ . "";
+ assert_equal_xml($xml, $expected);
+ });
+
+ it('should escape XML special characters in text content using the array syntax', function () {
+ $xml = new FluidXml();
+ $xml->addChild(['child1' => 'Hello & World', 'child2' => 'Tom & Jerry']);
+
+ $expected = "\n"
+ . " Hello & World\n"
+ . " Tom & Jerry\n"
+ . "";
+ assert_equal_xml($xml, $expected);
+ });
+
it('should add many children with and without a value', function () {
$xml = new FluidXml();
$xml->addChild(['child1', 'child2', 'child3' => 'value3', 'child4' => 'value4'])