2011-06-07 45 views
45

Tengo este código para crear y archivo de actualización xml:Cómo escribir CDATA usando SimpleXmlElement?

<?php 
$xmlFile = 'config.xml'; 
$xml  = new SimpleXmlElement('<site/>'); 
$xml->title = 'Site Title'; 
$xml->title->addAttribute('lang', 'en'); 
$xml->saveXML($xmlFile); 
?> 

Esto genera el siguiente archivo xml:

<?xml version="1.0"?> 
<site> 
    <title lang="en">Site Title</title> 
</site> 

La pregunta es: ¿Hay una manera de añadir CDATA con este método/técnica para crear el código xml a continuación?

<?xml version="1.0"?> 
<site> 
    <title lang="en"><![CDATA[Site Title]]></title> 
</site> 
+2

No parece que SimpleXML admita la creación de nodos CDATA. Pruebe [DOM] (http://php.net/manual/en/book.dom.php) en su lugar – Phil

+1

¿Por qué le importa? ' Título del sitio' y '<! [CDATA [Site Title]]>' son idénticos, excepto que uno usa más bytes y es más difícil de leer como humano. – Quentin

+0

@Quentin Buen punto. Solo un requisito del cliente. – quantme

Respuesta

80

¡Lo tengo! He adaptado el código de this great solution:

<?php 
// http://coffeerings.posterous.com/php-simplexml-and-cdata 
class SimpleXMLExtended extends SimpleXMLElement { 
    public function addCData($cdata_text) { 
    $node = dom_import_simplexml($this); 
    $no = $node->ownerDocument; 
    $node->appendChild($no->createCDATASection($cdata_text)); 
    } 
} 

$xmlFile = 'config.xml'; 
// instead of $xml = new SimpleXMLElement('<site/>'); 
$xml  = new SimpleXMLExtended('<site/>'); 
$xml->title = NULL; // VERY IMPORTANT! We need a node where to append 
$xml->title->addCData('Site Title'); 
$xml->title->addAttribute('lang', 'en'); 
$xml->saveXML($xmlFile); 
?> 

archivo XML generado:

<?xml version="1.0"?> 
<site> 
    <title lang="en"><![CDATA[Site Title]]></title> 
</site> 

Gracias Petah

+6

http://www.posterous.com/ ya no está disponible. Afortunadamente publicaste aquí! – Rober

+3

'public function addChildcdata ($ element_name, $ cdata) {$ this -> $ element_name = NULL; $ this -> $ element_name-> addCData ($ cdata); } 'Esta función añadida a la clase extendida le permite agregar CData directamente. – user151841

+0

Puedo simplemente agregar mi 2c que cuando lo carga archivo 'simplexml_load_file/string()' simplemente puede proporcionarle una opción "LIBXML_NOCDATA"? http://php.net/manual/en/libxml.constants.php – ReSpawN

23

aquí está mi versión de esta clase que tiene un método addChildWithCDATA rápida, basado en your answer:

Class SimpleXMLElementExtended extends SimpleXMLElement { 

    /** 
    * Adds a child with $value inside CDATA 
    * @param unknown $name 
    * @param unknown $value 
    */ 
    public function addChildWithCDATA($name, $value = NULL) { 
    $new_child = $this->addChild($name); 

    if ($new_child !== NULL) { 
     $node = dom_import_simplexml($new_child); 
     $no = $node->ownerDocument; 
     $node->appendChild($no->createCDATASection($value)); 
    } 

    return $new_child; 
    } 
} 

Simplemente utiliza i t así:

$node = new SimpleXMLElementExtended(); 
$node->addChildWithCDATA('title', 'Text that can contain any unsafe XML charachters like & and <>'); 
9

También puede crear una función de ayuda para esto, si usted prefiere no ampliar SimpleXMLElement:

/** 
    * Adds a CDATA property to an XML document. 
    * 
    * @param string $name 
    * Name of property that should contain CDATA. 
    * @param string $value 
    * Value that should be inserted into a CDATA child. 
    * @param object $parent 
    * Element that the CDATA child should be attached too. 
    */ 
$add_cdata = function($name, $value, &$parent) { 
    $child = $parent->addChild($name); 

    if ($child !== NULL) { 
    $child_node = dom_import_simplexml($child); 
    $child_owner = $child_node->ownerDocument; 
    $child_node->appendChild($child_owner->createCDATASection($value)); 
    } 

    return $child; 
}; 
2
class MySimpleXMLElement extends SimpleXMLElement{ 

     public function addChildWithCData($name , $value) { 
      $new = parent::addChild($name); 
      $base = dom_import_simplexml($new); 
      $docOwner = $base->ownerDocument; 
      $base->appendChild($docOwner->createCDATASection($value)); 
     } 

    } 

     $simpleXmlElemntObj = new MySimpleXMLElement('<site/>'); 

     /* USAGE */ 

     /* Standard */ 
     $simpleXmlElemntObj->addChild('Postcode','1111'); 

     /* With CDATA */ 
     $simpleXmlElemntObj->addChildWithCData('State','Processing'); 


    /* RESULT */ 
    /* 
    <?xml version="1.0"?> 
    <site> 
     <Postcode>1111</Postcode> 
     <State><![CDATA[Processing]]></State> 
    </site> 
    */ 
0

Aquí está mi solución combinada con la adición de niño con CDATA o agregando CDATA al nodo.

class SimpleXMLElementExtended extends SimpleXMLElement 
{ 
    /** 
    * Add value as CData to a given XML node 
    * 
    * @param SimpleXMLElement $node SimpleXMLElement object representing the child XML node 
    * @param string $value A text to add as CData 
    * @return void 
    */ 
    private function addCDataToNode(SimpleXMLElement $node, $value = '') 
    { 
     if ($domElement = dom_import_simplexml($node)) 
     { 
      $domOwner = $domElement->ownerDocument; 
      $domElement->appendChild($domOwner->createCDATASection("{$value}")); 
     } 
    } 

    /** 
    * Add child node with value as CData 
    * 
    * @param string $name The child XML node name to add 
    * @param string $value A text to add as CData 
    * @return SimpleXMLElement 
    */ 
    public function addChildWithCData($name = '', $value = '') 
    { 
     $newChild = parent::addChild($name); 
     if ($value) $this->addCDataToNode($newChild, "{$value}"); 
     return $newChild; 
    } 

    /** 
    * Add value as CData to the current XML node 
    * 
    * @param string $value A text to add as CData 
    * @return void 
    */ 
    public function addCData($value = '') 
    { 
     $this->addCDataToNode($this, "{$value}"); 
    } 
} 

// Usage example: 

$xml_doc = '<?xml version="1.0" encoding="utf-8"?> 
<offers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1"> 
</offers>'; 

$xml = new SimpleXMLElementExtended($xml_doc); 

$offer = $xml->addChild('o'); 
$offer->addAttribute('id', $product->product_id); 
$offer->addAttribute('url', 'some url'); 

$cat = $offer->addChildWithCData('cat', 'Category description as CDATA'); 

// or 

$cat = $offer->addChild('cat'); 
$cat->addCData('Category description as CDATA');