Comment "parser" une balise XML avec espace de nom ?

Bonjour à tous,

j'aimerais savoir comment "parser" une balise XML avec espace de noms (namespace) ?

Exemple :
# Génération du fichier XML
$xml = "<?xml version='1.0' encoding='".PLX_CHARSET."'?>\n";
$xml .= "<document xmlns:dc='http://purl.org/dc/terms/'>\n";
$xml .= "\t".'<infopost>'."\n";
$xml .= "\t\t".'<dc:title><![CDATA['.trim($content['title']).']]></dc:title>'."\n";
$xml .= "\t".'</infopost>'."\n";
$xml .= "</document>\n";
Pour l'instant les balises auxquelles j'ai ajoutées des préfixes pour les espaces de noms ne s'affichent pas dans le site : Autant dans l'admin que dans la partie public.

Dans class.plx.motor.php j'ai essayé de remplacer $parser = xml_parser_create(PLX_CHARSET); par $parser = xml_parser_create_ns(PLX_CHARSET, ':');, mais ça n'a pas fonctionné ...

Quelqu'un pourrait me guider svp ?

Merci, bon dimanche à vous tous !

Réponses

  • StéphaneStéphane Member, Former PluXml Project Manager
    Bonjour yhugo

    Je pense qu'avec ce bout de code, cela devrait t'inspirer
    <?php
    
    	function parseArticle($filename, $namespace) {
    
    		# Mise en place du parseur XML
    		$data = implode('',file($filename));
    		$parser = xml_parser_create_ns('UTF-8');
    		xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0);
    		xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,0);
    		xml_parse_into_struct($parser,$data,$values,$iTags);
    		xml_parser_free($parser);		
    		# Recuperation des valeurs de nos champs XML
    		$art['title'] = trim($values[ $iTags[$namespace.':title'][0] ]['value']);
    		return $art;
    	}
    	
    	$art = parseArticle("./test.xml", 'http://purl.org/dc/terms/');
    	echo "<pre>";
    	print_r($art);
    	echo "</pre>";
    	
    ?>
    
    la fonction xml_parser_create_ns remplace xml_parser_create

    de plus il faut adapter la récupération des données
    $art['title'] = trim($values[ $iTags[$namespace.':title'][0] ]['value']);
    
    A toi d'adapter selon tes besoins

    Stéphane

    nb: j'ai mis UTF-8 en dur plutôt que d'utiliser PLX_CHARSET. ça te permettra de tester le code avec un simple copier coller dans un fichier php et un fichier test.xml

    le fichier xml:
    <?xml version='1.0' encoding='UTF-8'?>
    <document xmlns:dc="http://purl.org/dc/terms/">
    	<infopost>
    		<dc:title><![CDATA[Premier article]]></dc:title>
    	</infopost>
    </document>
    

    Consultant PluXml

    Ancien responsable du projet (2010 à 2018)

  • Merci beaucoup Stéphane ... C'est gentil de me répondre aussi rapidement !

    Je vais jouer avec ce bout de code aujourd'hui et je t'en redonne des nouvelles.

    Bonne journée
  • Bonsoir,

    @Stephane : J'ai essayé le code que tu m'as proposé dans des fichiers à part en dehors de Pluxml... Et ça a bien fonctionné.

    J'ai donc entrepris de faire les changements dans Pluxml, mais là il n'y a rien qui s'affiche ... rien ne se passe. Ça ne bug pas non plus, donc il me manque quelque chose ... ?

    Voici la fonction parseArticle() que j'ai modifié :
    function parseArticle($filename, $namespace) { //YHS ADD
    
    		# Mise en place du parseur XML
    
    		$data = implode('',file($filename));
    
    		//$parser = xml_parser_create(PLX_CHARSET);
    
    		$parser = xml_parser_create_ns(PLX_CHARSET);//YHS ADD
    
    		xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0);
    
    		xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,0);
    
    		xml_parse_into_struct($parser,$data,$values,$iTags);
    
    		xml_parser_free($parser);
    
    		# Recuperation des valeurs de nos champs XML
    
    		//$art['title'] = trim($values[ $iTags['title'][0] ]['value']);
    
    		$art['title'] = trim($values[ $iTags[$namespace.':title'][0] ]['value']);//YHS ADD
    
    		$art['author'] = trim($values[ $iTags['author'][0] ]['value']);
    
    		$art['allow_com'] = trim($values[ $iTags['allow_com'][0] ]['value']);
    
    		$art['chapo'] = (isset($values[ $iTags['chapo'][0] ]['value']))?trim($values[ $iTags['chapo'][0] ]['value']):'';
    
    		$art['content'] = (isset($values[ $iTags['content'][0] ]['value']))?trim($values[ $iTags['content'][0] ]['value']):'';
    
    		# Informations obtenues en analysant le nom du fichier
    
    		$art['filename'] = $filename;
    
    		$art['size'] = filesize($filename);
    
    		$tmp = $this->artInfoFromFilename($filename, 'all');
    
    		$art['numero'] = $tmp['artId'];
    
    		$art['categorie'] = $tmp['catId'];
    
    		$art['url'] = $tmp['artUrl'];
    
    		$art['date'] = plxDate::dateToIso($tmp['artDate'],$this->aConf['delta']);
    
    		# On recupere le nombre de commentaires de cet article si besoin est
    
    		if($this->mode != 'article') { # En mode article, on a cette information autrement
    
    			$motif = '/^'.$art['numero'].'.[0-9]{10}.[0-9]+.rdf$/';
    
    			$art['nb_com'] = $this->getNbCommentaires($motif);
    
    		}
    
    		# On retourne le tableau
    
    		return $art;
    
    	}
    
    Merci, à bientôt
  • StéphaneStéphane Member, Former PluXml Project Manager
    Bonjour yhugo

    regarde cette ligne
    $art['title'] = trim($values[ $iTags[$namespace.':title'][0] ]['value']);
    
    compare là avec
    $art['title'] = trim($values[ $iTags['title'][0] ]['value']);
    
    tu vois la différence avec le $namespace.
    C'est ça qu'il te manque dans la récupération de tous les champs

    Stéphane

    Consultant PluXml

    Ancien responsable du projet (2010 à 2018)

  • Bonjour Stephane,

    pourtant c'est ce que j'ai mis ... si tu regardes la 12e ligne du bloc de code ci-haut ... Pour l'instant je ne l'ai fait que pour 'title' mais c'est bien cette ligne ...
    $art['title'] = trim($values[ $iTags[$namespace.':title'][0] ]['value']);
    
    Les lignes que j'ai modifiées ont //YHS ADD au bout.

    Est-ce que le problème peut être dans le fichier XML ? Si le parent du noeud 'title' a un préfixe d'espace de nom lui-aussi est-ce que ça peut empêcher la récupération ?

    Merci encore, bonne journée
  • StéphaneStéphane Member, Former PluXml Project Manager
    Il faut passer en deuxieme paramètre de la fonction parseArticle le nom du namespace.

    Tu peux définir une constante dans le fichier config.php du genre
    define('PLX_NAMESPACE', 'http://purl.org/dc/terms/');
    
    et en recherchant dans les fichiers de pluxml l'appel de la fonction parseArticle, il faut changer, par exemple dans class.plx.motor.php dans la fonction getArticle
    $array[ $k ] = $this->parseArticle(PLX_ROOT.$this->aConf['racine_articles'].$v);
    
    par
    $array[ $k ] = $this->parseArticle(PLX_ROOT.$this->aConf['racine_articles'].$v, PLX_NAMESPACE);
    
    reste plus qu'à faire pareil, aux autres endroits ou parseArticle est appelé.

    Consultant PluXml

    Ancien responsable du projet (2010 à 2018)

  • yhugoyhugo Member
    décembre 2009 modifié
    Bonjour Stephane, merci beaucoup de prendre le temps de me répondre ... c'est très apprécié.

    Si j'ai besoin d'utiliser plus d'un espace de nom dans mon fichier XML ... Est-ce possible de "parser" un fichier qui en contiendrait plusieurs ?

    Merci, bonne fin de journée
  • StéphaneStéphane Member, Former PluXml Project Manager
    Peux-tu me donner un exemple de fichier xml avec plusieurs namespace stp
    Merci.

    Consultant PluXml

    Ancien responsable du projet (2010 à 2018)

  • yhugoyhugo Member
    décembre 2009 modifié
    Stéphane a écrit:
    Peux-tu me donner un exemple de fichier xml avec plusieurs namespace stp
    Merci.
    Salut Stephane,

    en fait mon but ultime c'est de transformer PluXML pour qu'il gère les fichiers RDF/XML ...

    Pour l'instant les fichiers .RDF que je génère pour les articles ressemblent à ça :
    <?xml version='1.0' encoding='UTF-8'?>
    <rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:rdfs='http://www.w3.org/2000/01/rdf-schema#' xmlns:sioc='http://rdfs.org/sioc/ns#' xmlns:sioct='http://rdfs.org/sioc/types#' xmlns:dc='http://purl.org/dc/elements/1.1/' xmlns:dcterms='http://purl.org/dc/terms/' xmlns:admin='http://webns.net/mvcb/' xmlns:foaf='http://xmlns.com/foaf/0.1/'>
    	<foaf:Document rdf:about='http://localhost/pluxml/'>
    		<dc:title>Nom du site Web courant et son slogan</dc:title>
    		<dc:description>Pésentation du site Web courant</dc:description>
    		<foaf:primaryTopic rdf:resource='http://localhost/pluxml/sujetPrincipalPageCouranteOuCategorie'/>
    		<admin:generatorAgent rdf:resource='http://pluxml.org/'/>
    	</foaf:Document>
    
    	<sioc:Post rdf:about='http://localhost/pluxml/urlDuBilletCourant'>
    		<dc:title><![CDATA[jQuery : Un petit script pour ouvrir un hyperlien externe dans une autre fenêtre]]></dc:title>
    		<sioc:has_creator rdfs:seeAlso='http://monsite.com/foaf.rdf'><![CDATA[yhugo]]></sioc:has_creator>
    		<dc:description><![CDATA[<p>Voici un petit script jQuery qui permet d'ouvrir automatiquement d'importe quel hyperlien externe dans une nouvelle fenêtre ou un nouvel onglet.</p>
    
    <p>Et ces quelques lignes de javascript ont l'avantages d'être non-intrusives et vous assureront des pages valides si vous utilisez un doctype XHTML 1.0 strict, ce qui ne serait pas le cas si vous ajoutiez directement l'attribut target="_blank" dans vos balises HTML.</p>]]></dc:description>
    		<sioc:content><![CDATA[<h2>Procédure d'intégration</h2>
    
    <p>D'abord vous aurez besoin de récupérer la librairie jQuery, et inclure celle-ci dans le HEAD de vos pages Web, comme ceci :</p>
    
    <p>Et maintenant juste en dessous dans une autre balise SCRIPT ajoutez ces quelques lignes de javascript :</p>]]></sioc:content>
    		<dcterms:created></dcterms:created>
    		<dcterms:modified></dcterms:modified>
    		<sioc:link rdf:resource='http://localhost/pluxml/urlDuBilletCourant' rdfs:label='Mot clé principal ?' />
    		<sioc:topic rdf:resource='http://lienVersOntologieMotCle.com' rdfs:label='Mot clé 1' />
    		<sioc:topic rdf:resource='http://lienVersOntologieMotCle.com' rdfs:label='Mot clé 2 ETC.' />
    		<allow_com>1</allow_com>
    	</sioc:Post>
    </rdf:RDF>
    
    Comme tu peux voir dans la balise ouvrante <rdf:RFD>, je fais référence à quelques "namespaces".

    Merci, bonne fin de soirée
  • StéphaneStéphane Member, Former PluXml Project Manager
    Bonjour yhugo

    Désolé mais je ne trouve pas de réponses à ta question.
    Je ne sais pas faire dans le cas de plusieurs namespace et avec une telle structure de fichier xml

    Stéphane.

    Consultant PluXml

    Ancien responsable du projet (2010 à 2018)

  • Stéphane a écrit:
    Bonjour yhugo

    Désolé mais je ne trouve pas de réponses à ta question.
    Je ne sais pas faire dans le cas de plusieurs namespace et avec une telle structure de fichier xml

    Stéphane.
    Bonjour Stephane,

    pas grave je finirai bien par trouver... De toute façon ce n'est pas très pressant, c'est un projet personnel.

    Merci beaucoup pour ton aide, bonne fin de journée
Connectez-vous ou Inscrivez-vous pour répondre.