Marshal XML is serializing / marshalling data structures to XML. It is also deserializing / unmarshalling XML back to the data structures.
Easiest way to install the library is via composer:
composer require kingson-de/marshal-xml-serializer
The following PHP versions are supported:
- PHP 7.0
- PHP 7.1
- PHP 7.2
- PHP 7.3
Just run:
composer test
Or without code coverage:
composer quicktest
Please check the Marshal Serializer README for more information.
The library provides several static methods to create your XML data once you defined the data structures.
<?php
use KingsonDe\Marshal\Data\Item;
use KingsonDe\Marshal\MarshalXml;
$xml = MarshalXml::serialize(new Item($mapper, $model));
// or
$xml = MarshalXml::serializeItem($mapper, $model);
// or
$xml = MarshalXml::serializeItemCallable(function (User $user) {
return [
'root' => [
'username' => $user->getUsername(),
'email' => $user->getEmail(),
'birthday' => $user->getBirthday()->format('Y-m-d'),
'followers' => count($user->getFollowers()),
],
];
}, $user);
Be aware MarshalXml::serializeCollection
and MarshalXml::serializeCollectionCallable
methods are not available.
Collections in XML cannot be generated at root level.
But after defining the root node you can use collections anywhere.
If you are using a concrete implementation that is extending AbstractXmlMapper you can use the attributes
method.
<?php
use KingsonDe\Marshal\AbstractXmlMapper;
class RootMapper extends AbstractXmlMapper {
public function map(){
return [
'root' => [
$this->attributes() => [
'xmlns' => 'http://example.org/xml',
],
],
];
}
}
If you are using a callable you need to use the MarshalXml::ATTRIBUTES_KEY
constant.
<?php
use KingsonDe\Marshal\MarshalXml;
$xml = MarshalXml::serializeItemCallable(function () {
return [
'root' => [
MarshalXml::ATTRIBUTES_KEY => [
'xmlns' => 'http://example.org/xml',
],
],
];
});
This will generate:
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="http://example.org/xml"/>
This is pretty simple:
<?php
use KingsonDe\Marshal\MarshalXml;
$xml = MarshalXml::serializeItemCallable(function (User $user) {
return [
'root' => [
'user' => $user->getUsername(),
],
];
}, $user);
This will generate:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<user>Kingson</user>
</root>
Then you must use the cdata
method for concrete Mapper implementations or MarshalXml::CDATA_KEY
for callable.
<?php
use KingsonDe\Marshal\AbstractXmlMapper;
class UserMapper extends AbstractXmlMapper {
public function map(User $user){
return [
'root' => [
'user' => $this->cdata($user->getUsername()),
],
];
}
}
<?php
use KingsonDe\Marshal\MarshalXml;
$xml = MarshalXml::serializeItemCallable(function (User $user) {
return [
'root' => [
'user' => [
MarshalXml::CDATA_KEY => $user->getUsername(),
],
],
];
}, $user);
This will generate:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<user><![CDATA[Kingson]]></user>
</root>
Then you must use the data
/ cdata
method for concrete Mapper implementations or MarshalXml::DATA_KEY
/ MarshalXml::CDATA_KEY
for callable.
<?php
use KingsonDe\Marshal\AbstractXmlMapper;
class UserMapper extends AbstractXmlMapper {
public function map(User $user){
return [
'root' => [
'user' => [
$this->attributes() => [
'xmlns' => 'http://example.org/xml',
],
$this->data() => $user->getUsername(),
],
'userCDATA' => [
$this->attributes() => [
'xmlns' => 'http://example.org/xml',
],
$this->cdata() => $user->getUsername(),
],
],
];
}
}
<?php
use KingsonDe\Marshal\MarshalXml;
$xml = MarshalXml::serializeItemCallable(function (User $user) {
return [
'root' => [
'user' => [
MarshalXml::ATTRIBUTES_KEY => [
'xmlns' => 'http://example.org/xml',
],
MarshalXml::DATA_KEY => $user->getUsername(),
],
'userCDATA' => [
MarshalXml::ATTRIBUTES_KEY => [
'xmlns' => 'http://example.org/xml',
],
MarshalXml::CDATA_KEY => $user->getUsername(),
],
],
];
}, $user);
This will generate:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<user xmlns="http://example.org/xml">Kingson</user>
<userCDATA xmlns="http://example.org/xml"><![CDATA[Kingson]]></userCDATA>
</root>
To transform XML back to your structure use Marshal's deserialize functions. You need a class extending the AbstractObjectMapper which will be passed to the deserializeXml function.
<?php
use KingsonDe\Marshal\AbstractObjectMapper;
use KingsonDe\Marshal\Data\FlexibleData;
use KingsonDe\Marshal\MarshalXml;
class AcmeExampleIdMapper extends AbstractObjectMapper {
public function map(FlexibleData $flexibleData, ...$additionalData) {
return $flexibleData
->get('container')
->get('acme-example:config')
->get('acme-example:id')
->get(MarshalXml::CDATA_KEY);
}
}
<?php
use KingsonDe\Marshal\MarshalXml;
$id = MarshalXml::deserializeXml($xml, new AcmeExampleIdMapper());
Another option would be to use the deserializeCallable function.
<?php
use KingsonDe\Marshal\MarshalXml;
$id = MarshalXml::deserializeXmlCallable($xml, function (FlexibleData $flexibleData) {
return $flexibleData['container']['acme-example:config']['acme-example:id'][MarshalXml::CDATA_KEY];
});
An easy way to modify existing XML is to use FlexibleData. Here is an example:
<?php
use KingsonDe\Marshal\Data\FlexibleData;
use KingsonDe\Marshal\MarshalXml;
$xml = '<?xml version="1.0" encoding="UTF-8"?><root><tag>Hello World!</tag></root>';
$flexibleData = new FlexibleData(MarshalXml::deserializeXmlToData($xml));
$flexibleData['root']['tag'] = 'some other text';
$modifiedXml = MarshalXml::serialize($flexibleData);
This project is released under the terms of the Apache 2.0 license.