susina/xml-to-array

View on GitHub
README.md

Summary

Maintainability
Test Coverage
# Xml to Array Converter

![Test Suite](https://github.com/susina/xml-to-array/actions/workflows/test.yml/badge.svg)
[![Maintainability](https://api.codeclimate.com/v1/badges/df696c7f95bd65d7510c/maintainability)](https://codeclimate.com/github/susina/xml-to-array/maintainability)
[![Test Coverage](https://api.codeclimate.com/v1/badges/df696c7f95bd65d7510c/test_coverage)](https://codeclimate.com/github/susina/xml-to-array/test_coverage)
![GitHub License](https://img.shields.io/github/license/susina/xml-to-array)

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 array
-  `FileConverter`: 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 array
    - `convertAndSave(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 array
    - `convertAndSave(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](https://getcomposer.org):

```bash
composer require susina/xml-to-array
```

The library depends on three php extensions, usually installed by default:

- libxml
- simplexml
- dom

and [Symfony Options Resolver](https://symfony.com/doc/current/components/options_resolver.html) 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
<?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
<?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
<?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
<?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](https://www.php.net/manual/en/function.include.php) PHP statement.

For example:

```php
<?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
<?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
<?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
<?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](#mergeattributes): boolean, default true
- [typesAsString](#typesasstring): boolean, default false
- [preserveFirstTag](#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
<?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
<?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
 *     ]
 * ]
 */
```

### 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
<?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
<?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
<?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
<?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](https://github.com/susina/xml-to-array/issues).

## Contributing

Please, see [CONTRIBUTING.md](CONTRIBUTING.md)

## Licensing

This library is released under [Apache-2.0](LICENSE) license.