web-dev-qa-db-fra.com

PHP - simppexml - addChild avec un autre simplexmlelement

J'essaie de construire un document XML plutôt complexe.

J'ai un tas de sections du document XML qui répète. Je pensais utiliser plusieurs modèles de chaîne comme document de base pour les sections et créer des instances d'éléments XML à l'aide de simppexml_load_string.

Donc j'ai une instance de simplexmlellement comme document de base

$ root = simpplexml_load_string ($ template_root);

ensuite, je boucle à travers des articles de ma base de données, créez un nouveau simplexmellement, quelque chose comme ceci:

pour (bla bla bla):

$ item = simpplexml_load_string ($ template_Item); // des trucs avec l'élément // Essayez d'ajouter un élément au document root.
[.____] // coincé ici .. ne peut pas faire $ root-> Articles-> AddChild (article $)

fin de fin;

Je ne peux pas appeler AddChild car il s'attend à ce que ce soit un nom de balise et une valeur .. Vous ne pouvez pas ajouter un autre simplexmellement.

Est-ce que j'ai râté quelque chose? Semble vraiment bête que AddChild ne peut pas prendre un simplexmlellement comme paramètre.

Y a-t-un autre moyen de faire ça? (En dehors de l'utilisation d'un XML LIB différent)

28
Ben

Autant que je sache, vous ne pouvez pas le faire avec simppexml car addChild _ _ _ NE PAS une copie profonde de l'élément (être nécessaire pour spécifier le nom de la balise peut facilement être surmonté en appelant SimpleXMLElement::getName()).

Une solution serait d'utiliser DOM à la place:

Avec cette fonction:

function sxml_append(SimpleXMLElement $to, SimpleXMLElement $from) {
    $toDom = dom_import_simplexml($to);
    $fromDom = dom_import_simplexml($from);
    $toDom->appendChild($toDom->ownerDocument->importNode($fromDom, true));
}

Nous avons pour

<?php
header("Content-type: text/plain");
$sxml = simplexml_load_string("<root></root>");

$n1 = simplexml_load_string("<child>one</child>");
$n2 = simplexml_load_string("<child><k>two</k></child>");

sxml_append($sxml, $n1);
sxml_append($sxml, $n2);

echo $sxml->asXML();

le résultat

<?xml version="1.0"?>
<root><child>one</child><child><k>two</k></child></root>

Voir aussi certains commentaires utilisateur utilisant des fonctions récursives et addChild, par exemple. celui-ci .

56
Artefacto

Vous pouvez utiliser cette fonction basée sur la création des enfants avec des attributs de la source:

function xml_adopt($root, $new) {
    $node = $root->addChild($new->getName(), (string) $new);
    foreach($new->attributes() as $attr => $value) {
        $node->addAttribute($attr, $value);
    }
    foreach($new->children() as $ch) {
        xml_adopt($node, $ch);
    }
}

$xml = new SimpleXMLElement("<root/>");
$child = new SimpleXMLElement("<content><p a=\"aaaaaaa\">a paragraph</p><p>another <br/>p</p></content>");

xml_adopt($xml, $child);
echo $xml->asXML()."\n";

Cela produira:

<?xml version="1.0"?>
<root><content><p a="aaaaaaa">a paragraph</p><p>another p<br/></p></content></root>
15
Carlos C Soto

L'exemple XML_ADOPT () ne conserve pas les nœuds d'espace de noms.
[.____] Mon édition a été rejetée parce que cela a changé à beaucoup? était spam ?.

Voici une version de xml_adopt () qui conserve les espaces de noms.

function xml_adopt($root, $new, $namespace = null) {
    // first add the new node
    // NOTE: addChild does NOT escape "&" ampersands in (string)$new !!!
    //  replace them or use htmlspecialchars(). see addchild docs comments.
    $node = $root->addChild($new->getName(), (string) $new, $namespace);
    // add any attributes for the new node
    foreach($new->attributes() as $attr => $value) {
        $node->addAttribute($attr, $value);
    }
    // get all namespaces, include a blank one
    $namespaces = array_merge(array(null), $new->getNameSpaces(true));
    // add any child nodes, including optional namespace
    foreach($namespaces as $space) {
      foreach ($new->children($space) as $child) {
        xml_adopt($node, $child, $space);
      }
    }
}

(Modifier: Exemple ajouté)

$xml = new SimpleXMLElement(
  '<?xml version="1.0" encoding="utf-8"?>
  <rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/">
  <channel></channel></rss>');

$item = new SimpleXMLElement(
  '<item xmlns:media="http://search.yahoo.com/mrss/">
    <title>Slide Title</title>
    <description>Some description</description>
    <link>http://example.com/img/image.jpg</link>
    <guid isPermaLink="false">A1234</guid>
    <media:content url="http://example.com/img/image.jpg" medium="image" duration="15">
    </media:content>
  </item>');

$channel = $xml->channel;
xml_adopt($channel, $item);

// output:
// Note that the namespace is (correctly) only preserved on the root element
'<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
  <channel>
    <item>
      <title>Slide Title</title>
      <description>Some description</description>
      <link>http://example.com/img/image.jpg</link>
      <guid isPermaLink="false">A1234</guid>
      <media:content url="http://example.com/img/image.jpg" medium="image" duration="15">
        </media:content>
    </item>
  </channel>
</rss>'
8
GDmac