PHPackages                             inspirum/xml - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Parsing &amp; Serialization](/categories/parsing)
4. /
5. inspirum/xml

ActiveLibrary[Parsing &amp; Serialization](/categories/parsing)

inspirum/xml
============

Simple XML writer and memory efficient XML reader with powerful xml-to-array cast

v3.1.2(1y ago)1012.5k↓50%1MITPHPPHP ^8.2CI passing

Since Jan 13Pushed 1y ago1 watchersCompare

[ Source](https://github.com/inspirum/xml-php)[ Packagist](https://packagist.org/packages/inspirum/xml)[ Docs](https://github.com/inspirum/xml-php)[ RSS](/packages/inspirum-xml/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (6)Versions (12)Used By (1)

XML reader / writer
===================

[](#xml-reader--writer)

[![Latest Stable Version](https://camo.githubusercontent.com/52d06f27c3e9043336a80e6dfb56f464260c5fefa1d0c8b5c77887669a1762e6/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f696e73706972756d2f786d6c2e7376673f7374796c653d666c61742d73717561726526636f6c6f72423d626c7565)](https://packagist.org/packages/inspirum/xml)[![Build Status](https://camo.githubusercontent.com/7c62c900295e66d798b45bf738c7b019e7d278ab77b67c938985f9cca7b04f69/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f696e73706972756d2f786d6c2d7068702f6d61737465722e796d6c3f6272616e63683d6d6173746572267374796c653d666c61742d737175617265)](https://github.com/inspirum/xml-php/actions)[![Coverage Status](https://camo.githubusercontent.com/20f11264dd5e19d26a0cc4b31f2e2030d091a13238ab058f39f9d65d0befa1f9/68747470733a2f2f696d672e736869656c64732e696f2f7363727574696e697a65722f636f7665726167652f672f696e73706972756d2f786d6c2d7068702f6d61737465722e7376673f7374796c653d666c61742d737175617265)](https://scrutinizer-ci.com/g/inspirum/xml-php/code-structure)[![Quality Score](https://camo.githubusercontent.com/67521b7c5c2a0c6119a16a8a2cfe05d4335e1e55bffc1357b09978f7818ae43c/68747470733a2f2f696d672e736869656c64732e696f2f7363727574696e697a65722f672f696e73706972756d2f786d6c2d7068702e7376673f7374796c653d666c61742d737175617265)](https://scrutinizer-ci.com/g/inspirum/xml-php)[![PHPStan](https://camo.githubusercontent.com/4b1330d67416a001f59bf39d60499aec28a71f8ee2d3185777cae563373ef201/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7374796c652d6c6576656c25323031302d627269676874677265656e2e7376673f7374796c653d666c61742d737175617265266c6162656c3d7068707374616e)](https://github.com/phpstan/phpstan)[![Total Downloads](https://camo.githubusercontent.com/613f613af0cddd6b608657e19b13934998ecebce63ee5d5a33d78c1546713bb6/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f696e73706972756d2f786d6c2e7376673f7374796c653d666c61742d73717561726526636f6c6f72423d626c7565)](https://packagist.org/packages/inspirum/xml/stats)[![Software License](https://camo.githubusercontent.com/781e34ea231bd505cb9d5b9788806ef838a52ec42589f65ad0f8275ef3ee28a5/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f696e73706972756d2f786d6c2d7068702e7376673f7374796c653d666c61742d73717561726526636f6c6f72423d626c7565)](./LICENSE.md)

Simple XML fluent writer and memory efficient XML reader.

- Fluent builder build over [Document Object Model](https://www.php.net/manual/en/book.dom.php) with automatic CDATA escaping, namespace support and other features
- Utilises [XMLReader](https://www.php.net/manual/en/book.xmlreader.php) and [Generator](https://www.php.net/manual/en/language.generators.overview.php) for memory efficient reading of large files
- The entire code is covered by unit tests

Usage example
-------------

[](#usage-example)

*All the code snippets shown here are modified for clarity, so they may not be executable.*

#### XML Writer

[](#xml-writer)

Writing Google Merchant XML feed file

```
/** @var Inspirum\XML\Builder\DocumentFactory $factory */

$locale       = 'cs';
$currencyCode = 'CZK';

$xml = $factory->create();
$rss = $xml->addElement('rss', [
    'version' => '2.0',
    'xmlns:g' => 'http://base.google.com/ns/1.0',
]);

$channel = $rss->addElement('channel');
$channel->addTextElement('title', 'Google Merchant');
$channel->addTextElement('link', 'https://www.example.com');
$channel->addTextElement('description', 'Google Merchant products feed');
$channel->addTextElement('language', $locale);
$channel->addTextElement('lastBuildDate', (new \DateTime())->format('D, d M y H:i:s O'));
$channel->addTextElement('generator', 'Eshop');

foreach ($products as $product) {
    $item = $xml->createElement('item');
    $item->addTextElement('g:id', $product->getId());
    $item->addTextElement('title', $product->getName($locale));
    $item->addTextElement('link', $product->getUrl());
    $item->addTextElement('description', \strip_tags($product->getDescription($locale)));
    $item->addTextElement('g:image_link', $product->getImageUrl());
    foreach ($product->getAdditionalImageUrls() as $imageUrl) {
        $item->addTextElement('g:additional_image_link', $imageUrl);
    }
    $price = $product->getPrice($currencyCode);
    $item->addTextElement('g:price', $price->getOriginalPriceWithVat() . ' ' . $currencyCode);
    if ($price->inDiscount()) {
        $item->addTextElement('g:sale_price', $price->getPriceWithVat() . ' ' . $currencyCode);
    }
    if ($product->hasEAN()) {
        $item->addTextElement('g:gtin', $product->getEAN());
    } else {
        $item->addTextElement('g:identifier_exists', 'no');
    }
    $item->addTextElement('g:condition', 'new');
    if ($product->inStock()) {
        $item->addTextElement('g:availability', 'in stock');
    } elseif ($product->hasPreorder()) {
        $item->addTextElement('g:availability', 'preorder');
        $item->addTextElement('g:availability_date', $product->getDeliveryDate());
    } else {
        $item->addTextElement('g:availability', 'out of stock');
    }
    $item->addTextElement('g:brand', $product->getBrand());
    $item->addTextElement('g:size', $product->getParameterValue('size', $locale));
    $item->addTextElement('g:color', $product->getParameterValue('color', $locale));
    $item->addTextElement('g:material', $product->getParameterValue('material', $locale));
    if ($product->isVariant()) {
        $item->addTextElement('g:item_group_id', $product->getParentProductId()());
    }
    if ($product->getCustomAttribute('google_category') !== null) {
        $item->addTextElement('g:google_product_category', $product->getCustomAttribute('google_category'));
    } elseif ($product->getMainCategory() !== null) {
        $item->addTextElement('g:product_type', $product->getMainCategory()->getFullname($locale));
    }
}

$xml->validate('/google_feed.xsd');

$xml->save('/output/feeds/google.xml');

/**
var_dump($xml->toString(true));

    Google Merchant
    https://www.example.com
    Google Merchant products feed
    cs
    Sat, 14 Nov 20 08:00:00 +0200
    Eshop

      0001

      http://localhost/produkt/sample-product-1-a-b
      Lorem ipsum dolor sit amet, consectetur adipisicing elit.
      http://localhost/images/no_image.webp
      19.99 CZK
      7220110003812
      new
      in stock
      Co.

    ...

*/
```

#### XML Reader

[](#xml-reader)

Reading data from Google Merchant XML feed

```
/** @var \Inspirum\XML\Reader\ReaderFactory $factory */

$reader = $factory->create('/output/feeds/google.xml');

$title = $reader->nextNode('title')->getTextContent();

/**
var_dump($title);
'Google Merchant'
*/

$lastBuildDate = $reader->nextNode('lastBuildDate')->getTextContent();

/**
var_dump($lastBuildDate);
'2020-08-25T13:53:38+00:00'
*/

$price = 0.0;
foreach ($reader->iterateNode('item') as $item) {
    $data = $item->toArray();
    $price += (float) $data['g:price'];
}

/**
var_dump($price);
501.98
*/
```

Splitting data to XML fragments by xpath (with valid namespaces)

```
/** @var \Inspirum\XML\Reader\ReaderFactory $factory */
$reader = $factory->create('/output/feeds/google.xml');

foreach ($reader->iterateNode('/rss/channel/item', true) as $item) {
    $data = $item->toString();
    $id = ($item->xpath('/item/g:id')[0] ?? null)?->getTextContent()
    // ...
}
```

System requirements
-------------------

[](#system-requirements)

- [PHP 8.2+](http://php.net/releases/8_2_0.php)
- [ext-dom](http://php.net/dom)
- [ext-json](http://php.net/json)
- [ext-xmlreader](http://php.net/xmlreader)

Installation
------------

[](#installation)

Run composer require command

```
$ composer require inspirum/xml
```

or add requirement to your `composer.json`

```
"inspirum/xml": "^3.0"
```

Usage
-----

[](#usage)

Available framework integrations:

- [Symfony](https://github.com/inspirum/xml-php-symfony)

But you can also use it without any framework implementation:

```
use Inspirum\XML\Builder\DefaultDocumentFactory;
use Inspirum\XML\Builder\DefaultDOMDocumentFactory;
use Inspirum\XML\Reader\DefaultReaderFactory;
use Inspirum\XML\Reader\DefaultXMLReaderFactory;

$documentFactory = new DefaultDocumentFactory(new DefaultDOMDocumentFactory());
$document = $documentFactory->create();
// ...

$readerFactory = new DefaultReaderFactory(new DefaultXMLReaderFactory(), $documentFactory);
$reader = $readerFactory->create('/path/to/file.xml');
// ...
```

#### XML Writer

[](#xml-writer-1)

Optionally you can specify XML version and encoding (defaults to UTF-8).

```
use Inspirum\XML\Builder\DefaultDocumentFactory;

$factory = new DefaultDocumentFactory()

$xml = $factory->create('1.0', 'WINDOWS-1250');
/**

*/

$xml = $factory->create();
/**

*/
```

Nesting elements

```
$a = $xml->addElement('a');
$a->addTextElement('b', 'BB', ['id' => 1]);
$b = $a->addElement('b', ['id' => 2]);
$b->addTextElement('c', 'CC');

/**

  BB

    CC

*/
```

Used as fluent builder

```
$xml->addElement('root')->addElement('a')->addElement('b', ['id' => 1])->addTextElement('c', 'CC');

/**

      CC

*/
```

Automatic CDATA escaping

```
$a = $xml->addElement('a');
$a->addTextElement('b', 'me & you');
$a->addTextElement('b', '30&nbsp;km');

/**

*/
```

Forced CDATA escaping

```
$a = $xml->addElement('a');
$a->addTextElement('b', 'me');
$a->addTextElement('b', 'you', forcedEscape: true);

/**

  me

*/
```

Adding XML fragments

```
$a = $xml->addElement('a');
$a->addXMLData('CC0');
$a->addTextElement('b', '1');

/**

    CC

  0
  1

*/
```

To use automatic namespace usage you only have to set `xmlns:{prefix}` attribute on (usually) root element.

Elements (or/and attributes) use given prefix as `{prefix}:{localName}`, and it will be created with [`createElementNS`](https://php.net/manual/domdocument.createelementns.php) or [`createAttributeNS`](https://php.net/manual/domdocument.createattributens.php) method.

```
$root = $xml->addElement('g:root', ['xmlns:g' =>'stock.xsd', 'g:version' => '2.0']);
$items = $root->addElement('g:items');
$items->addTextElement('g:item', 1);
$items->addTextElement('g:item', 2);
$items->addTextElement('g:item', 3);

/**

     1
     2
     3

*/
```

Namespace support its necessary for XML validation with XSD schema

```
try {
    $xml->validate('/sample.xsd');
    // valid XML
} catch (\DOMException $exception) {
    // invalid XML
}
```

#### XML Reader

[](#xml-reader-1)

> /sample.xml

```

    2020-08-25T13:53:38+00:00

            1
            Test 1

            2
            Test 2

            3
            Test 3

```

Reading XML files into [**Node**](./src/Builder/Node.php) instances

Read next node with given name

```
$node = $reader->nextNode('g:updated');

$node->getTextContent();
/**
'2020-08-25T13:53:38+00:00'
*/

$node->toString();
/**
2020-08-25T13:53:38+00:00
*/
```

Powerful cast to array method

```
$data = $reader->nextNode('g:items')->toArray();

/**
var_dump($ids);
[
  'g:item' => [
    0 => [
      'g:id'        => '1'
      'g:name'      => 'Test 1'
      '@attributes' => [
        'active' => 'true'
        'price'  => '99.9'
      ]
    ]
    1 => [
      'g:id'        => '3'
      'g:name'      => 'Test 3'
      '@attributes' => [
        'active' => 'false'
        'price'  => '0'
      ]
    ]
  ]
  'item' => [
    0 => [
      'g:id'        => '2'
      'g:name'      => 'Test 2'
      '@attributes' => [
        'active' => 'true'
        'price'  => '19.9'
      ]
    ]
  ]
]
*/
```

Optional config supported for `toArray` method

```
use Inspirum\XML\Builder\DefaultDocumentFactory;
use Inspirum\XML\Formatter\FullResponseConfig;

$factory = new DefaultDocumentFactory()

$config = new FullResponseConfig(
    attributesName: '@attr',
    valueName: '@val',
    autoCast: true,
);

$data = $factory->createForFile('/sample.xml')->toArray($config);

/**
var_dump($ids);
[
  '@attr'  => []
  '@val'   => null
  '@nodes' => [
    'g:feed' => [
      0 => [
        '@attr'  => [
          'g:version' => 2.0
        ]
        '@val'   => null
        '@nodes' => [
          'g:updated' => [
            0 => [
              '@attr'  => []
              '@val'   => '2020-08-25T13:53:38+00:00'
              '@nodes' => []
            ]
          ]
          'title' => [
            0 => [
              '@attr'  => []
              '@val'   => null
              '@nodes' => []
            ]
          ]
          'g:items' => [
            0 => [
              '@attr'  => []
              '@val'   => null
              '@nodes' => [
                'g:item' => [
                  0 => [
                    '@attr'  => [
                      'active' => true
                      'price'  => 99.9
                    ]
                    '@val'   => null
                    '@nodes' => [
                      'g:id' => [
                        0 => [
                          '@attr'  => []
                          '@val'   => 1
                          '@nodes' => []
                        ]
                      ]
                      'g:name' => [
                        0 => [
                          '@attr'  => []
                          '@val'   => 'Test 1'
                          '@nodes' => []
                        ]
                      ]
                    ]
                  ]
                  1 => [
                    '@attr'  => [
                      'active' => false
                      'price'  => 0
                    ]
                    '@val'   => null
                    '@nodes' =>
                    [
                      'g:id' => [
                        0 => [
                          '@attr'  => []
                          '@val'   => 3
                          '@nodes' => []
                        ]
                      ]
                      'g:name' => [
                        0 => [
                          '@attr'  => []
                          '@val'   => 'Test 3'
                          '@nodes' => []
                        ]
                      ]
                    ]
                  ]
                ]
                'item' => [
                  0 => [
                    '@attr'  => [
                      'active' => true
                      'price'  => 19.9
                    ]
                    '@val'   => null
                    '@nodes' => [
                      'g:id' => [
                        0 => [
                          '@attr'  => []
                          '@val'   => 2
                          '@nodes' => []
                        ]
                      ]
                      'g:name' => [
                        0 => [
                          '@attr'  => []
                          '@val'   => 'Test 2'
                          '@nodes' => []
                        ]
                      ]
                    ]
                  ]
                ]
              ]
            ]
          ]
        ]
      ]
    ]
  ]
]
*/
```

Iterate all nodes with given name

```
$ids = [];
foreach ($reader->iterateNode('item') as $item) {
    $ids[] = $item->toArray()['id'];
}

/**
var_dump($ids);
[
  0 => '1'
  1 => '3'
]
*/
```

Splitting data to XML fragments (with valid namespaces)

```
$items = [];
foreach ($reader->iterateNode('g:item', true) as $item) {
    $items[] = $item->toString();
}

/**
var_dump($items);
[
  0 => '1Test 1'
  1 => '3Test 3'
]
*/
```

### All available methods

[](#all-available-methods)

- [`Inspirum\XML\Builder\DocumentFactory`](./src/Builder/DocumentFactory.php)
- [`Inspirum\XML\Builder\Document`](./src/Builder/Document.php)
- [`Inspirum\XML\Builder\Node`](./src/Builder/Node.php)
- [`Inspirum\XML\Reader\ReaderFactory`](./src/Reader/ReaderFactory.php)
- [`Inspirum\XML\Reader\Reader`](./src/Reader/Reader.php)

Testing
-------

[](#testing)

To run unit tests, run:

```
$ composer test:test
```

To show coverage, run:

```
$ composer test:coverage
```

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](./docs/CONTRIBUTING.md) and [CODE\_OF\_CONDUCT](./docs/CODE_OF_CONDUCT.md) for details.

Security
--------

[](#security)

If you discover any security related issues, please email  instead of using the issue tracker.

Credits
-------

[](#credits)

- [Tomáš Novotný](https://github.com/tomas-novotny)
- [All Contributors](https://github.com/inspirum/xml-php/contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](./LICENSE.md) for more information.

###  Health Score

44

—

FairBetter than 92% of packages

Maintenance47

Moderate activity, may be stable

Popularity30

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity72

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~153 days

Total

11

Last Release

420d ago

Major Versions

v1.0.1 → v2.0.02022-05-21

v2.3.1 → v3.0.02023-10-17

PHP version history (4 changes)v1.0.0PHP &gt;=7.1

v2.0.0PHP &gt;=8.1

v2.2.0PHP ^8.1

v3.0.0PHP ^8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/e2804b72261a28767b27deae892144e2a2c6a09a0d71d149631606346731d52d?d=identicon)[tomas-novotny](/maintainers/tomas-novotny)

---

Top Contributors

[![tomas-novotny](https://avatars.githubusercontent.com/u/36948723?v=4)](https://github.com/tomas-novotny "tomas-novotny (89 commits)")

---

Tags

domdocumentphpxmlxml-parserxml-parsingxml-to-arrayxml-to-jsonxmlreaderxmlwriterxmlxml-to-arrayxml-parserxml-builderxml writerXml Readerxml-splitter

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/inspirum-xml/health.svg)

```
[![Health](https://phpackages.com/badges/inspirum-xml/health.svg)](https://phpackages.com/packages/inspirum-xml)
```

###  Alternatives

[masterminds/html5

An HTML5 parser and serializer.

1.8k242.8M229](/packages/masterminds-html5)[jms/serializer

Library for (de-)serializing data of any complexity; supports XML, and JSON.

2.3k135.8M851](/packages/jms-serializer)[jms/metadata

Class/method/property metadata management in PHP

1.8k152.8M88](/packages/jms-metadata)[jms/serializer-bundle

Allows you to easily serialize, and deserialize data of any complexity

1.8k89.3M627](/packages/jms-serializer-bundle)[veewee/xml

XML without worries

1835.9M29](/packages/veewee-xml)[sabre/xml

sabre/xml is an XML library that you may not hate.

52832.2M131](/packages/sabre-xml)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
