40 votes

Justification de la gestion par SimpleXMLElement des valeurs de texte dans addChild et addAttribute

N'est-ce pas là un comportement incohérent? (PHP 5.2.6)

 <?php

$a = new SimpleXMLElement('<a/>');

$a->addAttribute('b', 'One & Two');
//$a->addChild('c', 'Three & Four'); -- results in "unterminated entity reference" warning!
$a->addChild('c', 'Three &amp; Four');
$a->d = 'Five & Six';

print($a->asXML());
 

Rendu:

 <?xml version="1.0"?>
<a b="One &amp; Two">
    <c>Three &amp; Four</c>
    <d>Five &amp; Six</d>
</a>
 

Sur bugs.php.net, ils rejettent toutes les soumissions à ce sujet, disant que c'est une fonctionnalité. Pourquoi est-ce possible? BTW, il n'y a rien dans les documents sur cette divergence des valeurs de texte d'échappement par SimpleXMLElement.

Quelqu'un peut-il me convaincre que c'est la meilleure décision de conception d'API possible?

81voto

Alan Storm Points 82442

Juste pour s'assurer que nous sommes sur la même page, vous avez trois situations.

  1. L'insertion d'une esperluette dans un attribut à l'aide de addAttribute

  2. L'insertion d'une esperluette dans un élément à l'aide de la méthode addChild

  3. L'insertion d'une esperluette dans un élément d'une propriété de surcharge

C'est l'écart entre 2 et 3 qui vous coupe le sifflet. Pourquoi ne addChild pas automatiquement échapper à l'esperluette, tandis que l'ajout d'une propriété à l'objet et définition de sa valeur ne échapper à l'esperluette automatiquement?

Basé sur mon instinct, et encouragés par ce bug, c'était une volonté délibérée de décision de conception. La propriété de surcharge ($a->d = 'Cinq & Six";) est destinée à être la "fuite des arobases pour moi" façon de faire les choses. La méthode addChild méthode est destinée à être "ajouter exactement ce que je vous dis d'ajouter" la méthode. Ainsi, selon le comportement que vous avez besoin, SimpleXML peut vous accueillir.

Disons que vous avez une base de données de texte où tous les esperluettes étaient déjà échappé. L'auto-échappement ne fonctionne pas pour vous ici. C'est l'endroit où vous souhaitez utiliser la méthode addChild. Ou disons que vous nécessaires à l'insertion d'une entité dans votre document

$a = simplexml_load_string('<root></root>');
$a->b = 'This is a non-breaking space &nbsp;';
$a->addChild('c','This is a non-breaking space &nbsp;');    
print $a->asXML();

C'est ce que le Développeur PHP en ce bug est de défendre des droits. Le comportement de la méthode addChild est destiné à fournir un "moins simple, plus robuste" de soutien lorsque vous en avez besoin pour insérer une esperluette dans le document sans qu'il soit échappé.

Bien sûr, cela ne nous laisse avec la première situation je l'ai mentionné, le addAttribute méthode. Le addAttribute méthode ne coder les esperluettes. Donc, on pourrait aujourd'hui l'état de l'incohérence

  1. Le addAttriute méthode s'échappe des arobases
  2. La méthode addElement ne pas coder les esperluettes
  3. Ce comportement est un peu incohérente. Il est raisonnable que l'utilisateur attend de l' méthodes sur SimpleXML pour échapper à des choses d'une manière cohérente

Cette puis expose le vrai problème avec le SimpleXML api. La situation idéale serait ici

  1. Propriété de la Surcharge sur un Élément Objets échappe arobases
  2. Propriété de la Surcharge sur les Objets d'Attribut s'échappe des arobases
  3. La méthode addElement n'échappe pas à arobases
  4. le addAttribute méthode ne permet pas de coder les esperluettes

C'est impossible, parce que SimpleXML a pas de concept d'un Attribut de l'Objet. Le addAttribute méthode est (semble être?) la seule façon d'ajouter un attribut. En raison de cela, il s'avère (semble?) SimpleXML en incapables de créer des attributs avec des entités.

Tout cela révèle le paradoxe de **Simple**XML. L'idée derrière cette API est de fournir un moyen simple d'interagir avec quelque chose qui s'avère être complexe.

L'équipe pourrait avoir ajouté un SimpleXMLAttribute Objet, mais c'est une couche supplémentaire de complexité. Si vous souhaitez un multiple de hiérarchie d'objets, l'utilisation DomDoument.

L'équipe pourrait avoir ajouté les drapeaux de la addAttribute et addElement, mais les drapeaux de faire de l'API de plus en plus complexes.

La vraie leçon à tirer ici? Peut-être que c'est aussi simple que cela est difficile et simple et de la date est encore plus difficile. Je ne sais pas si c'était le cas ou pas, mais avec SimpleXML, il semble que quelqu'un a commencé avec une idée simple (utilisation de la propriété, la surcharge de rendre la création de documents XML facile), puis ajustée, comme les problèmes/demandes de fonctionnalités d'origine.

En fait, je pense que la vraie leçon à tirer ici est d'utiliser JSON ;)

16voto

Mathias Weitz Points 101

Ceci est ma solution, en particulier cela résout l'ajout de plusieurs enfants avec le même nom de balise

 $job->addChild('industrycode')->{0} = $entry1;
$job->addChild('industrycode')->{0} = $entry2;
$job->addChild('industrycode')->{0} = $entry3;
 

10voto

Daniel Points 507

"Disons que vous avez une base de données de texte où tous les esperluettes étaient déjà échappé."

Si vous faites cela, vous le faites mal. Les données doivent être stockées dans sa plus précis, pas munged quel que soit le type de sortie que vous utilisez actuellement. C'est encore pire si vous fait stocker des objets blob de (valide) HTML dans la base de données. À l'aide de la méthode addChild() pour récupérer les données de nouveau va détruire votre HTML; pas sensible de la bibliothèque des expositions telles horrible asymétrie.

la méthode addChild() pas de codage de votre texte pour vous, c'est complètement contre-intuitif. Quel est le point dans une API qui ne vous protège pas de tout cela? C'est comme json_encode() barfing si vous utilisez un guillemet double dans l'une de vos valeurs.

De toute façon, pour répondre à la question d'origine: Évidemment, moi aussi, je pense que c'est pas une bonne décision. Je crois qu'il est compatible avec beaucoup de PHP sur les décisions de conception, qui est de répondre à l'idée de quelqu'un de ce qui est "plus rapide", plutôt que de les corriger.

7voto

Dimitre Novatchev Points 147842

L'exigence pour échapper les caractères & et < est fournie dans la section de Données de Caractère et de Balisage et pas dans la section Attribut-Valeur de Normalisation, comme la réponse précédente unis.

Pour citer le XML Spec.:

"L'esperluette (&) et le chevron vers la gauche (<) ne DOIVENT PAS apparaître dans leur forme littérale, sauf s'ils sont utilisés comme délimiteurs du balisage, ou dans un commentaire, une instruction de traitement, ou d'une section CDATA. Si elles sont nécessaires ailleurs, ils DOIVENT être échappés en utilisant soit des références à des caractères numériques ou les cordes &amp; et &lt; respectivement"

5voto

Graham Lexie Points 31

Alan Tempête a eu une belle description de la question, cependant, il ya une solution facile pour le paradoxe qu'il décrit. La méthode addChild() pourrait avoir un paramètre optionnel qui détermine automatiquement les caractères d'échappement. Donc, je suis toujours convaincu que c'est tout simplement un (très) mauvais choix de conception.

La confusion est aggravée par le fait que la documentation de la méthode addChild() ne fait aucune référence que ce soit, de sorte que le problème (bien que l'on est dans la discussion). En outre, la méthode s'échappe de certains personnages (à savoir au moins et de plus de signes). Cela va induire en erreur des développeurs utilisant la méthode de croire qu'il échappe aux personnages en général.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X