pahnin
pahnin

Reputation: 5588

simplexml editing CDATA node

I have an xml file, I want to open it, edit certain CDATA node with the values from $_POST input and save it as same file, I've read some online documentation and ended up here, someone please suggest a nice way of doing this...

regardsh

Upvotes: 1

Views: 2369

Answers (4)

Joss Eve
Joss Eve

Reputation: 9

You can extend class SimpleXMLElement with simples function to do this

class ExSimpleXMLElement extends SimpleXMLElement {
    /**
     * Add CDATA text in a node
     * @param string $cdata_text The CDATA value  to add
     */
    private function addCData($cdata_text) {
        $node = dom_import_simplexml($this);
        $no = $node->ownerDocument;
        $node->appendChild($no->createCDATASection($cdata_text));
    }

    /**
     * Create a child with CDATA value
     * @param string $name The name of the child element to add.
     * @param string $cdata_text The CDATA value of the child element.
     */
    public function addChildCData($name, $cdata_text) {
        $child = $this->addChild($name);
        $child->addCData($cdata_text);

        return $child;
    }

    /**
     * Modify a value with CDATA value
     * @param string $name The name of the node element to modify.
     * @param string $cdata_text The CDATA value of the node element.
     */
    public function valueChildCData($name, $cdata_text) {

        $name->addCData($cdata_text);

        return $name;
    }
}

usage:

$xml_string = <<<XML
        <root>
            <item id="foo"/>
        </root>
XML;

$xml5 = simplexml_load_string($xml_string, 'ExSimpleXMLElement');
$xml5->valueChildCData($xml5->item, 'mysupertext');
echo $xml5->asXML();

$xml6 = simplexml_load_string($xml_string, 'ExSimpleXMLElement');
$xml6->item->addChildCData('mylittlechild', 'thepunishment');
echo $xml6->asXML();

result:

<?xml version="1.0"?>
<root>
  <item id="foo"><![CDATA[mysupertext]]></item>
</root>

<?xml version="1.0"?>
<root>
  <item id="foo">
    <mylittlechild><![CDATA[thepunishment]]></mylittlechild>
  </item>
</root>

Upvotes: 0

Ingo
Ingo

Reputation: 429

Since I had the same issue just recently, I wanted to let people also see some code, because the linked examples can only add new CDATA sections, but do not remove the old ones. So "my" solutions is merged from the mentioned code example plus deleting the old CDATA node.

// get DOM node
$node = dom_import_simplexml($mySimpleXmlElement); 


// remove existing CDATA ($node->childNodes->item(1) does not seem to work)
foreach($node->childNodes as $child) {
  if ($child->nodeType == XML_CDATA_SECTION_NODE) {
    $node->removeChild($child);
  }
}

// add new CDATA
$no = $node->ownerDocument; 
$node->appendChild($no->createCDATASection($myNewContent)); 

// print result
echo $xml->asXML();

Upvotes: 1

hakre
hakre

Reputation: 198204

SimpleXML does not make CDATA elements accessible by default. You can either tell simplexml to skip them (default) or to read them (see: read cdata from a rss feed). If you read them, they are standard text values, so they get merged with other textnodes.

More control is offered by the Document Object ModelDocs, which offers a DOMCdataSection which extends from DOMText, the standard text node model.

Even though this is a different PHP library (DOM vs. SimpleXML), both are compatible to each other. For example a SimpleXMLElement can be converted into a DOMElement by using the dom_import_simplexml function.

If you post some code what you've done so far it should be easy to figure out how to access the CDATA sections you want to modify. Please provide as well some demo XML data so the example is more speaking.

Upvotes: 1

Leysam Rosario
Leysam Rosario

Reputation: 369

I suggest you use this http://www.php.net/manual/en/class.domdocument.php

Upvotes: 0

Related Questions