This file keeps the documentation examples in a form that is easy to copy, run, and adapt.
Normalized hierarchy for traversal and wrappers
Streaming extraction for large XML
Streaming extraction with custom hierarchy keys
Traversal wrapper over the normalized hierarchy
Custom key names for one-shot conversion
Readable output for application code and JSON
Readable streaming output
Compose the current node when you already control the XMLReader cursor
Normalized hierarchy for traversal and wrappers.
use SbWereWolf\XmlNavigator\Conversion\FastXmlToArray;
$xml = <<<'XML'
<feed generated_at="2026-03-28T09:00:00Z">
<offer id="206111" available="true">
<name>USB-C Dock</name>
<price currency="USD">129.90</price>
<picture>https://cdn.example.test/1.jpg</picture>
<picture>https://cdn.example.test/2.jpg</picture>
</offer>
</feed>
XML;
$result = FastXmlToArray::convert($xml);
var_export($result);Output:
array (
'n' => 'feed',
'a' =>
array (
'generated_at' => '2026-03-28T09:00:00Z',
),
's' =>
array (
0 =>
array (
'n' => 'offer',
'a' =>
array (
'id' => '206111',
'available' => 'true',
),
's' =>
array (
0 =>
array (
'n' => 'name',
'v' => 'USB-C Dock',
),
1 =>
array (
'n' => 'price',
'v' => '129.90',
'a' =>
array (
'currency' => 'USD',
),
),
2 =>
array (
'n' => 'picture',
'v' => 'https://cdn.example.test/1.jpg',
),
3 =>
array (
'n' => 'picture',
'v' => 'https://cdn.example.test/2.jpg',
),
),
),
),
)Streaming extraction for large XML. This is the recommended workflow when the file is large and only some nodes matter.
use SbWereWolf\XmlNavigator\Parsing\FastXmlParser;
$uri = tempnam(sys_get_temp_dir(), 'xml-extract-kit-');
file_put_contents($uri, <<<'XML'
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<offer id="1">
<name>Keyboard</name>
<price>49.90</price>
</offer>
<service id="s-1">
<name>Warranty</name>
</service>
<offer id="2">
<name>Mouse</name>
<price>19.90</price>
</offer>
</catalog>
XML);
$reader = XMLReader::open($uri);
if ($reader === false) {
throw new RuntimeException('Cannot open XML file.');
}
$offers = FastXmlParser::extractHierarchy(
$reader,
static fn (XMLReader $cursor): bool =>
$cursor->nodeType === XMLReader::ELEMENT
&& $cursor->name === 'offer'
);
foreach ($offers as $offer) {
var_export($offer);
echo PHP_EOL;
}
$reader->close();
unlink($uri);The same hierarchy-first workflow can use your own internal key names.
use SbWereWolf\XmlNavigator\Parsing\FastXmlParser;
$uri = tempnam(sys_get_temp_dir(), 'xml-extract-kit-');
file_put_contents($uri, <<<'XML'
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<offer id="1">
<name>Keyboard</name>
<price>49.90</price>
</offer>
<service id="s-1">
<name>Warranty</name>
</service>
<offer id="2">
<name>Mouse</name>
<price>19.90</price>
</offer>
</catalog>
XML);
$reader = XMLReader::open($uri);
if ($reader === false) {
throw new RuntimeException('Cannot open XML file.');
}
$offers = FastXmlParser::extractHierarchy(
$reader,
static fn (XMLReader $cursor): bool =>
$cursor->nodeType === XMLReader::ELEMENT
&& $cursor->name === 'offer',
'value',
'attributes',
'name',
'children',
);
foreach ($offers as $offer) {
var_export($offer);
echo PHP_EOL;
}
$reader->close();
unlink($uri);Traversal wrapper over the normalized hierarchy.
use SbWereWolf\XmlNavigator\Conversion\FastXmlToArray;
use SbWereWolf\XmlNavigator\Navigation\XmlElement;
$xml = <<<'XML'
<catalog region="eu">
<offer id="1001" available="true">
<name>Keyboard</name>
<tag>office</tag>
<tag>usb</tag>
</offer>
</catalog>
XML;
$root = new XmlElement(FastXmlToArray::convert($xml));
$offer = $root->pull('offer')->current();
echo $root->name() . PHP_EOL; // catalog
echo $root->get('region') . PHP_EOL; // eu
echo ($root->hasElement('offer') ? 'yes' : 'no') . PHP_EOL; // yes
foreach ($offer->attributes() as $attribute) {
echo $attribute->name() . '=' . $attribute->value() . PHP_EOL;
}
$tagValues = array_map(
static fn (XmlElement $tag): string => $tag->value(),
$offer->elements('tag')
);
var_export($tagValues);
$snapshot = $offer->serialize();
$restored = new XmlElement($snapshot);
echo PHP_EOL;
echo $restored->get('id') . PHP_EOL; // 1001Output:
catalog
eu
yes
id=1001
available=true
array (
0 => 'office',
1 => 'usb',
)
1001
Custom key names for one-shot conversion.
use SbWereWolf\XmlNavigator\Conversion\XmlConverter;
$converter = new XmlConverter(
val: 'value',
attr: 'attributes',
name: 'name',
seq: 'children',
);
$hierarchy = $converter->toHierarchyOfElements(
'<price currency="USD">129.90</price>'
);
var_export($hierarchy);Output:
array (
'name' => 'price',
'value' => '129.90',
'attributes' =>
array (
'currency' => 'USD',
),
)Readable output for application code and JSON.
use SbWereWolf\XmlNavigator\Conversion\FastXmlToArray;
$xml = <<<'XML'
<feed generated_at="2026-03-28T09:00:00Z">
<offer id="206111" available="true">
<name>USB-C Dock</name>
<price currency="USD">129.90</price>
<picture>https://cdn.example.test/1.jpg</picture>
<picture>https://cdn.example.test/2.jpg</picture>
</offer>
</feed>
XML;
$result = FastXmlToArray::prettyPrint($xml);
echo json_encode(
$result,
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES
);Output:
{
"feed": {
"@attributes": {
"generated_at": "2026-03-28T09:00:00Z"
},
"offer": {
"@attributes": {
"id": "206111",
"available": "true"
},
"name": "USB-C Dock",
"price": {
"@value": "129.90",
"@attributes": {
"currency": "USD"
}
},
"picture": [
"https://cdn.example.test/1.jpg",
"https://cdn.example.test/2.jpg"
]
}
}
}Readable streaming output when you want JSON-like arrays directly.
use SbWereWolf\XmlNavigator\Parsing\FastXmlParser;
$uri = tempnam(sys_get_temp_dir(), 'xml-extract-kit-');
file_put_contents($uri, <<<'XML'
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<offer id="1">
<name>Keyboard</name>
<price>49.90</price>
</offer>
<service id="s-1">
<name>Warranty</name>
</service>
<offer id="2">
<name>Mouse</name>
<price>19.90</price>
</offer>
</catalog>
XML);
$reader = XMLReader::open($uri);
if ($reader === false) {
throw new RuntimeException('Cannot open XML file.');
}
$offers = FastXmlParser::extractPrettyPrint(
$reader,
static fn (XMLReader $cursor): bool => $cursor->name === 'offer'
);
foreach ($offers as $offer) {
echo json_encode($offer, JSON_PRETTY_PRINT) . PHP_EOL;
}
$reader->close();
unlink($uri);When you already control the XMLReader cursor, the low-level
composers can serialize the current element directly.
use SbWereWolf\XmlNavigator\Extraction\HierarchyComposer;
use SbWereWolf\XmlNavigator\Extraction\PrettyPrintComposer;
$reader = XMLReader::XML(
'<price currency="USD">129.90</price>'
);
$hierarchy = HierarchyComposer::compose($reader);
$reader->close();
$reader = XMLReader::XML(
'<price currency="USD">129.90</price>'
);
$pretty = PrettyPrintComposer::compose($reader);
$reader->close();
var_export($hierarchy);
echo PHP_EOL;
var_export($pretty);