cloud-castle / parser-xml
Безопасный разбор и построение XML для PHP 8.1+ с защитой от XXE (отклонение DOCTYPE), fail-loud и двунаправленным маппингом XML↔массив. Единственная зависимость — ext-dom.
Requires
- php: >=8.1
- ext-dom: *
- ext-libxml: *
- psr/http-client: ^1.0
- psr/http-factory: ^1.0
- psr/http-message: ^1.1 || ^2.0
Requires (Dev)
- deptrac/deptrac: ^3.0 || ^4.0
- ergebnis/composer-normalize: ^2.45
- friendsofphp/php-cs-fixer: ^3.75
- icanhazstring/composer-unused: ^0.9
- infection/infection: ^0.29 || ^0.33
- nyholm/psr7: ^1.8
- php-parallel-lint/php-parallel-lint: ^1.4
- phpmd/phpmd: ^2.15
- phpstan/extension-installer: ^1.4
- phpstan/phpstan: ^1.12 || ^2.1
- phpstan/phpstan-deprecation-rules: ^1.2 || ^2.0
- phpstan/phpstan-phpunit: ^1.4 || ^2.0
- phpstan/phpstan-strict-rules: ^1.6 || ^2.0
- phpunit/phpunit: ^10.5 || ^11.5
- psalm/plugin-phpunit: ^0.19 || ^0.20
- rector/rector: ^1.2 || ^2.0
- roave/security-advisories: dev-latest
- sabre/xml: ^4.0
- squizlabs/php_codesniffer: ^3.12 || ^4.0
- symfony/serializer: ^6.4
- vimeo/psalm: ^6.0
- webmozart/assert: ^1.11
This package is auto-updated.
Last update: 2026-07-29 09:12:01 UTC
README
🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano
CloudCastle Parser Xml
Безопасный разбор и построение XML для PHP 8.1+ с защитой от XXE: документы с
DOCTYPE/DTD отклоняются (закрывает XXE и «billion laughs»), внешние сущности не загружаются. Всегда бросает исключение при ошибке, не раскрывая исходных данных. Двунаправленный маппинг XML ↔ массив. Единственная зависимость —ext-dom.
Установка
composer require cloud-castle/parser-xml
Требуется PHP 8.1+ и расширения ext-dom/ext-libxml.
Быстрый старт
<?php
use CloudCastle\Parser\Xml\Xml;
// Разбор XML в массив (XXE-безопасно: DOCTYPE отклоняется).
$data = Xml::toArray('<user id="1"><name>Alex</name></user>');
// ['user' => ['@attributes' => ['id' => '1'], 'name' => 'Alex']]
// Построение XML из массива.
$xml = Xml::fromArray(['name' => 'Alex', 'roles' => ['role' => ['admin', 'user']]], 'user');
// <?xml ...?><user><name>Alex</name><roles><role>admin</role><role>user</role></roles></user>
// Проверка без исключения (в т.ч. отклонение небезопасного DOCTYPE).
if (Xml::isValid($input)) {
// ...
}
// Разбор из локального файла.
$data = Xml::toArrayFromFile('/path/to/catalog.xml');
// Автоопределение источника: локальный путь или URL. Загрузка по URL
// делегируется PSR-18 клиенту (лимит размера, таймауты и защита от SSRF —
// на стороне клиента, например cloud-castle/http-client).
$data = Xml::toArrayFrom('https://example.com/catalog.xml', $httpClient, $requestFactory);
$data = Xml::toArrayFrom('/path/to/catalog.xml'); // тот же метод — локальный файл
// Префиксы пространств имён сохраняются на элементах и атрибутах.
$data = Xml::toArray('<root xmlns:x="urn:x"><x:item x:id="1">v</x:item></root>');
// ['root' => ['x:item' => ['@attributes' => ['x:id' => '1'], '@value' => 'v']]]
Возможности
- Защита от XXE: документы с
DOCTYPE/DTD отклоняются (MalformedXmlException), внешние сущности не загружаются, сеть отключена (LIBXML_NONET). - Fail-loud: любая ошибка разбора или построения — исключение, а не тихий
false/null. - Двунаправленность:
toArray()(XML → массив) иfromArray()(массив → XML) с симметричным маппингом — атрибуты в@attributes, смешанный текст в@value, повторяющиеся элементы в список. - Исключения не содержат исходных данных — только причину сбоя, чтобы персональные и финансовые данные из XML не утекли в логи и трассировки.
- Валидация имён элементов и атрибутов при построении (нет инъекции в теги).
- Загрузка из файла и по URL:
toArrayFromFile()(локальный файл) иtoArrayFrom()(автоопределение локального пути или URL). Сеть не встроена — загрузка по URL идёт через инъектируемый PSR-18 клиент, где и задаются лимит размера, таймауты и защита от SSRF (например,cloud-castle/http-client). - Пространства имён: префиксы элементов и атрибутов (
x:item,x:id) сохраняются при разборе и обратной сериализации. - Единственная runtime-зависимость — расширение
ext-dom(контракты PSR-18/17 нужны только для загрузки по URL).
Сравнение с аналогами
Все таблицы ниже сгенерированы автоматически из честных сравнительных
тестов (benchmarks/compare.php) на ОДИНАКОВОЙ операции для всех аналогов,
PHP 8.1.34, без Xdebug.
1. Функциональность
| Возможность | 🏆 CloudCastle | symfony | sabre | simplexml¹ | dom¹ |
|---|---|---|---|---|---|
| Отклонение DOCTYPE/DTD (защита от XXE) | ✅ | ✅ | ❌ | ❌ | ❌ |
| Fail-loud: исключение при ошибке разбора | ✅ | ✅ | ✅ | ❌ | ❌ |
| Двунаправленность (toArray и fromArray) | ✅ | ✅ | ✅ | ❌ | ✅ |
| Исключения не содержат исходных данных (безопасно для логов с ПД) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Минимум зависимостей (только ext-dom) | ✅ | ❌ | ❌ | ✅ | ✅ |
| Загрузка из файла/URL с контролем размера и SSRF (PSR-18) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Всего | 🏆 6 | 3 | 2 | 1 | 2 |
2. Безопасность и корректность
| Свойство | 🏆 CloudCastle | symfony | sabre | simplexml¹ | dom¹ |
|---|---|---|---|---|---|
| Отклонение DOCTYPE/DTD (XXE и «billion laughs») | ✅ | ❌ | ❌ | ❌ | ❌ |
| Внешние сущности не загружаются | ✅ | ✅ | ✅ | ✅ | ✅ |
| Fail-loud: исключение вместо тихого null/false | ✅ | ✅ | ✅ | ❌ | ❌ |
| Исключения не раскрывают исходные данные (нет утечки ПД) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Валидация имён при построении (нет инъекции в теги) | ✅ | ✅ | ✅ | ❌ | ✅ |
| Всего | 🏆 5 | 3 | 3 | 1 | 2 |
3. Производительность
разбор XML-документа в структуру, 40 000 раз (минимум из 4).
| Решение | Время (мс) | Итог |
|---|---|---|
| simplexml¹ | 367,7 | базовый уровень (не библиотека) |
| dom¹ | 479,4 | базовый уровень (не библиотека) |
| 🏆 CloudCastle | 654,4 | быстрейшее среди библиотек |
| sabre | 768,2 | аналог |
| symfony | 1 091,4 | аналог |
4. Потребление памяти
Пик памяти на 40 000 операций (изолированный процесс, только целевая библиотека).
| Решение | Пиковая память (KB) | Итог |
|---|---|---|
| 🏆 CloudCastle | 7 012 | легчайшее среди библиотек |
| symfony | 7 012 | аналог |
| sabre | 7 012 | аналог |
| simplexml¹ | 7 012 | базовый уровень (не библиотека) |
| dom¹ | 7 012 | базовый уровень (не библиотека) |
¹ Базовый уровень (нативные вызовы/примитивы без полноты решения) показан для контекста и не претендует на победу среди библиотек-аналогов.
Вывод: CloudCastle Parser Xml — самый безопасный среди рассмотренных
XML-инструментов (единственный отклоняет DOCTYPE/DTD «из коробки», закрывая
XXE) и при этом самый быстрый среди библиотек (быстрее symfony/serializer и
sabre/xml; нативные simplexml/DOMDocument взяты за базовый уровень — они
быстрее, но не дают XXE-защиты, исключений и двунаправленного маппинга).
Рекомендуется везде, где XML приходит из недоверенного источника (SOAP, RSS,
загрузки, интеграции) и важна защита от XXE без риска утечки данных в логи.
Разработка
composer install
composer check # линтеры + статический анализ + тесты
composer fix # автоисправления (Rector, PHP CS Fixer, PHPCBF)
composer ci # полный CI-пайплайн локально
Полный список команд с описаниями: composer run-script --list.
Документация
- Репозиторий: https://gitverse.ru/cloud-castle/parser-xml
- История изменений: CHANGELOG.md
- Как внести вклад: CONTRIBUTING.md
- Кодекс поведения: CODE_OF_CONDUCT.md
- Политика безопасности: SECURITY.md
Лицензия
MIT © CloudCastle (alex-4-17@yandex.ru)
🇷🇺 Русский · 🇬🇧 English · 🇩🇪 Deutsch · 🇫🇷 Français · 🇪🇸 Español · 🇮🇹 Italiano