susina / xml-to-array
Simple PHP library to convert an XML string into an array
Requires
- php: >=8.2
- ext-dom: *
- ext-libxml: *
- ext-simplexml: *
- symfony/options-resolver: ^7.1
Requires (Dev)
- mikey179/vfsstream: ^1.6
- pestphp/pest: ^2.35
- psalm/phar: ^5
- susina/coding-standard: ^2
This package is auto-updated.
Last update: 2024-10-15 15:56:24 UTC
README
Xml to Array is a simple library to convert XML into PHP array.
The library consists in one namespace Susina\XmlToArray
and two classes:
Converter
: to convert an XML string into PHP arrayFileConverter
: to convert an XML file
Both classes expose the same public api:
- Susina\XmlToArray\Converter
convert(string $xmlToParse): array
to convert an xml string into an arrayconvertAndSave(string $xmlToParse, string $filename): void
to convert an xml string to an array and save it into a regular php file.
- Susina\XmlToArray\FileConverter
convert(string $xmlFile): array
to read an xml file and convert it into an arrayconvertAndSave(string $xmlFile, string $filename): void
to read an xml file and, convert it into an array and save it into a regular php file.
Installation
Install the library via composer:
composer require susina/xml-to-array
The library depends on three php extensions, usually installed by default:
- libxml
- simplexml
- dom
and Symfony Options Resolver component, that'll be install by composer.
Usage
Use the convert
method to parse an XML string. Let's get a look at the following example:
<?php declare(strict_types=1); use Susina\XmlToArray\Converter; $xmlString = " <?xml version='1.0' standalone='yes'?> <movies> <movie> <title>Star Wars</title> <starred>True</starred> <percentage>32.5</percentage> </movie> <movie> <title>The Lord Of The Rings</title> <starred>false</starred> <percentage>30.7</percentage> </movie> </movies> "; $converter = new Converter(); $array = $converter->convert($xmlString); /* * $array now contains the following array: * * [ * "movie" => [ * 0 => [ * "title" => "Star Wars", * "starred" => true, * "percentage" => 32.5 * ], * 1 => [ * "title" => "The Lord Of The Rings", * "starred" => false, * "percentage" => 30.7 * ] * ] * ] */
Alternatively, you can use the static instantiator:
<?php declare(strict_types=1); ..... $array = Converter::create()->convert($xmlString);
If you want to read and convert an xml file, you can play with FileConverter
class:
<?php declare(strict_types=1); use Susina\XmlToArray\FileConverter; $converter = new FileConverter(); $array = $converter->convert('/my_dir/my_file.xml');
and by using the static constructor:
<?php declare(strict_types=1); $array = FileConverter::create()->convert('/my_dir/my_file.xml');
You can save the converted array into a regular formatted php file, that you can import in some other script by include PHP statement.
For example:
<?php declare(strict_types=1); use Susina\XmlToArray\Converter; $xmlString = " <?xml version='1.0' standalone='yes'?> <movies> <movie> <title>Star Wars</title> <starred>True</starred> <percentage>32.5</percentage> </movie> <movie> <title>The Lord Of The Rings</title> <starred>false</starred> <percentage>30.7</percentage> </movie> </movies> "; $converter = new Converter(); $converter->convertAndSave($xmlString, 'array_file.php');
The content of array_file.php
is the following:
<?php declare(strict_types=1); /* * This file is auto-generated by susina/xml-to-array library. */ return array ( 'movie' => array ( 0 => array ( 'title' => 'Star Wars', 'starred' => true, 'percentage' => 32.5, ), 1 => array ( 'title' => 'The Lord Of The Rings', 'starred' => false, 'percentage' => 30.7, ), ), );
You can load your array via include
statement:
<?php declare(strict_types=1); //Some instructions $array = include('array_file.php');
Also FileConverter
class has its convertAndSave
method, which has the same behavior, but it accepts the name of the xml file to convert as first parameter:
<?php declare(strict_types=1); ........... FileConverter::create()->convertAndSave($xmlFileName, 'array_file.php');
Configuration
You can configure the converters by passing an associative array to the constructor, where the keys are the name of the option. The available options are the following:
- mergeAttributes: boolean, default true
- idAsKey: boolean, default true
- typesAsString: boolean, default false
- preserveFirstTag: boolean, default false
mergeAttributes
Default: true
When this option is set to true, the attributes of a tag are merged into the tag it self, otherwise they're saved into a @attribute
array, i.e.:
<?php declare(strict_types=1); $xmlString = ' <?xml version="1.0" encoding="utf-8"?> <config> <logger name="defaultLogger"> <type>stream</type> <path>/var/log/default.log</path> <level>300</level> </logger> </config> '; //mergeAttributes is true by default $array = Converter::create()->convert($xmlString); /* * $array now contains the following array: * * [ * "logger" => [ * "name" => "defaultLogger", * "type" => "stream", * "path" => "/var/log/default.log" * "level" => 300 * ] * ] */
In the previous example, you can see that the name attribute is "merged" into logger array.
When this option is set to false, a @attribute array is created:
<?php declare(strict_types=1); $xmlString = ' <?xml version="1.0" encoding="utf-8"?> <config> <logger name="defaultLogger"> <type>stream</type> <path>/var/log/default.log</path> <level>300</level> </logger> </config> '; $array = Converter::create(['mergeAttributes' => false])->convert($xmlString); /* * $array now contains the following array: * * [ * "logger" => [ * "@attributes" => [ * "name" => "defaultLogger" * ], * "type" => "stream", * "path" => "/var/log/default.log" * "level" => 300 * ] * ] */
idAsKey
Default: true
When this option is set to true, the value of an id attribute or tag is considered as the key of an associative array, i.e.:
<?php declare(strict_types=1); $xmlString = " <?xml version='1.0' standalone='yes'?> <movies> <movie> <title>Star Wars</title> <starred>True</starred> <actor id=\"actorH\" name=\"Harrison Ford\" /> <actor id=\"actorM\" name=\"Mark Hamill\" /> <actor> <id>actorC</id> <name>Carrie Fisher</name> </actor> </movie> </movies>"; //idAsKey is true by default $array = Converter::create()->convert($xmlString); /* * $array now contains the following array: * * 'movie' => [ * 0 => [ * 'title' => 'Star Wars', * 'starred' => true, * 'actorH' => ['name' => 'Harrison Ford'], * 'actorM' => ['name' => 'Mark Hamill'], * 'actorC' => ['name' => 'Carrie Fisher'] * ] * ] */
Otherwise, if you set this option to false no magic happens:
<?php declare(strict_types=1); $xmlString = " <?xml version='1.0' standalone='yes'?> <movies> <movie> <title>Star Wars</title> <starred>True</starred> <actor id=\"actorH\" name=\"Harrison Ford\" /> <actor id=\"actorM\" name=\"Mark Hamill\" /> <actor> <id>actorC</id> <name>Carrie Fisher</name> </actor> </movie> </movies>"; $converter = new Converter(['idAsKey' => false]); $array = $converter->convert($xmlString); /* * $array now contains the following array: * * 'movie' => [ * 0 => [ * 'title' => 'Star Wars', * 'starred' => true, * 'actor' => [ * 0 => [ * 'id' => 'actorH', * 'name' => 'Harrison Ford' * ], * 1 => [ * 'id' => 'actorM', * 'name' => 'Mark Hamill' * ], * 2 => [ * 'id' => 'actorC', * 'name' => 'Carrie Fisher' * ] * ] * ] * ] */
typesAsString
Default: false
The normal behavior of this library is to preserve all PHP types (boolean, numeric, null etc.). If typesAsString option is set to true all the values are considered strings:
<?php declare(strict_types=1); use Susina\XmlToArray\Converter; $xmlString = " <?xml version='1.0' standalone='yes'?> <movies> <movie> <title>Star Wars</title> <starred>True</starred> <percentage>32.5</percentage> <views>589623</views> </movie> </movies> "; // typesAsString is false by default $array = Converter::create()->convert($xmlString); /* * $array now contains the following array: * * [ * "movie" => [ * 0 => [ * "title" => "Star Wars", * "starred" => true, * "percentage" => 32.5, * "views" => 589623 * ], * ] * ] */
In the previous example, if you set the property to true, all values are strings:
<?php declare(strict_types=1); use Susina\XmlToArray\Converter; $xmlString = ....... $array = Converter::create(['typesAsString' => true])->convert($xmlString); /* * $array now contains the following array: * * [ * "movie" => [ * 0 => [ * "title" => "Star Wars", * "starred" => 'True', * "percentage" => '32.5' * "views" => '589623' * ], * ] * ] */
preserveFirstTag
Default: false
If your xml document starts with a single tag, containing all the others, the first tag is not considered as part of the resulting array:
<?php declare(strict_types=1); use Susina\XmlToArray\Converter; $xmlString = " <?xml version='1.0' standalone='yes'?> <database> <movie> <title>Star Wars</title> </movie> <movie> <title>The Lord Of The Rings</title> </movie> <movie> <title>Spider-Man</title> </movie> </database> "; // preserveFirstTag is false by default $converter = new Converter(); $array = $converter->convert($xmlString); /* * $array now contains the following array: * * [ * "movie" => [ * 0 => [ * "title" => "Star Wars", * ], * 1 => [ * "title" => "The Lord Of The Rings", * ], * 2 => [ * "title" "Spider-Man" * ] * ] * ] */
If you want to keep this tag as the first key of your array, set this option to true:
<?php declare(strict_types=1); use Susina\XmlToArray\Converter; $xmlString = ............. $converter = new Converter(['preserveFirstTag' => true]); $array = $converter->convert($xmlString); /* * $array now contains the following array: * * [ * "database => [ * "movie" => [ * 0 => [ * "title" => "Star Wars", * ], * 1 => [ * "title" => "The Lord Of The Rings", * ], * 2 => [ * "title" "Spider-Man" * ] * ] * ] * ] */
Issues
If you find a bug or any other issue, please report it on Github.
Contributing
Please, see CONTRIBUTING.md
Licensing
This library is released under Apache-2.0 license.