codeception/lib-xml
XML utilities for Codeception tests. Provides helpers to load, parse, query, and assert XML/HTML content in a clean, test-friendly API. Useful for validating SOAP responses, RSS feeds, and markup fragments with expressive assertions and convenient matchers.
Start by installing the package via Composer — it's lightweight and optional, ideal for adding to test suites only:
composer require --dev codeception/lib-xml
No configuration is required out of the box. The main entry points are the XML facade or direct instantiation of Codeception\Lib\Xml\Loader and Codeception\Lib\Xml\Comparator.
Your first use case: comparing two XML strings in a Codeception test:
// Inside a Cept or Cest
use Codeception\Lib\Xml\Comparator;
$I->assertXmlStringEqualsXmlString(
'<root><item id="1">Apple</item></root>',
'<root> <item id="1">Apple</item> </root>' // Formatting differs, but semantically equal
);
Or use XML::load() to parse XML from string/file and apply assertions:
use Codeception\Lib\Xml\XML;
$xml = XML::load('<users><user id="1">Alice</user></users>');
$I->assertEquals('Alice', $xml->xpath('//user')[0]->textContent);
Check tests/_support/AcceptanceTester.php or your helper class for examples; default usage pattern is test-first, minimal setup.
Fixture-based validation: Load expected XML fixtures (e.g., API responses, configuration exports), compare against generated output using Comparator::normalize() and Comparator::equals().
$expected = XML::loadFile('tests/fixtures/user-export.xml');
$actual = XML::load($generatedXml);
$I->assertTrue(Comparator::equals($expected, $actual));
Assertion chaining for readability: Wrap XML::load() in helper methods to avoid repetition:
class ApiHelper extends \Codeception\Module {
public function seeXmlContainsUser($xml, $userId, $name) {
$dom = XML::load($xml);
$nodes = $dom->xpath("//user[@id='$userId']");
$this->assertNotEmpty($nodes, "User $userId not found");
$this->assertEquals($name, trim($nodes[0]->textContent));
}
}
Integration with Codeception modules: Use in REST, Doctrine2, or custom modules to assert XML payloads (e.g., SOAP, legacy APIs). For example, after an API call:
$I->sendGET('/users/1');
$xml = XML::load($I->getResponse());
$I->assertEquals('Active', XML::getNodeValue($xml, '//user/status'));
Normalizing before comparison: When XML comes from external systems with inconsistent whitespace or attribute ordering, use Comparator::normalize():
$normalized = Comparator::normalize($rawXml);
No namespace handling by default: xpath() calls assume no namespaces unless explicitly handled. If your XML uses namespaces (e.g., xmlns="http://example.com"), register them in DOM or use namespace-aware XPath:
$dom = XML::load($xmlWithNs);
$xpath = new DOMXPath($dom);
$xpath->registerNamespace('ns', 'http://example.com');
$node = $xpath->evaluate('//ns:user')[0];
SimpleXML vs DOM: XML::load() returns DOMDocument for reliability in XPath and mutation. If you prefer SimpleXML, use XML::loadSimpleXml(), but note limitations (e.g., no attributes in DOMDocument::saveXML() by default — use LIBXML_NO_EMPTY_TAGS).
Normalization quirks: Comparator::normalize() strips insignificant whitespace but preserves structure. If you have mixed content (e.g., <p>Text <b>bold</b> more</p>), normalization may still differ across parsers. Add LIBXML_NO_EMPTY_TAGS in custom loader if needed.
Whitespace and CDATA: Comparator::normalize() treats <![CDATA[...]]> as plain text; ensure this aligns with your semantic expectations (e.g., HTML in XML may be misnormalized).
Testing edge cases: When comparing large XML trees, use Comparator::diff() (if exposed) or manually inspect via DOMDocument::saveXML() in test output. Enable --debug in Codeception to see full diff.
Extendability: The library avoids over-abstraction — for advanced XML work (XSLT, validation), stick with built-in DOMDocument/XMLReader, using lib-xml only for test scaffolding. You can safely cast its returned DOMDocument back to core classes.
How can I help you explore Laravel packages today?