Skip to content

Commit b4cdeef

Browse files
committed
Allow configuration of libxml options for decoding XML
1 parent f0cd4b6 commit b4cdeef

File tree

6 files changed

+65
-10
lines changed

6 files changed

+65
-10
lines changed

src/Encoder/Method/ResponseEncoder.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ private function decode(MethodContext $context, string $xml): array
101101
// The SoapResponse only contains the payload of the response (with no headers).
102102
// It can be parsed directly as XML.
103103
invariant($xml !== '', 'Expected a non-empty response payload. Received an empty HTTP response');
104-
$parts = (new OperationReader($meta))($xml)->elements();
104+
$parts = (new OperationReader($meta))($xml, $context->registry->decoderLibXmlOptions())->elements();
105105

106106
return map(
107107
$parts,

src/EncoderRegistry.php

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,12 @@ final class EncoderRegistry
2626
/**
2727
* @param MutableMap<string, XmlEncoder<mixed, string>> $simpleTypeMap
2828
* @param MutableMap<string, XmlEncoder<mixed, string>> $complextTypeMap
29+
* @param int $decoderLibXmlOptions - bitmask of LIBXML_* constants https://www.php.net/manual/en/libxml.constants.php
2930
*/
3031
private function __construct(
3132
private MutableMap $simpleTypeMap,
32-
private MutableMap $complextTypeMap
33+
private MutableMap $complextTypeMap,
34+
private int $decoderLibXmlOptions = 0,
3335
) {
3436
}
3537

@@ -341,4 +343,22 @@ public function detectEncoderForContext(Context $context): XmlEncoder
341343
{
342344
return EncoderDetector::default()($context);
343345
}
346+
347+
/**
348+
* @param int $libXmlOptions - bitmask of LIBXML_* constants https://www.php.net/manual/en/libxml.constants.php
349+
*/
350+
public function setDecoderLibXmlOptions(int $libXmlOptions): self
351+
{
352+
$this->decoderLibXmlOptions = $libXmlOptions;
353+
354+
return $this;
355+
}
356+
357+
/**
358+
* @return int - bitmask of LIBXML_* constants https://www.php.net/manual/en/libxml.constants.php
359+
*/
360+
public function decoderLibXmlOptions(): int
361+
{
362+
return $this->decoderLibXmlOptions;
363+
}
344364
}

src/Xml/Reader/OperationReader.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@ public function __construct(
2222
* Reads all operation response message parts:
2323
*
2424
* @param non-empty-string $xml
25+
* @param int $libXmlOptions - bitmask of LIBXML_* constants https://www.php.net/manual/en/libxml.constants.php
2526
*/
26-
public function __invoke(string $xml): ElementList
27+
public function __invoke(string $xml, int $libXmlOptions = 0): ElementList
2728
{
2829
$bindingStyle = BindingStyle::tryFrom($this->meta->bindingStyle()->unwrapOr(BindingStyle::DOCUMENT->value));
2930

3031
// The Response can contain out of multiple response parts.
3132
// Therefore, it is being wrapped by a central root element:
32-
$body = (new SoapEnvelopeReader())($xml);
33+
$body = (new SoapEnvelopeReader())($xml, $libXmlOptions);
3334
$bodyElement = $body->element();
3435

3536
$elements = match($bindingStyle) {

src/Xml/Reader/SoapEnvelopeReader.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,18 @@
88
use Soap\Xml\Locator\SoapBodyLocator;
99
use VeeWee\Xml\Dom\Document;
1010
use function VeeWee\Xml\Dom\Assert\assert_element;
11+
use function VeeWee\Xml\Dom\Configurator\loader;
12+
use function VeeWee\Xml\Dom\Loader\xml_string_loader;
1113

1214
final class SoapEnvelopeReader
1315
{
1416
/**
1517
* @param non-empty-string $xml
18+
* @param int $libXmlOptions - bitmask of LIBXML_* constants https://www.php.net/manual/en/libxml.constants.php
1619
*/
17-
public function __invoke(string $xml): Element
20+
public function __invoke(string $xml, int $libXmlOptions = 0): Element
1821
{
19-
$envelope = Document::fromXmlString($xml);
22+
$envelope = Document::configure(loader(xml_string_loader($xml, $libXmlOptions)));
2023

2124
// Make sure it does not contain a fault response before parsing the body parts.
2225
(new SoapFaultGuard())($envelope);

tests/Unit/Xml/Reader/OperationReaderTest.php

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717
final class OperationReaderTest extends TestCase
1818
{
1919
#[DataProvider('provideEnvelopeCases')]
20-
public function test_it_can_read_a_soap_envelope(MethodMeta $meta, string $envelope, array $expected): void
20+
public function test_it_can_read_a_soap_envelope(MethodMeta $meta, string $envelope, array $expected, int $libXmlOptions = 0): void
2121
{
2222
$reader = new OperationReader($meta);
23-
$actual = $reader($envelope);
23+
$actual = $reader($envelope, $libXmlOptions);
2424

2525
static::assertSame(
2626
$expected,
@@ -91,5 +91,19 @@ public static function provideEnvelopeCases()
9191
'<c>c</c>',
9292
],
9393
];
94+
95+
yield 'xml-options' => [
96+
$methodMeta->withBindingStyle(BindingStyle::DOCUMENT->value),
97+
<<<EOXML
98+
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
99+
<soap:Body xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
100+
<Request><![CDATA[content]]></Request>
101+
</soap:Body>
102+
</soap:Envelope>
103+
EOXML,
104+
['<Request>content</Request>'],
105+
\LIBXML_NOCDATA
106+
];
107+
94108
}
95109
}

tests/Unit/Xml/Reader/SoapEnvelopeReaderTest.php

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@
1919
final class SoapEnvelopeReaderTest extends TestCase
2020
{
2121
#[DataProvider('provideEnvelopeCases')]
22-
public function test_it_can_read_a_soap_envelope(SoapVersion $version, string $envelope, string $expected): void
22+
public function test_it_can_read_a_soap_envelope(SoapVersion $version, string $envelope, string $expected, int $libXmlOptions = 0): void
2323
{
2424
$reader = new SoapEnvelopeReader();
25-
$actual = $reader($envelope);
25+
$actual = $reader($envelope, $libXmlOptions);
2626

2727
static::assertXmlStringEqualsXmlString($expected, $actual->value());
2828
}
@@ -83,5 +83,22 @@ public static function provideEnvelopeCases()
8383
</soap:Body>
8484
EOXML,
8585
];
86+
87+
yield 'xml-options' => [
88+
SoapVersion::SOAP_12,
89+
<<<EOXML
90+
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap12/">
91+
<soap:Body xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap12/">
92+
<Request><![CDATA[content]]></Request>
93+
</soap:Body>
94+
</soap:Envelope>
95+
EOXML,
96+
<<<EOXML
97+
<soap:Body xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap12/">
98+
<Request>content</Request>
99+
</soap:Body>
100+
EOXML,
101+
\LIBXML_NOCDATA
102+
];
86103
}
87104
}

0 commit comments

Comments
 (0)