PHPackages                             sbwerewolf/xml-navigator - 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. sbwerewolf/xml-navigator

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

sbwerewolf/xml-navigator
========================

Easy XML to PHP array conversion and fast XML streaming conversion

v9.3.17(1mo ago)212.5k↓31.1%Apache-2.0PHPPHP &gt;=8.4

Since Jan 1Pushed 1y ago1 watchersCompare

[ Source](https://github.com/SbWereWolf/xml-navigator)[ Packagist](https://packagist.org/packages/sbwerewolf/xml-navigator)[ RSS](/packages/sbwerewolf-xml-navigator/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (17)Versions (38)Used By (0)

Xml Navigator
=============

[](#xml-navigator)

The PHP library `Xml Navigator` base on `XMLReader`.

You can assign XML as string or as URI ( or file system path to file).

Navigator can provide XML-document as array or as object.

How to use
----------

[](#how-to-use)

```
$xml =name === 'One';
        }
    );
/* Extract all elements with name `One` */
foreach ($extractor as $element) {
    echo json_encode($element, JSON_PRETTY_PRINT) . PHP_EOL;
}

$reader->close();
```

Output to console will be:

```
{
    "n": "One",
    "v": "text",
    "a": {
        "attr": "val"
    }
}
{
    "n": "One",
    "v": "text",
    "a": {
        "attr": "val"
    }
}
{
    "n": "One",
    "v": "text",
    "a": {
        "attr": "val"
    }
}
```

### XML file processing with no worries of file size

[](#xml-file-processing-with-no-worries-of-file-size)

Access time to first element do not depend on file size.

Let explain this with example.

First generate XML files by script:

```
function generateFile(string $filename, int $limit, string $xml): void
{
    $file = fopen($filename, 'a');
    fwrite($file, '');

    for ($i = 0; $i < $limit; $i++) {
        $content = "$xml$xml$xml$xml$xml$xml$xml$xml$xml$xml";
        fwrite($file, $content);
    }

    fwrite($file, '');
    fclose($file);

    $size = round(filesize($filename) / 1024, 2);
    echo "$filename size is $size Kb" . PHP_EOL;
}

$xml = 'value' . PHP_EOL;
$generation['temp-465b.xml'] = 1;
$generation['temp-429Kb.xml'] = 1_000;
$generation['temp-429Mb.xml'] = 1_000_000;

foreach ($generation as $filename => $size) {
    generateFile($filename, $size, $xml);
}
```

```
temp-465b.xml size is 0.45 Kb
temp-429Kb.xml size is 429.71 Kb
temp-429Mb.xml size is 429687.52 Kb
```

Now, run benchmark by script:

```
/**
 * @param string $filename
 * @return void
 */
function parseFirstElement(string $filename): void
{
    $start = hrtime(true);

    /** @var XMLReader $reader */
    $reader = XMLReader::open($filename);

    $mayRead = true;
    /* scroll to first `SomeElement` */
    while ($mayRead && $reader->name !== 'SomeElement') {
        $mayRead = $reader->read();
    }
    /* Compose array from XML element with name `SomeElement` */
    $result =
        \SbWereWolf\XmlNavigator\Extraction\PrettyPrintComposer
        ::compose($reader);

    $reader->close();

    $finish = hrtime(true);
    $duration = $finish - $start;
    $duration = number_format($duration,);
    echo "First element parsing duration of $filename is $duration ns" .
        PHP_EOL;
}
/* files to metering with benchmark */
$files = [
    'temp-465b.xml',
    'temp-429Kb.xml',
    'temp-429Mb.xml',
];

echo 'Warm up OPcache' . PHP_EOL;
parseFirstElement(current($files));

echo 'Benchmark is starting' . PHP_EOL;
foreach ($files as $filename) {
    parseFirstElement($filename);
}
echo 'Benchmark was finished' . PHP_EOL;
```

```
Warm up OPcache
First element parsing duration of temp-465b.xml is 1,250,700 ns
Benchmark is starting
First element parsing duration of temp-465b.xml is 114,400 ns
First element parsing duration of temp-429Kb.xml is 132,400 ns
First element parsing duration of temp-429Mb.xml is 119,900 ns
Benchmark was finished
```

### XML-document as array

[](#xml-document-as-array)

XmlConverter implements array approach.

XmlConverter can use to convert XML-document to array, example:

```
$xml = toHierarchyOfElements($xml);

$prettyPrint = json_encode($xmlAsArray, JSON_PRETTY_PRINT);
echo 'JSON representation of XML:'
    . PHP_EOL
    . $prettyPrint
    . PHP_EOL;

echo 'Array representation of XML:'
    . PHP_EOL
    . var_export($xmlAsArray, true)
    . PHP_EOL;
```

OUTPUT:

```
JSON representation of XML:
{
    "name": "ElemWithNestedElems",
    "sequence": [
        {
            "name": "ElemWithVal",
            "value": "val"
        },
        {
            "name": "ElemWithAttribs",
            "attributes": {
                "one": "atrib",
                "other": "atrib"
            }
        },
        {
            "name": "ElemWithAll",
            "value": "\n        element value\n    ",
            "attributes": {
                "attribute_name": "attribute-value"
            }
        }
    ]
}
Array representation of XML:
array (
  'name' => 'ElemWithNestedElems',
  'sequence' =>
  array (
    0 =>
    array (
      'name' => 'ElemWithVal',
      'value' => 'val',
    ),
    1 =>
    array (
      'name' => 'ElemWithAttribs',
      'attributes' =>
      array (
        'one' => 'atrib',
        'other' => 'atrib',
      ),
    ),
    2 =>
    array (
      'name' => 'ElemWithAll',
      'value' => '
        element value
    ',
      'attributes' =>
      array (
        'attribute_name' => 'attribute-value',
      ),
    ),
  ),
)
```

### XML-document as object

[](#xml-document-as-object)

XmlElement implements object-oriented approach.

#### Navigator API

[](#navigator-api)

- `name(): string` // Returns the name of XML element
- `hasValue(): bool` // Returns `true` if XML element has value
- `value(): string` // Returns the value of XML element
- `hasAttribute(string $name = ''): bool` // Returns `true` if XML element has attribute with `$name`. If `$name` omitted, than returns `true` if XML element has any attribute
- `get(string $name = null): string` // Get value of attribute with the `$name`, if `$name` is omitted, than returns value of random attribute
- `attributes(): XmlAttribute[]` // Returns all attributes of XML element
- `hasElement(?string $name = null): bool` // Returns `true` if XML element has nested element with `$name`. If `$name` omitted, than returns `true` if XML element has any nested element
- `pull(string $name = ''): Generator` // Pull nested elements as `IXmlElement`, if `$name` is defined, than pull elements only with the `$name`
- `elements(): IXmlElement[]` // Returns all nested elements
- `serialize(): array;` Generates a storable representation (`$data`) of a IXmlElement, use `new XmlElement($data)` to restore `XmlElement` object

### Interact with XML as object

[](#interact-with-xml-as-object)

```
$xml = name() . PHP_EOL;
/* doc */

/* get value of element */
echo "`{$navigator->value()}`" . PHP_EOL;
/* `` */

/* get list of attributes */
$attributes = $navigator->attributes();
foreach ($attributes as $attribute) {
    /** @var \SbWereWolf\XmlNavigator\Navigation\IXmlAttribute $attribute */
    echo "`{$attribute->name()}` `{$attribute->value()}`" . PHP_EOL;
}
/*
`attrib` `a`
`option` `o`
*/

/* get value of attribute */
echo $navigator->get('attrib') . PHP_EOL;
/* a */

/* get list of nested elements */
$elements = $navigator->elements();
foreach ($elements as $element) {
    echo "{$element->name()}" . PHP_EOL;
}
/*
base
valuable
complex
 */

/* get desired nested element */
/** @var \SbWereWolf\XmlNavigator\Navigation\IXmlElement $elem */
$elem = $navigator->pull('valuable')->current();
echo $elem->name() . PHP_EOL;
/* valuable */

/* get all nested elements */
foreach ($navigator->pull() as $pulled) {
    /** @var \SbWereWolf\XmlNavigator\Navigation\IXmlElement $pulled */
    echo $pulled->name() . PHP_EOL;
    /*
    base
    valuable
    complex
    */
}

/* get nested element with given name */
/** @var \SbWereWolf\XmlNavigator\Navigation\IXmlElement $nested */
$nested = $navigator->pull('complex')->current();
/* get names of all elements of nested element */
$elements = $nested->elements();
foreach ($elements as $element) {
    echo "{$element->name()}" . PHP_EOL;
}
/*
a
b
b
b
c
c
c
different
*/

/* pull all elements with name `b` */
foreach ($nested->pull('b') as $b) {
    /** @var \SbWereWolf\XmlNavigator\Navigation\IXmlElement $b */
    echo ' element with name' .
        ' `' . $b->name() .
        '` have attribute `val` with value' .
        ' `' . $b->get('val') . '`' .
        PHP_EOL;
}
/*
 element with name `b` have attribute `val` with value `x`
 element with name `b` have attribute `val` with value `y`
 element with name `b` have attribute `val` with value `z`
*/
```

Advanced using
--------------

[](#advanced-using)

[Unit tests](test/Integration/DebugTest.php) have more examples of using, please investigate them.

Run tests
---------

[](#run-tests)

```
composer test
```

Contacts
--------

[](#contacts)

```
Volkhin Nikolay
e-mail ulfnew@gmail.com
phone +7-902-272-65-35
Telegram @sbwerewolf

```

- [Telegram chat with me](https://t.me/SbWereWolf)
- [WhatsApp chat with me](https://wa.me/79022726535)

###  Health Score

49

—

FairBetter than 95% of packages

Maintenance64

Regular maintenance activity

Popularity28

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity79

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 ~43 days

Recently: every ~94 days

Total

37

Last Release

52d ago

Major Versions

v4.1.5 → v5.1.52023-01-21

v5.2.7 → v6.2.72023-01-29

v6.2.8 → v7.2.82023-01-31

v6.2.9 → v8.2.112025-01-06

v8.3.18 → v9.3.172026-03-28

### Community

Maintainers

![](https://www.gravatar.com/avatar/56415ea6aeceece7248ce372ec911905cab2cd1313ed2bb4ec8cfacdbaa7d08f?d=identicon)[SbWereWolf](/maintainers/SbWereWolf)

---

Top Contributors

[![SbWereWolf](https://avatars.githubusercontent.com/u/16444541?v=4)](https://github.com/SbWereWolf "SbWereWolf (76 commits)")

---

Tags

xmlxml-apixml-parserxml-to-array

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

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

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

###  Alternatives

[masterminds/html5

An HTML5 parser and serializer.

1.8k242.8M229](/packages/masterminds-html5)[sabberworm/php-css-parser

Parser for CSS Files written in PHP

1.8k191.2M65](/packages/sabberworm-php-css-parser)[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)[hassankhan/config

Lightweight configuration file loader that supports PHP, INI, XML, JSON, and YAML files

97513.5M170](/packages/hassankhan-config)[meyfa/php-svg

Read, edit, write, and render SVG files with PHP

54613.9M42](/packages/meyfa-php-svg)

PHPackages © 2026

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