2010-06-01 4 views
9

J'ai le code PHP suivant, mais cela ne fonctionne pas. Je ne vois aucune erreur, mais peut-être que je suis juste aveugle. Je cours ceci sur PHP 5.3.1.Obtenir exsl: node-set pour fonctionner en PHP

<?php 
$xsl_string = <<<HEREDOC 
<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" 
       xmlns="http://www.w3.org/1999/xhtml" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:exsl="http://exslt.org/common" 
       extension-element-prefixes="exsl"> 
    <xsl:template match="/"> 
    <p>Hello world</p> 
    <xsl:variable name="person"> 
     <firstname>Foo</firstname> 
     <lastname>Bar</lastname> 
     <email>[email protected]</email> 
    </xsl:variable> 
    <xsl:value-of select="exsl:node-set(\$person)/email"/> 
    </xsl:template> 
</xsl:stylesheet> 
HEREDOC; 

$xml_dom = new DOMDocument("1.0", "utf-8"); 
$xml_dom->appendChild($xml_dom->createElement("dummy")); 

$xsl_dom = new DOMDocument(); 
$xsl_dom->loadXML($xsl_string); 

$xsl_processor = new XSLTProcessor(); 
$xsl_processor->importStyleSheet($xsl_dom); 
echo $xsl_processor->transformToXML($xml_dom); 
?> 

Ce code devrait afficher "Bonjour tout le monde", suivi par "[email protected]", mais la partie e-mail ne semble pas. Une idée de ce qui ne va pas?

-Geoffrey Lee

+0

Bonne question (1). Voir ma réponse pour l'explication et une solution complète. –

Répondre

8

Le problème est que le code XSLT fourni a un espace de noms par défaut.

Par conséquent, les éléments <firstname>, <lastname> et <email> sont dans l'espace de noms xhtml. Mais email est référencé sans préfixe:

exsl:node-set($person)/email 

XPath considère tous les noms préfixés pour être dans « aucun espace de noms ». Il essaie de trouver un enfant de exsl:node-set($person) appelé email qui se trouve dans "aucun espace de noms" et cela échoue car son email enfant se trouve dans l'espace de noms xhtml. Ainsi, aucun noeud email n'est sélectionné et sorti.

Solution:

Cette transformation:

<xsl:stylesheet version="1.0" 
    xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:x="http://www.w3.org/1999/xhtml" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:exsl="http://exslt.org/common" 
    exclude-result-prefixes="exsl x"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 

    <xsl:template match="/"> 
    <html> 
    <p>Hello world</p> 
    <xsl:variable name="person"> 
     <firstname>Foo</firstname> 
     <lastname>Bar</lastname> 
     <email>[email protected]</email> 
    </xsl:variable> 
    <xsl:text>&#xA;</xsl:text> 
    <xsl:value-of select="exsl:node-set($person)/x:email"/> 
    <xsl:text>&#xA;</xsl:text> 
    </html> 
    </xsl:template> 
</xsl:stylesheet> 

lorsqu'il est appliqué sur tout document XML (non utilisé), produit le résultat recherché:

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:x="http://www.w3.org/1999/xhtml"> 
    <p>Hello world</p> 
[email protected] 
</html> 

Prenez note:

  1. La définition d'espace de noms ajouté avec préfixe x

  2. Le changement select attribut de <xsl:value-of>:

exsl:node-set($person)/x:email

+0

Ah, c'est tout à fait logique maintenant. Merci pour votre réponse bien écrite! – geofflee

Questions connexes