DOMNodeComparator.php 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. <?php declare(strict_types=1);
  2. /*
  3. * This file is part of sebastian/comparator.
  4. *
  5. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace SebastianBergmann\Comparator;
  11. use function assert;
  12. use function mb_strtolower;
  13. use function sprintf;
  14. use DOMDocument;
  15. use DOMNode;
  16. use ValueError;
  17. final class DOMNodeComparator extends ObjectComparator
  18. {
  19. public function accepts(mixed $expected, mixed $actual): bool
  20. {
  21. return $expected instanceof DOMNode && $actual instanceof DOMNode;
  22. }
  23. /**
  24. * @throws ComparisonFailure
  25. */
  26. public function assertEquals(mixed $expected, mixed $actual, float $delta = 0.0, bool $canonicalize = false, bool $ignoreCase = false, array &$processed = []): void
  27. {
  28. assert($expected instanceof DOMNode);
  29. assert($actual instanceof DOMNode);
  30. $expectedAsString = $this->nodeToText($expected, true, $ignoreCase);
  31. $actualAsString = $this->nodeToText($actual, true, $ignoreCase);
  32. if ($expectedAsString !== $actualAsString) {
  33. $type = $expected instanceof DOMDocument ? 'documents' : 'nodes';
  34. throw new ComparisonFailure(
  35. $expected,
  36. $actual,
  37. $expectedAsString,
  38. $actualAsString,
  39. sprintf("Failed asserting that two DOM %s are equal.\n", $type)
  40. );
  41. }
  42. }
  43. /**
  44. * Returns the normalized, whitespace-cleaned, and indented textual
  45. * representation of a DOMNode.
  46. */
  47. private function nodeToText(DOMNode $node, bool $canonicalize, bool $ignoreCase): string
  48. {
  49. if ($canonicalize) {
  50. $document = new DOMDocument;
  51. try {
  52. $c14n = $node->C14N();
  53. assert(!empty($c14n));
  54. @$document->loadXML($c14n);
  55. } catch (ValueError) {
  56. }
  57. $node = $document;
  58. }
  59. $document = $node instanceof DOMDocument ? $node : $node->ownerDocument;
  60. $document->formatOutput = true;
  61. $document->normalizeDocument();
  62. $text = $node instanceof DOMDocument ? $node->saveXML() : $document->saveXML($node);
  63. return $ignoreCase ? mb_strtolower($text, 'UTF-8') : $text;
  64. }
  65. }