Search code examples
phpxmlsimplexml

How to prevent self closing tag in php simplexml


I want to generate xml by using php simplexml.

$xml = new SimpleXMLElement('<xml/>');

$output = $xml->addChild('child1');
$output->addChild('child2', "value");
$output->addChild('noValue', '');

Header('Content-type: text/xml');
print($xml->asXML());

The output is

<xml>
   <child1>
      <child2>value</child2>
      <noValue/>
   </child1>
</xml>

What I want is if the tag has no value it should display like this

<noValue></noValue>

I've tried using LIBXML_NOEMPTYTAG from Turn OFF self-closing tags in SimpleXML for PHP?

I've tried $xml = new SimpleXMLElement('<xml/>', LIBXML_NOEMPTYTAG); and it doesn't work. So I don't know where to put the LIBXML_NOEMPTYTAG


Solution

  • LIBXML_NOEMPTYTAG does not work with simplexml, per the spec:

    This option is currently just available in the DOMDocument::save and DOMDocument::saveXML functions.

    To achieve what you're after, you need to convert the simplexml object to a DOMDocument object:

    $xml = new SimpleXMLElement('<xml/>');
    $child1 = $xml->addChild('child1');
    $child1->addChild('child2', "value");
    $child1->addChild('noValue', '');
    $dom_sxe = dom_import_simplexml($xml);  // Returns a DomElement object
    
    $dom_output = new DOMDocument('1.0');
    $dom_output->formatOutput = true;
    $dom_sxe = $dom_output->importNode($dom_sxe, true);
    $dom_sxe = $dom_output->appendChild($dom_sxe);
    
    echo $dom_output->saveXML($dom_output, LIBXML_NOEMPTYTAG);
    

    which returns:

    <?xml version="1.0" encoding="UTF-8"?>
    <xml>
      <child1>
        <child2>value</child2>
        <noValue></noValue>
      </child1>
    </xml>
    

    Something worth pointing out... the likely reason that the NOEMPTYTAG option is available for DOMDocument and not simplexml is that empty elements are not considered valid XML, while the DOM specification allows for them. You are banging your head against the wall to get invalid XML, which may suggest that the valid self-closing empty element would work just as well.