Skip to content
This repository was archived by the owner on Jun 16, 2025. It is now read-only.

Commit 4d585e0

Browse files
committed
Initial commit
0 parents  commit 4d585e0

29 files changed

+1827
-0
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/example export-ignore

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.idea
2+
example/resource/*
3+
vendor
4+
test.php
5+
coverage
6+
composer.lock
7+
tests/unit/resources/generated.xml

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2018 Alaa Al-Maliki
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
# XML Data Mapper
2+
A small library to generate xml from source data
3+
4+
# Installation
5+
6+
`composer require alaa-almaliki/xml-data-mapper`
7+
8+
# Example
9+
10+
see [Example](https://github.com/alaa-almaliki/xml-data-mapper/tree/master/example)
11+
12+
To run the example run the command `php main.php`
13+
14+
### How it works
15+
16+
There is one class to be extended:
17+
18+
code
19+
20+
```php
21+
// Check example folder to fully understand how it works
22+
23+
// the class order represents xml mode which contains xml text node
24+
25+
class Order extends \Xml\Data\Subject
26+
{
27+
protected $nodeName = 'order'; // the node name is name of the xml node that contains text nodes
28+
29+
/**
30+
* add callbacks
31+
*/
32+
public function addCallbacks()
33+
{
34+
// you can manupilate the values presented in the xml
35+
$this->storage->registerCallback('first_name', function ($value) {
36+
return strtoupper($value);
37+
});
38+
39+
$this->storage->registerCallback('last_name', function ($value) {
40+
return strtoupper($value);
41+
});
42+
}
43+
44+
/**
45+
* @return array
46+
*/
47+
public function getMappedAttributes()
48+
{
49+
return [
50+
'order_number' => 'order_id', // The mapping is done as 'xml_attribute' => 'data_source_attribute'
51+
'order_date' => 'created_at',
52+
'customer_id' => 'customer_id',
53+
'first_name' => 'customer_firstname',
54+
'last_name' => 'customer_lastname',
55+
];
56+
}
57+
}
58+
```
59+
60+
Generating the XML
61+
```php
62+
// Data source - where the keys are used for mapping - see class order above
63+
$data = [
64+
'order' => [
65+
'order_id' => '1',
66+
'created_at' => '2018-03-04',
67+
'customer_id' => '123',
68+
'customer_firstname' => 'Alaa',
69+
'customer_lastname' => 'Al-Maliki',
70+
'shipping_address' => [
71+
'full_name' => 'Alaa Al-Maliki',
72+
'street' => '123 Wightfield Road',
73+
'city' => 'Manachester',
74+
'country' => 'United Kingdom',
75+
'postcode' => 'AB1 CD2'
76+
],
77+
'billing_address' => [
78+
'full_name' => 'John Doe',
79+
'street' => '456 Crimson Avenue',
80+
'city' => 'London',
81+
'country' => 'United Kingdom',
82+
'postcode' => 'BQ1 DF2'
83+
],
84+
'items' => [
85+
[
86+
'item_id' => '1',
87+
'qty' => 2,
88+
'name' => 'Blue Jeans',
89+
'sku' => 'BJ-123',
90+
'tax_code' => 'UK1',
91+
'total' => 12.98
92+
],
93+
[
94+
'item_id' => '2',
95+
'qty' => 1,
96+
'name' => 'Small T-shirt',
97+
'sku' => 'SS-456',
98+
'tax_code' => 'UK1',
99+
'total' => 32.56
100+
]
101+
],
102+
'payment' => [
103+
'method' => 'by_card',
104+
'amount_paid' => 45.54,
105+
]
106+
]
107+
];
108+
109+
$order = new Order(new \Xml\Data\CallbackStorage()); // order node
110+
$order->setData($data['order']);
111+
$lines = [];
112+
113+
foreach ($data['order']['items'] as $item) {
114+
$orderLine = new Line(new \Xml\Data\CallbackStorage()); // order line node
115+
$orderLine->setData($item);
116+
$lines[] = $orderLine;
117+
}
118+
119+
$shippingAddress = new ShippingAddress(new \Xml\Data\CallbackStorage()); // shipping address node
120+
$shippingAddress->setData($data['order']['shipping_address']);
121+
122+
$billingAddress = new BillingAddress(new \Xml\Data\CallbackStorage()); // billing address node
123+
$billingAddress->setData($data['order']['billing_address']);
124+
125+
$payment = new Payment(new \Xml\Data\CallbackStorage()); // payment node
126+
$payment->setData($data['order']['payment']);
127+
128+
$rootSubject = new RootSubject(new \Xml\Data\CallbackStorage()); // orders node - root
129+
130+
$rootSubject->addSubject($order); // add order node to the root node which is named order
131+
$order->addSubjects($lines, 'lines'); // add lines nodes to the order node
132+
$order->addSubject($billingAddress); // add billing address node to the order node
133+
$order->addSubject($shippingAddress); // add shipping address node to the order node
134+
$order->addSubject($payment); // add payment node to the order node
135+
136+
// generate the xml file
137+
\Xml\Data\Mapper::convert($rootSubject)
138+
->toXml()
139+
->addNamespace('xsi', "http://www.w3.org/1999/xhtml")
140+
->addNamespace('xmlns', "http://www.w3.org/2000/10/XMLSchema")
141+
->withOpenTag()
142+
->write(__DIR__ . '/resource/order.xml');
143+
```
144+
# Running unit tests
145+
`vendor/bin/phpunit -c phpunit.xml.dist`
146+
147+
# Contributions
148+
Feel free to contribute if any bugs found or enhancements need to be done
149+
150+
# License
151+
MIT

composer.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"name": "alaa-almaliki/xml-data-mapper",
3+
"type": "php-library",
4+
"homepage": "https://gitlab.com/alaa-almaliki/xml-data-mapper",
5+
"license": "MIT",
6+
"keywords": ["php arrays xml-mapper"],
7+
"authors": [
8+
{
9+
"name": "Alaa Al-Maliki",
10+
"email": "alaa.almaliki@gmail.com"
11+
}
12+
],
13+
"autoload": {
14+
"psr-4": {
15+
"Xml\\Data\\": "src/"
16+
},
17+
"files": ["src/Internal/functions.php"]
18+
},
19+
"require-dev": {
20+
"phpunit/phpunit": "^6.5"
21+
}
22+
}

example/autoload.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
final class Autoload
4+
{
5+
/** @var Autoloader */
6+
private static $_instance;
7+
/**
8+
* @return Autoloader|static
9+
*/
10+
private static function _instance()
11+
{
12+
if (!self::$_instance) {
13+
self::$_instance = new static();
14+
}
15+
return self::$_instance;
16+
}
17+
public static function register()
18+
{
19+
spl_autoload_register([self::_instance(), '_autoload']);
20+
}
21+
/**
22+
* @param string $class
23+
*/
24+
private static function _autoload($class)
25+
{
26+
$file = __DIR__ . '/src' . DIRECTORY_SEPARATOR . $class . '.php';
27+
if (!file_exists($file)) {
28+
$file = __DIR__ . '/src/Order' . DIRECTORY_SEPARATOR . $class . '.php';
29+
}
30+
31+
if (strpos($class, '\\') !== false) {
32+
if (!file_exists($file)) {
33+
$classPath = explode('\\', $class);
34+
unset($classPath[0]);
35+
unset($classPath[1]);
36+
$file = dirname(dirname(__FILE__)) . '/src'.DIRECTORY_SEPARATOR . implode('/', $classPath) . '.php';
37+
}
38+
}
39+
40+
require_once $file;
41+
}
42+
43+
}
44+
45+
Autoload::register();

example/main.php

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
ini_set('display_errors', '1');
4+
error_reporting(E_ALL);
5+
6+
require_once __DIR__ . '/autoload.php';
7+
require_once dirname(dirname(__FILE__)) . '/src/Internal/functions.php';
8+
$data = [
9+
'order' => [
10+
'order_id' => '1',
11+
'created_at' => '2018-03-04',
12+
'customer_id' => '123',
13+
'customer_firstname' => 'Alaa',
14+
'customer_lastname' => 'Al-Maliki',
15+
'shipping_address' => [
16+
'full_name' => 'Alaa Al-Maliki',
17+
'street' => '123 Wightfield Road',
18+
'city' => 'Manachester',
19+
'country' => 'United Kingdom',
20+
'postcode' => 'AB1 CD2'
21+
],
22+
'billing_address' => [
23+
'full_name' => 'John Doe',
24+
'street' => '456 Crimson Avenue',
25+
'city' => 'London',
26+
'country' => 'United Kingdom',
27+
'postcode' => 'BQ1 DF2'
28+
],
29+
'items' => [
30+
[
31+
'item_id' => '1',
32+
'qty' => 2,
33+
'name' => 'Blue Jeans',
34+
'sku' => 'BJ-123',
35+
'tax_code' => 'UK1',
36+
'total' => 12.98
37+
],
38+
[
39+
'item_id' => '2',
40+
'qty' => 1,
41+
'name' => 'Small T-shirt',
42+
'sku' => 'SS-456',
43+
'tax_code' => 'UK1',
44+
'total' => 32.56
45+
]
46+
],
47+
'payment' => [
48+
'method' => 'by_card',
49+
'amount_paid' => 45.54,
50+
]
51+
]
52+
];
53+
54+
$order = new Order(new \Xml\Data\CallbackStorage());
55+
$order->setData($data['order']);
56+
$lines = [];
57+
58+
foreach ($data['order']['items'] as $item) {
59+
$orderLine = new Line(new \Xml\Data\CallbackStorage());
60+
$orderLine->setData($item);
61+
$lines[] = $orderLine;
62+
}
63+
64+
$shippingAddress = new ShippingAddress(new \Xml\Data\CallbackStorage());
65+
$shippingAddress->setData($data['order']['shipping_address']);
66+
67+
$billingAddress = new BillingAddress(new \Xml\Data\CallbackStorage());
68+
$billingAddress->setData($data['order']['billing_address']);
69+
70+
$payment = new Payment(new \Xml\Data\CallbackStorage());
71+
$payment->setData($data['order']['payment']);
72+
73+
$rootSubject = new RootSubject(new \Xml\Data\CallbackStorage());
74+
75+
$rootSubject->addSubject($order);
76+
$order->addSubjects($lines, 'lines');
77+
$order->addSubject($billingAddress);
78+
$order->addSubject($shippingAddress);
79+
$order->addSubject($payment);
80+
81+
\Xml\Data\Mapper::convert($rootSubject)
82+
->toXml()
83+
->addNamespace('xsi', "http://www.w3.org/1999/xhtml")
84+
->addNamespace('xmlns', "http://www.w3.org/2000/10/XMLSchema")
85+
->withOpenTag()
86+
->write(__DIR__ . '/resource/order.xml');
87+
88+

example/src/Order.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
class Order extends \Xml\Data\Subject
4+
{
5+
protected $nodeName = 'order';
6+
7+
public function addCallbacks()
8+
{
9+
$this->storage->registerCallback('first_name', function ($value) {
10+
return strtoupper($value);
11+
});
12+
13+
$this->storage->registerCallback('last_name', function ($value) {
14+
return strtoupper($value);
15+
});
16+
}
17+
18+
/**
19+
* @return array
20+
*/
21+
public function getMappedAttributes()
22+
{
23+
return [
24+
'order_number' => 'order_id',
25+
'order_date' => 'created_at',
26+
'customer_id' => 'customer_id',
27+
'first_name' => 'customer_firstname',
28+
'last_name' => 'customer_lastname',
29+
];
30+
}
31+
}

0 commit comments

Comments
 (0)