Giter Club home page Giter Club logo

xmlbuilder's Introduction

PHP XML Builder Library

This is a simple PHP 7.2+ based XML Builder library. Use it to easily generate XML output with just PHP.

Table of Contents

Installation

composer require aaronddm/xml-builder

Prerequisites

  • PHP >=7.2.0
  • php-xml if using XMLWriter

Basic Usage

The following is an example of the most basic usage of this library.

Example: Using XMLWriter

<?php

require_once 'vendor/autoload.php';

use AaronDDM\XMLBuilder\XMLBuilder;
use AaronDDM\XMLBuilder\Writer\XMLWriterService;
use AaronDDM\XMLBuilder\Exception\XMLArrayException;

$xmlWriterService = new XMLWriterService();
$xmlBuilder = new XMLBuilder($xmlWriterService);

try {
    $xmlBuilder
        ->createXMLArray()
            ->start('Root')
                ->addCData('1 First Child First Element', 'This is a test')
                ->add('First Child Second Element', false)
                ->start('Second Parent')
                    ->add('Second child 1', null, ['myAttr' => 'Attr Value'])
                    ->add('Second child 2', false)
                    ->start('Third Parent')
                        ->add('Child')
                    ->end()
                ->end()
                ->add('First Child Third Element')
            ->end();

    var_dump($xmlBuilder->getXML());
} catch (XMLArrayException $e) {
    var_dump('An exception occurred: ' . $e->getMessage());
}

Output

string(414) "<?xml version="1.0" encoding="UTF-8"?>
<Root>
    <FirstChildFirstElement><![CDATA[This is a test]]></FirstChildFirstElement>
    <FirstChildSecondElement>False</FirstChildSecondElement>
    <SecondParent>
        <Secondchild myAttr="Attr Value"/>
        <Secondchild>False</Secondchild>
        <ThirdParent>
            <Child/>
        </ThirdParent>
    </SecondParent>
    <FirstChildThirdElement/>
</Root>
"

Example: Custom XMLWriter instance

<?php

require_once 'vendor/autoload.php';

use AaronDDM\XMLBuilder\XMLBuilder;
use AaronDDM\XMLBuilder\Writer\XMLWriterService;

$xmlWriter = new \XMLWriter();
$xmlWriter->openMemory();
$xmlWriter->setIndent(true);
$xmlWriter->setIndentString('    ');
$xmlWriter->startDocument('1.0', 'UTF-8');
$xmlWriter->writeDtd('html', '-//W3C//DTD XHTML 1.0 Transitional//EN', 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd');

$xmlWriterService = new XMLWriterService($xmlWriter);
$xmlBuilder = new XMLBuilder($xmlWriterService);

try {
    $xmlBuilder
        ->createXMLArray()
            ->start('Root')
                ->addCData('1 First Child First Element', 'This is a test')
                ->add('First Child Second Element', false)
                ->start('Second Parent')
                    ->add('Second child 1', null, ['myAttr' => 'Attr Value'])
                    ->add('Second child 2', false)
                    ->start('Third Parent')
                        ->add('Child')
                    ->end()
                ->end()
                ->add('First Child Third Element')
            ->end();

    var_dump($xmlBuilder->getXML());
} catch (XMLArrayException $e) {
    var_dump('An exception occurred: ' . $e->getMessage());
}

Output

string(414) "<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<Root>
    <FirstChildFirstElement><![CDATA[This is a test]]></FirstChildFirstElement>
    <FirstChildSecondElement>False</FirstChildSecondElement>
    <SecondParent>
        <Secondchild myAttr="Attr Value"/>
        <Secondchild>False</Secondchild>
        <ThirdParent>
            <Child/>
        </ThirdParent>
    </SecondParent>
    <FirstChildThirdElement/>
</Root>
"

Looping through data

You easily added sets of data using the startLoop method provided.

Example: XML output of a list of users

<?php
require_once 'vendor/autoload.php';

use AaronDDM\XMLBuilder\XMLArray;
use AaronDDM\XMLBuilder\XMLBuilder;
use AaronDDM\XMLBuilder\Writer\XMLWriterService;

$users = [
    [
        'name' => 'John Doe',
        'age' => 32
    ],
    [
        'name' => 'Jane Doe',
        'age' => 98
    ]
];


$xmlWriterService = new XMLWriterService();
$xmlBuilder = new XMLBuilder($xmlWriterService);

$xmlBuilder
    ->createXMLArray()
        ->start('Root')
            ->startLoop('Users', [], function (XMLArray $XMLArray) use ($users) {
                foreach ($users as $user) {
                    $XMLArray->start('User')
                        ->add('name', $user['name'])
                        ->add('age', $user['age']);
                }
            })
            ->end()
        ->end();

var_dump($xmlBuilder->getXML());

Output

string(261) "<?xml version="1.0" encoding="UTF-8"?>
<Root>
    <Users>
        <User>
            <name>John Doe</name>
            <age>32</age>
        </User>
        <User>
            <name>Jane Doe</name>
            <age>98</age>
        </User>
    </Users>
</Root>
"

Looping without a parent

You easily loop through a list of of data using the loop method provided, without having a parent element for the looped data.

Example: XML output of a list of users

<?php
require_once 'vendor/autoload.php';

use AaronDDM\XMLBuilder\XMLArray;
use AaronDDM\XMLBuilder\XMLBuilder;
use AaronDDM\XMLBuilder\Writer\XMLWriterService;

$users = [
    [
        'name' => 'John Doe',
        'age' => 32
    ],
    [
        'name' => 'Jane Doe',
        'age' => 98
    ]
];


$xmlWriterService = new XMLWriterService();
$xmlBuilder = new XMLBuilder($xmlWriterService);

$xmlBuilder
    ->createXMLArray()
    ->start('Root')
        ->loop(function (XMLArray $XMLArray) use ($users) {
            foreach ($users as $user) {
                $XMLArray->start('User')
                    ->add('name', $user['name'])
                    ->add('age', $user['age']);
            }
        })
    ->end();
    
var_dump($xmlBuilder->getXML());
?>

Output

<Root>
    <User>
        <name>John Doe</name>
        <age>32</age>
    </User>
    <User>
        <name>Jane Doe</name>
        <age>98</age>
    </User>
</Root>

Using a custom "XMLElementData" class

You can override the XMLElementData element class to implement transformations to the value of your data based on the type passed. To do this, you simply extend the XMLElementData class and override any of the methods to your liking.

Example: Customized MyXMLElementData class

<?php

require_once 'vendor/autoload.php';

use AaronDDM\XMLBuilder\XMLElementData;
use AaronDDM\XMLBuilder\XMLBuilder;
use AaronDDM\XMLBuilder\Writer\XMLWriterService;
use AaronDDM\XMLBuilder\Exception\XMLArrayException;

/**
 * Class MyXMLElementData
 */
class MyXMLElementData extends XMLElementData
{
    /**
     * @return mixed
     */
    public function getValue()
    {
        $type = $this->getType();
        $value = $this->value;

        if(is_bool($value)) {
            $type = 'boolean';
        }

        switch($type) {
            case 'specialType':
                $value = 'Special Type Value';
                break;
            case 'boolean':
                $value = ($value) ? 'True' : 'False';
                break;
        }

        return $value;
    }
}

$xmlWriterService = new XMLWriterService();
$xmlBuilder = new XMLBuilder($xmlWriterService);
$xmlBuilder->setElementDataClass(MyXMLElementData::class);

try {
    $xmlBuilder
        ->createXMLArray()
            ->start('Root')
                ->addCData('1 First Child First Element', 'This is a test')
                ->add('First Child Second Element', false)
                ->start('Second Parent')
                    ->add('Second child 1', null, ['myAttr' => 'Attr Value'])
                    ->add('Second child 2', false)
                    ->start('Third Parent')
                        ->add('Child')
                        ->add('Special Type Child', "1", [], 'specialType')
                    ->end()
                ->end()
                ->add('First Child Third Element')
            ->end();

    var_dump($xmlBuilder->getXML());
} catch (XMLArrayException $e) {
    var_dump('An exception occurred: ' . $e->getMessage());
}

Output

string(482) "<?xml version="1.0" encoding="UTF-8"?>
<Root>
    <FirstChildFirstElement><![CDATA[This is a test]]></FirstChildFirstElement>
    <FirstChildSecondElement>False</FirstChildSecondElement>
    <SecondParent>
        <Secondchild myAttr="Attr Value"/>
        <Secondchild>False</Secondchild>
        <ThirdParent>
            <Child/>
            <SpecialTypeChild>Special Type Value</SpecialTypeChild>
        </ThirdParent>
    </SecondParent>
    <FirstChildThirdElement/>
</Root>
"

Running tests

cd /root/of/project/
vendor/bin/phpunit

OR

docker build -t xmlbuilder .
docker run -u appuser -it --rm xmlbuilder vendor/bin/phpunit

License

This project is open-sourced software licensed under the MIT license.

xmlbuilder's People

Contributors

aaronddm avatar deniskoronets avatar pendalf89 avatar ricklambrechts avatar zhenq avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

xmlbuilder's Issues

:sparkles: **Welcome to GitHub Projects**

We're so excited that you've decided to create a new project! Now that you're here, let's make sure you know how to get the most out of GitHub Projects.

  • Create a new project
  • Give your project a name
  • Hit the ? key to see available keyboard shortcuts
  • Add a new column
  • Drag and drop this card to the new column
  • Search for and add issues or PRs to your project
  • Manage automation on columns

Adding a custom DOCTYPE tag

I need to create an XML file that has the following Doctype:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE VAR_COMP TXT "/path/to/file.dtd">

How can add this Doctype with this library?
Thanks.

How to loop without parent node ?

Hi,

Thanks for your package. I would like to loop by adding in XML

<Line>
<Sku>XXX</Sku>
<Qty>1</Qty>
</Line>

With this it creates a parent node but I don't need to. How can I do to only do a simple loop without a parent node ?

->startLoop('Users', [], function (XMLArray $XMLArray) use ($users) {
                foreach ($users as $user) {
                    $XMLArray->start('User')
                        ->add('name', $user['name'])
                        ->add('age', $user['age']);
                }
            })
            ->end()

Allow digit characters in

Hi,

I would like to name an attribute with digits like this : <AD1XCVD>.
It does not work cause there is a preg_replace that prevents it , so I obtain this <ADXCVD>

vendor\aaronddm\xml-builder\lib\XMLElementData.php we have this line

$name = preg_replace('/([^a-zA-Z\-\_\:]+)/', '', $name);

How can I do to allow it please ?

Unexpected closing tags

Hi @AaronDDM
thanks for this lib it's more connivant.
Could you please help I have came across with really weird closing tag accidently even i didn't understood how/why
So this is my code

    $xmlWriterService = new XMLWriterService();
    $xml_builder_obj = new XMLBuilder($xmlWriterService);
    $root = $xml_builder_obj->createXMLArray()->start('ProductData');

    $root->loop(
        function (XMLArray $XMLArray) use ($results, $relatives_tags, $product_type_attributes) {

            foreach ($product_type_attributes as $tag_index => $tag_value) {
                if (is_array($tag_value) && fn_he_amazon_array_depth($tag_value) === 1) {

                    $groups = $relatives_tags(key($tag_value));

                    $XMLArray->add(key($tag_value), $results[$groups[1]], [explode(',',$groups[2])[2] => $results[$groups[2]]]);

                } else {
                    $XMLArray->add($tag_index, $tag_value);
                }
            }
        });
    $root->end();

and this is the outcomes

<?xml version="1.0" encoding="UTF-8"?>
<ProductData>
    <Viscosity>2T</Viscosity>
    <BatteryAverageLife unitOfMeasure="days">2</BatteryAverageLife>
</ProductData>
<ColorMap>beige</ColorMap>
<SizeMap>XX-Small</SizeMap>
<CompatibleWithVehicleType>Airplane</CompatibleWithVehicleType>

while the expected output is like below:

<?xml version="1.0" encoding="UTF-8"?>
<ProductData>
        <Viscosity>2T</Viscosity>
        <BatteryAverageLife unitOfMeasure="days">2</BatteryAverageLife>
        <ColorMap>beige</ColorMap>
        <SizeMap>XX-Small</SizeMap>
       <CompatibleWithVehicleType>Airplane</CompatibleWithVehicleType>
</ProductData>

ProductData should be closed at the end not to be closed after the second tag.
I have used startLoop and using $root instead of XMLArray but the same result.

So, Could you please help to understand this issue? though if I comment the first if statement it's works fine.

Thanks in advance

Example returns an empty string

Hello,

I tried your example :

use AaronDDM\XMLBuilder\XMLBuilder;
use AaronDDM\XMLBuilder\Writer\XMLWriterService;
use AaronDDM\XMLBuilder\Exception\XMLArrayException;

$xmlWriterService = new XMLWriterService();
$xmlBuilder = new XMLBuilder($xmlWriterService);

try {
    $xmlBuilder
        ->createXMLArray()
            ->start('Root')
                ->addCData('1 First Child First Element', 'This is a test')
                ->add('First Child Second Element', false)
                ->start('Second Parent')
                    ->add('Second child 1', null, ['myAttr' => 'Attr Value'])
                    ->add('Second child 2', false)
                    ->start('Third Parent')
                        ->add('Child')
                    ->end()
                ->end()
                ->add('First Child Third Element')
            ->end();

    var_dump($xmlBuilder->getXML());
} catch (XMLArrayException $e) {
    var_dump('An exception occurred: ' . $e->getMessage());
}

But it returns an empty string

string(407) " "

My version PHP is PHP 8.0.22.

Do you know why I've got this empty response?

Thank you.

Regards.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.