From 755bfc1f533ef94cc8c75e1929349366d05d1dd7 Mon Sep 17 00:00:00 2001 From: Toon Verwerft Date: Thu, 15 Oct 2026 20:35:28 +0200 Subject: [PATCH 1/2] Read the xsi namespace once instead of per decoded element Xmlns::xsi() builds a new object on every call. OptionalElementEncoder now resolves it once per iso, and DocumentToLookupArrayReader compares against a class constant. --- src/Encoder/OptionalElementEncoder.php | 6 ++++-- src/Xml/Reader/DocumentToLookupArrayReader.php | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Encoder/OptionalElementEncoder.php b/src/Encoder/OptionalElementEncoder.php index 78078f8..6201aac 100644 --- a/src/Encoder/OptionalElementEncoder.php +++ b/src/Encoder/OptionalElementEncoder.php @@ -42,6 +42,8 @@ public function iso(Context $context): IsoInterface return $elementIso; } + $xsiNamespace = Xmlns::xsi()->value(); + return new Iso( /** * @param T|null $raw @@ -54,7 +56,7 @@ public function iso(Context $context): IsoInterface /** * @return T|null */ - static function (ElementList|Element|string $xml) use ($elementIso, $isList) : mixed { + static function (ElementList|Element|string $xml) use ($elementIso, $isList, $xsiNamespace) : mixed { if ($xml === '') { return null; } @@ -70,7 +72,7 @@ static function (ElementList|Element|string $xml) use ($elementIso, $isList) : m $parsedXml instanceof Element => $parsedXml->element(), default => null }; - if ($documentElement && $documentElement->getAttributeNS(Xmlns::xsi()->value(), 'nil') === 'true') { + if ($documentElement && $documentElement->getAttributeNS($xsiNamespace, 'nil') === 'true') { return null; } diff --git a/src/Xml/Reader/DocumentToLookupArrayReader.php b/src/Xml/Reader/DocumentToLookupArrayReader.php index dd6b7b1..044e18b 100644 --- a/src/Xml/Reader/DocumentToLookupArrayReader.php +++ b/src/Xml/Reader/DocumentToLookupArrayReader.php @@ -7,7 +7,6 @@ use Dom\Node; use Soap\Encoding\Xml\Node\Element; use Soap\Encoding\Xml\Node\ElementList; -use VeeWee\Xml\Xmlns\Xmlns; use function VeeWee\Xml\Dom\Predicate\is_element; /** @@ -16,6 +15,8 @@ */ final class DocumentToLookupArrayReader { + private const XSI_NAMESPACE = 'http://www.w3.org/2001/XMLSchema-instance'; + /** * @return LookupArray */ @@ -52,7 +53,7 @@ public function __invoke(Element $xml): array // It might be possible that the child is a regular textNode. // In that case, we use '_' as the key and the value of the textNode as value. - if (!$nodes && $root->getAttributeNS(Xmlns::xsi()->value(), 'nil') !== 'true') { + if (!$nodes && $root->getAttributeNS(self::XSI_NAMESPACE, 'nil') !== 'true') { $nodes['_'] = $root->textContent ?? ''; } From 353a61c68fcbbc7fe2c390d5035138897a782673 Mon Sep 17 00:00:00 2001 From: Toon Verwerft Date: Thu, 15 Oct 2026 20:36:06 +0200 Subject: [PATCH 2/2] Read element values from the node directly Locator\Node\value() reads substitutedNodeValue and coerces it to a string, which it already is on a Dom\Element. Reading the property skips the function call and the Psl coercion. --- src/Xml/Reader/ElementValueReader.php | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Xml/Reader/ElementValueReader.php b/src/Xml/Reader/ElementValueReader.php index e5865c3..48c2210 100644 --- a/src/Xml/Reader/ElementValueReader.php +++ b/src/Xml/Reader/ElementValueReader.php @@ -7,8 +7,6 @@ use Soap\Encoding\Encoder\Context; use Soap\Encoding\Encoder\XmlEncoder; use VeeWee\Reflecta\Iso\IsoInterface; -use function Psl\Type\string; -use function VeeWee\Xml\Dom\Locator\Node\value as readValue; final class ElementValueReader { @@ -30,9 +28,7 @@ public function __invoke( */ public static function forEncoder(Context $context, XmlEncoder $encoder, Element $element): mixed { - return $encoder->iso($context)->from( - readValue($element, string()) - ); + return $encoder->iso($context)->from($element->substitutedNodeValue); } /** @@ -41,8 +37,6 @@ public static function forEncoder(Context $context, XmlEncoder $encoder, Element */ public static function forIso(IsoInterface $iso, Element $element): mixed { - return $iso->from( - readValue($element, string()) - ); + return $iso->from($element->substitutedNodeValue); } }