PHP SimpleXML get innerXML

Solution 1:

function SimpleXMLElement_innerXML($xml)
  {
    $innerXML= '';
    foreach (dom_import_simplexml($xml)->childNodes as $child)
    {
        $innerXML .= $child->ownerDocument->saveXML( $child );
    }
    return $innerXML;
  };

Solution 2:

This works (although it seems really lame):

echo (string)$qa->answer;

Solution 3:

To the best of my knowledge, there is not built-in way to get that. I'd recommend trying SimpleDOM, which is a PHP class extending SimpleXMLElement that offers convenience methods for most of the common problems.

include 'SimpleDOM.php';

$qa = simpledom_load_string(
    '<qa>
       <question>Who are you?</question>
       <answer>Who who, <strong>who who</strong>, <em>me</em></answer>
    </qa>'
);
echo $qa->answer->innerXML();

Otherwise, I see two ways of doing that. The first would be to convert your SimpleXMLElement to a DOMNode then loop over its childNodes to build the XML. The other would be to call asXML() then use string functions to remove the root node. Attention though, asXML() may sometimes return markup that is actually outside of the node it was called from, such as XML prolog or Processing Instructions.

Solution 4:

most straightforward solution is to implement custom get innerXML with simple XML:

function simplexml_innerXML($node)
{
    $content="";
    foreach($node->children() as $child)
        $content .= $child->asXml();
    return $content;
}

In your code, replace $body_content = $el->asXml(); with $body_content = simplexml_innerXML($el);

However, you could also switch to another API that offers distinction between innerXML (what you are looking for) and outerXML (what you get for now). Microsoft Dom libary offers this distinction but unfortunately PHP DOM doesn't.

I found that PHP XMLReader API offers this distintion. See readInnerXML(). Though this API has quite a different approach to processing XML. Try it.

Finally, I would stress that XML is not meant to extract data as subtrees but rather as value. That's why you running into trouble finding the right API. It would be more 'standard' to store HTML subtree as a value (and escape all tags) rather than XML subtree. Also beware that some HTML synthax are not always XML compatible ( i.e.
vs ,
). Anyway in practice, you approach is definitely more convenient for editing the xml file.

Solution 5:

I would have extend the SimpleXmlElement class:

class MyXmlElement extends SimpleXMLElement{

    final public function innerXML(){
        $tag = $this->getName();
        $value = $this->__toString();
        if('' === $value){
            return null;
        }
        return preg_replace('!<'. $tag .'(?:[^>]*)>(.*)</'. $tag .'>!Ums', '$1', $this->asXml());
    }
}

and then use it like this:

echo $qa->answer->innerXML();