1

I want to build an XML document in PHP.

I chose DOMDocument, and i know i have to use methods like createElement, createTextNode, appendChild, etc. to build my XML.

This is how i generated the xml with just one node containing vehicle information:

<?php
$doc = new DOMDocument ( '1.0', 'utf-8' );
$vehicles = $doc->createElement ( "Vehicles" );

$vehicle = $doc->createElement("Vehicle");
$vehicle_num = $doc->createElement("Number");
$vehicle_desc = $doc->createElement("Description");
$vehicle_year = $doc->createElement("Year");
$vehicle_make = $doc->createElement("Make");
$vehicle_model = $doc->createElement("Model");
$vehicle_color = $doc->createElement("Color");

$vehicle_num->appendChild($doc->createTextNode("AW2CM31Y8"));
$vehicle_year->appendChild($doc->createTextNode("2013"));
$vehicle_make->appendChild($doc->createTextNode("VOLKSWAGEN"));
$vehicle_model->appendChild($doc->createTextNode("NEW BEETLE"));
$vehicle_color->appendChild($doc->createTextNode("Black"));

$vehicle_desc->appendChild($vehicle_year);
$vehicle_desc->appendChild($vehicle_make);
$vehicle_desc->appendChild($vehicle_model);
$vehicle_desc->appendChild($vehicle_color);

$vehicle->appendChild($vehicle_num);
$vehicle->appendChild($vehicle_desc);

$vehicles->appendChild($vehicle);
$doc->appendChild ( $vehicles );

header ( "Content-type: text/xml" );
echo $doc->saveXML ();

But, what if i want to build an xml with say 100 nodes containing not only vehicle information, but also other nodes above and below it. This process would be too laborious.

So, is there an easy way of creating nodes and adding values to them in xml with php? I am concerned with the number of lines of code that i am supposed to write.

6
  • 2
    I'm not sure if optimistic is the right term to ask a technical question like yours. XML is merely a serialization format, so instead of writing the creation "as code" only, you should first of all separate the data into a data-structure of it's own. Then write code that creates the XML based on the data-structure. That's the best advice I can honestly give. Commented Oct 31, 2013 at 9:45
  • @hakre Modified my question now. Commented Oct 31, 2013 at 9:48
  • You can write it as plain xml? Or if you have a datasource to export as an XML use a for(each) loop? Commented Oct 31, 2013 at 9:49
  • 1
    Well I already understood it that way, however it still remains undefined what would be actually easy in your case. You perhaps would like to know how you can prevent the repetition of duplicate code. That perhaps nails it. Commented Oct 31, 2013 at 9:52
  • @hakre You got my point. I want to prevent duplicate code. Just for creating a single node in xml, i am writing around 3 lines of code. (Create node, add value, append to another node). I want to minimize the lines of code. Commented Oct 31, 2013 at 9:55

3 Answers 3

2

The first thing that comes to mind is that you have got code-repetition. You perhaps want to reduce that. This can be done by moving duplicate code into a function of it's own.

To do that fast, PHP has closures. Let's line that up:

You have a collection of vehicles and each vehicle just has properties and values. So you add a property to a vehicle. BTW, createElement does take a text already as value, so that you don't need to create the text-nodes. So let's wrap the duplicate code into functions and then just call these functions to create the XML. That already - through parametrization - shows your structure. Just differ between the definitions of the functions (first part) and the apply of those (second part):

<?php
/**
 * Create XML Document with PHP in an easy way
 *
 * @link http://stackoverflow.com/q/19702911/367456
 */

/**
 * @param DOMNode $node
 * @return DOMDocument
 */
$doc = function (DOMNode $node = NULL) {
    return $node ? ($node->ownerDocument ? : $node) : new DOMDocument();
};

/**
 * @param DOMElement $element
 * @param string $property
 * @param string $text
 * @return DOMElement the element the proeprty was added to
 */
$prop = function (DOMElement $element, $property, $text) {
    return $element->appendChild(
        $element->ownerDocument->createElement($property, $text)
    );
};

/**
 * @param DOMNode $element
 * @param string $name
 * @return DOMElement
 */
$element = function (DOMNode $element, $name) use ($doc) {
    return $element->appendChild(
        $doc($element)->createElement($name)
    );
};

So after all those functions have been defined, on to the second part:

$prop(
    $vehicle = $element(
        $vehicles = $element(
            $doc()
            , 'Vehicles'
        )
        , 'Vehicle'
    )
    , "Number"
    , "AW2CM31Y8"
);

$prop(
    $vehicle
    , "Year"
    , "2013"
);

$prop(
    $vehicle
    , "Make"
    , "VOLKSWAGEN"
);

$prop(
    $vehicle
    , "Model"
    , "NEW BEETLE"
);

$prop(
    $vehicle
    , "Color"
    , "Black"
);

Et voila. This has revealed some structure. Code-duplication has been removed as well. The only thing left is to finally echo the result out:

header("Content-type: text/xml");
echo $doc($vehicles)->saveXML();

If you look at the code you can even read that it literally does reverse the data-structure to create the XML. So next thing would be to make use of some kind of traversal, but that needs the definition of a data-structure first, not only the definition of the code-structure as it has been done so far (and which should already be of use for you).

Online Example: https://eval.in/59090

Sign up to request clarification or add additional context in comments.

4 Comments

@dskanth: Don't remove the newlines / indents in that answers example code as it actually shows the structure. You may find it verbose, I use that to make this more prominent. Take care that this code/structure is actually a step in the middle as you don't have yet a data-structure.
Its ok. Thanks for the answer. Works nice.
Well, it's normally suggested to do array to XML conversion so that you can further reduce code duplication, an advanced example that can also update XML structures is: How to update SimpleXMLElement using array - keep in mind the example is not that verbose.
Extending hakre's answer, in case you need to add an attribute to the nodes in xml, use this code: $attr = function (DOMElement $element, $property, $attribute, $attribute_value, $text) { $elem = $element->ownerDocument->createElement($property, $text); $elem->setAttributeNode(new DOMAttr($attribute, $attribute_value)); return $element->appendChild($elem); }; Usage: $attr($vehicle, "Year", "month", "06", "2013");
1

It seems to me what you're really looking for is XML Serialisation of an object with some sort of control over the document created therein.

To this end you might want to look at the XMLSerializer project - https://bitbucket.org/schmijos/xmlserializer

Which will taken an array/PHP Object and serialize it into XML.

1 Comment

Thanks for the link.. looks useful
0

I recommend you to create xml with the same structure, and use it as template. So you need only fill this xml.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.