# array-to-xml: Spatie's one-method array to XML converter

> array-to-xml turns a PHP array into an XML document through a single static call, with conventions for root names, key sanitising, attributes, comments, CDATA and the XML declaration. It is a small, opinionated package whose whole API is one method, and the opinion is mostly about underscore-prefixed keys and a positional argument list.

**spatie/array-to-xml** — A simple class to convert an array to xml

- Repository: https://github.com/spatie/array-to-xml
- Website: https://spatie.be/open-source
- Stars: 1,199 · Forks: 214
- Language: PHP
- License: MIT
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/spatie-array-to-xml

## One static method and a default root element

The package description is deliberately modest: a very simple class to convert an array to an xml string. The class is Spatie\ArrayToXml\ArrayToXml, and the entire call is a static convert method.

```php
use Spatie\ArrayToXml\ArrayToXml;
...
$array = [
    'Good guy' => [
        'name' => 'Luke Skywalker',
        'weapon' => 'Lightsaber'
    ],
    'Bad guy' => [
        'name' => 'Sauron',
        'weapon' => 'Evil Eye'
    ]
];

$result = ArrayToXml::convert($array);
```

The result is a string, and the README shows what it contains, an XML declaration and a root element called root with one child element per top level key. The keys become element names, and nested arrays become nested elements, which is the obvious mapping and the reason the package exists.

The second argument sets the name of the root element, so ArrayToXml::convert($array, 'customrootname') produces a document rooted at that name instead. If you do not specify the argument, or set it to an empty string, root is used.

That is the whole core. Everything else in the README is about the conventions that let an array carry more than data, and the fact that the package is MIT licensed and comes with a PHPUnit configuration and a php-cs-fixer configuration in the repository is the sign of a package that is looked after rather than thrown together.

## Underscore-prefixed keys are the entire extension surface

Once the plain mapping is understood, the rest of the API is a small set of reserved key names, and they are the same convention as the ones used by templating and configuration formats everywhere else.

_attributes adds attributes to a node, and _value specifies the value of a node. A node with a _value and attributes becomes an element with text content, and the README's example produces an element like The_survivor with a house attribute and the text Harry Potter inside it.

_comment adds a comment to a node, and the placement of the comment depends on where you put the key in the array. You can also add multiple keys starting with _comment to add multiple comments, and the example uses _comment, _comment2 and _comment_other to produce three comments in a row, each placed relative to the element it follows. One rule catches people out: a comment is omitted if the value is an empty string or null.

_cdata wraps the value of a node into a CDATA section, which allows reserved characters to be used literally. A node whose value contains angle brackets is escaped normally, so <h1>Sauron</h1> becomes escaped text, while the same value under _cdata is emitted inside a CDATA section. If your input contains something that cannot be parsed, a DOMException will be thrown, which tells you the package builds a DOM and parses its way there rather than concatenating strings.

One constraint is stated in a note: the value of the _value field must be a string, with a link to the discussion that explains why.

## Spaces in key names become underscores, unless you say otherwise

The default behaviour is to sanitise key names. By default all spaces in the key names of your array will be converted to underscores.

So a key of 'Good guy' becomes the element Good_guy, which is what makes the output valid XML without the caller having to think about element naming rules. If you want to opt out of this behaviour you can set the third argument to false, and the key names are left alone, with ArrayToXml::convert($array, 'customrootname', false) producing a document that keeps its spaces.

That third argument is worth pausing on, because it is a boolean that is easy to misread. The method signature is a positional list, and the third position is the flag that leaves key names alone. The README's own example for customising the XML declaration passes true in that position, which means the opposite of what the same flag does elsewhere, and that is a perfectly good argument for wrapping the call in your own method if you use both features.

The argument list continues past that. Encoding is the fourth argument, version the fifth, DOM properties the sixth, and standalone the seventh.

```php
$result = ArrayToXml::convert($array, [], true, 'UTF-8', '1.1', [], true);
```

That call produces a declaration of <?xml version="1.1" encoding="UTF-8" standalone="yes"?>, which shows both the flexibility and the price of it. Seven positional parameters, four of which are only about the XML declaration, is a signature that is easy to get wrong and impossible to extend without breaking.

The root element can also carry attributes, by passing an array with an _attributes key as the second argument, and its name is then set with the rootElementName key in that same array.

## The alternative is to build the DOM yourself

There is a real alternative to this package, and it is the approach the package itself hints at, because the implementation uses a DOM and can throw a DOMException.

The alternative is to construct the document directly with PHP's own DOM API and serialise it, or to hand the structure to a templating layer that produces XML. The difference in approach is where the description of the document comes from.

An array to XML converter takes a document that is already described as data and renders it. That is exactly right when the shape of the XML is a mirror of the shape of your data, which is the common case for a third party format you have to emit, a config export, a feed, an invoice. It is fast to write and the result is consistent, and the whole document is one call you can reason about.

Building the DOM by hand is better when the document has a shape your data does not have, when elements need to appear in an order the data does not imply, when you need to validate against a schema, or when the document is large enough that holding it in memory as a DOM tree is a problem. It is also more code, and more of it is ceremony.

The tradeoff is that the converter wins on brevity and loses on expressiveness. Everything the document needs to say has to be expressible in the array, which is why the package needs _attributes, _value, _comment and _cdata: they are the escape hatches for the things a plain array cannot say.

## Conclusion

array-to-xml fits a PHP project that has to emit an XML document from data it already holds as an array, particularly an API returning a third party format, and it saves the team from hand-building a DOM tree. It does not fit a codebase that needs to parse, validate or transform XML, and it does not fit a project where the document structure has to be designed rather than mirrored. Before you adopt it, check the argument order against the four defaults, because the third argument flips the key sanitising behaviour and the fourth through seventh control the XML declaration.

## FAQ

### How do I install and use spatie/array-to-xml?

Install it with composer require spatie/array-to-xml, then call the static convert method: $result = ArrayToXml::convert($array). The result is an XML string with a root element called root unless you pass a different root element name as the second argument.

### How do I add attributes and element values in array-to-xml?

Use a key named _attributes to add attributes to a node and a key named _value to specify the value of a node. A node with both becomes an element with attributes and text content, and the note in the README says the value of the _value field must be a string.

### Can array-to-xml produce comments and CDATA sections?

Yes. A key named _comment adds a comment, with the placement depending on where the key sits in the array, and multiple keys starting with _comment add multiple comments. A key named _cdata wraps the value of a node in a CDATA section so reserved characters can be used literally.

### What happens to key names that contain spaces?

By default all spaces in key names are converted to underscores, so 'Good guy' becomes the element Good_guy. Setting the third argument of convert to false opts out of that behaviour and leaves the key names alone.

### Can I customise the XML declaration produced by array-to-xml?

Yes. Encoding is the fourth argument, version the fifth, DOM properties the sixth and standalone the seventh, so ArrayToXml::convert($array, [], true, 'UTF-8', '1.1', [], true) produces a declaration of version 1.1 with UTF-8 encoding and standalone set to yes.

## Sources

- [License: MIT](https://github.com/spatie/array-to-xml/blob/main/LICENSE)
- [Project website](https://spatie.be/open-source)
- [README](https://github.com/spatie/array-to-xml/blob/main/README.md)
- [Releases](https://github.com/spatie/array-to-xml/releases)
- [spatie/array-to-xml on GitHub](https://github.com/spatie/array-to-xml)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/spatie-array-to-xml
