简体   繁体   中英

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

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.

Despite the quite lengthy answers already given - which are not particularly wrong and do shed some light into some libxml library internals and it's PHP binding - you're most likely looking for:

$output->noValue = '';

To add an open tag, empty node-value and end tag (beautified, demo is here: http://3v4l.org/S2PKc ):

<?xml version="1.0"?>
<xml>
  <child1>
    <child2>value</child2>
    <noValue></noValue>
  </child1>
</xml>

Just noting as it seems it has been overlooked with the existing answers.

Since Simple XML is proving troublesome, perhaps XMLWriter could do what you want.

Here's a fiddle

<?php

$oXMLWriter = new XMLWriter;
$oXMLWriter->openMemory();
$oXMLWriter->startDocument('1.0', 'UTF-8');

$oXMLWriter->startElement('xml');
$oXMLWriter->writeElement('child1', 'Hello world!!');
$oXMLWriter->writeElement('noValue', '');
$oXMLWriter->endElement();

$oXMLWriter->endDocument();
echo htmlentities($oXMLWriter->outputMemory(TRUE));

?>

Output:

<?xml version="1.0" encoding="UTF-8"?>
  <xml>
    <child1>Hello world!!</child1>
    <noValue></noValue>
  </xml>

Extending from my comments (some got deleted):

The behavior depends on your environment. This same code:

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

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

echo $xml->asXML();

In 3v4l.org and Ideone.com , it produces self-closing tag;
In eval.in , codepad.org and on my localhost (PHP 5.3/5.4, libXML 2.7, Windows), it produces empty tag.

Since according to PHP document , LIBXML_NOEMPTYTAG only (guarenteed to) work in DOM , you may want to try DOM for ensurance:

$dom=new DOMDocument("1.0","UTF-8");
$dom->formatOutput=true;
$root=$dom->createElement("xml");
$dom->appendChild($root);
$child1=$dom->createElement("child1");
$root->appendChild($child1);
$node=$dom->createElement("child2");
$node->appendChild($dom->createTextNode("value"));
$child1->appendChild($node);
$node=$dom->createElement("noValue");
$child1->appendChild($node);
echo $dom->saveXML($dom,LIBXML_NOEMPTYTAG);

3v4l.org demo .

Edit :

All the above online demo site uses Content-Type: text/plain by default. If you want to directly output XML to browser as a standalone resource, you can specify the header before output:

header("Content-Type: text/xml");
echo $dom->saveXML($dom,LIBXML_NOEMPTYTAG);

I had to get the child node and asign to the nodeValue property an empty string, and the xml close tag appears.

$output->childNodes[1]->nodeValue = '';

Greetings.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM