Search code examples
phpxmldomsimplexmlcdata

Modify ![CDATA[]] in PHP? (XML)


I have an XML file which contains ![CDATA[]] data. Like this:

<link><![CDATA[https://google.de]]></link>

Now I heard that I can not modify ![CDATA[]] data or that they contains some special characters. But I do not remember anymore... That's the reason why I'am asking here.

Can I change the values in ![CDATA[]] and if yes, how?

I just want to append something like "?=dadc" on the link.

Edit: My XML file structure (Want to edit the url):

<?xml version="1.0" encoding="UTF-8"?>
    <rss>
      <channel xmlns:g="http://base.google.com/ns/1.0" version="2.0">
        <title>Google Eur English 1</title>
        <description/>
        <item>
          <title>Anno 2070</title>
          <g:image_link><![CDATA[http://cdn.kinguin.net/media/catalog/category/anno_8.jpg]]></g:image_link>
          <url><![CDATA[http://www.kinguin.net/category/4/anno-2070/?nosalesbooster=1&country_store=1&currency=EUR]]></url>
          <price><![CDATA[3.88 EUR]]></price>
          <platform>Uplay</platform>
        </item>
      </channel>
    </rss>

Greetings


Solution

  • That is true for SimpleXML. CDATA Sections are a special kind of text nodes. They are actually here to make embedded parts more readable for humans. SimpleXML does not really handle XML nodes so you will have to let it convert them to standard text nodes.

    If you have a JS or HTML fragment in XML it is easier to read if the special characters like < are not escaped. And this is what CDATA sections are for (and some backwards compatibility for browsers).

    So to modify a CDATA section and keep it, you will have to use DOM. DOM actually knows about the different node types. Here is a small example:

    $xml = '<link><![CDATA[https://google.de]]></link>';
    
    $document = new DOMDocument();
    $document->loadXml($xml);
    $xpath = new DOMXpath($document);
    
    foreach ($xpath->evaluate('//link/text()') as $linkValue) {
      $linkValue->data .= '?abc';
    }
    echo $document->saveXml();
    

    Output:

    <?xml version="1.0"?>
    <link><![CDATA[https://google.de?abc]]></link>