0

I'm generating an XML file via PHP and I'm doing it this way:

$dom  = new DOMDocument();
$root = $dom->createElement('Root');
...
// some node definitions here etc
$root->appendChild($product);
$root->appendChild($quantity);
$root->appendChild($measureUnit);
$root->appendChild($lineNumber);
...
$dom->appendChild($root);
$dom->save( '/some/dir/some-name.xml');

It all works well until I encountered some problem, when I get to the part that I needed to append lets say N child nodes. This meant that I would be calling the function appendChild() 'N' times too - and that resulted on a very long php script which is a little hard to maintain.

I know we can split the main script on smaller files for better maintenance but are there better ways to just 'chain' the 'appendChild' calls so it would save as a lot of written lines or is there a somewhat magic function such as 'appendChildren' available?

This is my first time using the DOMDocument() class, I hope someone can shed me some light.

Thank you

3
  • No, you can not chain appendChild calls, because that method returns the node that was appended, and not the node that you appended to. Commented Nov 18, 2021 at 11:46
  • 1
    You can of course stick all your nodes that you need to append into an array first - and then you loop over that array, and call appendChild for the current node inside the loop body. Commented Nov 18, 2021 at 11:52
  • Oh thanks! Yes, we're just looping it in an array for the meantime. I really thought we were doing something wrong Commented Nov 18, 2021 at 11:56

1 Answer 1

1

You can nest the DOMDocument::createElement() into DOMNode::appendChild() calls and chain child nodes or text content assignments.

Since PHP 8.0 DOMNode::append() can be used to append multiple nodes and strings.

$document = new DOMDocument();
// nest createElement inside appendChild
$document->appendChild(
    // store node in variable
    $root = $document->createElement('root')
);

// chain textContent assignment to appendChild
$root
  ->appendChild($document->createElement('product'))
  ->textContent = 'Example';
  
// use append to add multiple nodes  
$root->append(
  $product = $document->createElement('measureUnit'),
  $quantity = $document->createElement('quantity'),  
);
$product->textContent = 'cm';
$quantity->textContent = '42';


$document->formatOutput= true;
echo $document->saveXML();

Output:

<?xml version="1.0"?>
<root>
  <product>Example</product>
  <measureUnit>cm</measureUnit>
  <quantity>42</quantity>
</root>

I am using an interface for reusable and maintainable parts, usually:

interface XMLAppendable {
    
    public function appendTo(DOMElement $parent): void;
    
}

class YourXMLPart implements XMLAppendable {
    
    private $_product;
    private $_unit;
    private $_quantity;
    
    public function __construct(string $product, string $unit, int $quantity) {
        $this->_product = $product;
        $this->_unit = $unit;
        $this->_quantity = $quantity;
    }
    
    public function appendTo(DOMElement $parent): void {
        $document = $parent->ownerDocument; 
        $parent
            ->appendChild($document->createElement('product'))
            ->textContent = $this->_product;
        $parent
            ->appendChild($document->createElement('measureUnit'))
            ->textContent = $this->_unit;
        $parent
            ->appendChild($document->createElement('quantity'))
            ->textContent = $this->_quantity;
    }
}


$document = new DOMDocument();
// nest createElement inside appendChild
$document->appendChild(
    // store node in variable
    $root = $document->createElement('root')
);
$part = new YourXMLPart('Example', 'cm', 42);
$part->appendTo($root);

$document->formatOutput= true;
echo $document->saveXML();
Sign up to request clarification or add additional context in comments.

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.