1

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

pahnin
  • 5,367
  • 12
  • 40
  • 57

4 Answers4

1

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();
Ingo
  • 429
  • 3
  • 7
1

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.

Community
  • 1
  • 1
hakre
  • 193,403
  • 52
  • 435
  • 836
  • for now I've found a way to add CDATA with whatever the library or method may be given here http://coffeerings.posterous.com/php-simplexml-and-cdata. thnx for your help. – pahnin Nov 09 '11 at 22:04
  • Upvote appreceated ;) - The link you mention is to make SimpleXML read the CDATA sections (see as well: [read cdata from a rss feed](http://stackoverflow.com/questions/8020181/read-cdata-from-a-rss-feed/8020274#8020274)). I wonder if you need to specifically edit CDATA sections (if so please add some example XML) or just the (merged) text is okay for you. – hakre Nov 09 '11 at 22:11
  • I've managed to edit the CDATA by replacing old values with the input, i.e the input is what I need to save. So I just saved it with $xml->asXMl(); thnx – pahnin Nov 09 '11 at 22:16
  • Okay, so the CDATA section is the whole text (which is common for RSS feeds). Then loading into simpleXML with the flag `LIBXML_NOCDATA` is what you need. – hakre Nov 09 '11 at 22:23
  • This is not correct. SimpleXML handles CDATA just fine. You just have to remember to always cast to string using (string)$node and not believe print_r on a SimpleXMLElement. See http://uk3.php.net/manual/en/function.simplexml-load-string.php#84365 – IMSoP Jul 19 '12 at 00:39
  • @hakre Just don't use print_r (particularly once you've converted something to a string!) But yes, SimpleXML is really designed for read-only operations, so should be ruled out for that reason (not because of the "missing CDATA" myth). – IMSoP Jul 19 '12 at 09:20
  • Well, if you don't want it in CDATA elements, tell the parser. You then have just normalized nodes. I won't call that a myth but a useful feature. Strictly spoken, CDATA elements itself should not cause any issue. But well, you know ;) – hakre Jul 19 '12 at 09:26
0

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>
Joss Eve
  • 9
  • 2
0

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

Leysam Rosario
  • 379
  • 2
  • 11