[SPIP][PLUGINS] v3.0-->v3.2
[lhc/web/www.git] / www / ecrire / inc / xml.php
index 3a40fb1..d6280eb 100644 (file)
 /***************************************************************************\
  *  SPIP, Systeme de publication pour l'internet                           *
  *                                                                         *
- *  Copyright (c) 2001-2016                                                *
+ *  Copyright (c) 2001-2017                                                *
  *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
  *                                                                         *
  *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
  *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
 \***************************************************************************/
 
-if (!defined('_ECRIRE_INC_VERSION')) return;
+/**
+ * Outils pour lecture de XML
+ *
+ * @package SPIP\Core\XML
+ **/
 
-// http://doc.spip.org/@spip_xml_load
-function spip_xml_load($fichier, $strict=true, $clean=true, $taille_max = 1048576, $datas='', $profondeur = -1){
+if (!defined('_ECRIRE_INC_VERSION')) {
+       return;
+}
+
+
+/**
+ * Lit un fichier xml donné et renvoie son arbre.
+ *
+ * @example
+ *     ```
+ *     include_spip('inc/xml');
+ *     $arbre = spip_xml_load(_DIR_PLUGINS . "$plug/plugin.xml");
+ *     ```
+ *
+ * @uses spip_xml_parse()
+ *
+ * @param string $fichier
+ *     Chemin local ou URL distante du fichier XML
+ * @param bool $strict
+ *     true pour râler si une balise n'est pas correctement fermée, false sinon.
+ * @param bool $clean ?
+ * @param int $taille_max
+ *     Taille maximale si fichier distant
+ * @param string|array $datas
+ *     Données à envoyer pour récupérer le fichier distant
+ * @param int $profondeur ?
+ * @return array|bool
+ *     - array : l'arbre XML,
+ *     - false si l'arbre xml ne peut être créé ou est vide
+ **/
+function spip_xml_load($fichier, $strict = true, $clean = true, $taille_max = 1048576, $datas = '', $profondeur = -1) {
        $contenu = "";
-       if (preg_match(",^(http|ftp)://,",$fichier)){
+       if (tester_url_absolue($fichier)) {
                include_spip('inc/distant');
-               $contenu = recuperer_page($fichier,false,false,$taille_max, $datas);
+               $contenu = recuperer_page($fichier, false, false, $taille_max, $datas);
+       } else {
+               lire_fichier($fichier, $contenu);
        }
-       else lire_fichier ($fichier, $contenu);
        $arbre = array();
-       if ($contenu)
+       if ($contenu) {
                $arbre = spip_xml_parse($contenu, $strict, $clean, $profondeur);
-               
-       return count($arbre)?$arbre:false;
+       }
+
+       return count($arbre) ? $arbre : false;
+}
+
+if (!defined('_SPIP_XML_TAG_SPLIT')) {
+       define('_SPIP_XML_TAG_SPLIT', "{<([^:>][^>]*?)>}sS");
 }
 
-if (!defined('_SPIP_XML_TAG_SPLIT')) define('_SPIP_XML_TAG_SPLIT', "{<([^:>][^>]*?)>}sS");
-// http://doc.spip.org/@spip_xml_parse
-function spip_xml_parse(&$texte, $strict=true, $clean=true, $profondeur = -1){
+/**
+ * Parse une chaine XML donnée et retourne un tableau.
+ *
+ * @see spip_xml_aplatit() pour l'inverse
+ *
+ * @param string $texte
+ *     Texte XML
+ * @param bool $strict
+ *     true pour râler si une balise n'est pas correctement fermée, false sinon.
+ * @param bool $clean ?
+ * @param int $profondeur ?
+ * @return array|bool
+ *     - array : l'arbre XML,
+ *     - false si l'arbre xml ne peut être créé ou est vide
+ **/
+function spip_xml_parse(&$texte, $strict = true, $clean = true, $profondeur = -1) {
        $out = array();
-  // enlever les commentaires
-  $charset = 'AUTO';
-  if ($clean===true){
-       if (preg_match(",<\?xml\s(.*?)encoding=['\"]?(.*?)['\"]?(\s(.*))?\?>,im",$texte,$regs))
-               $charset = $regs[2];
-         $texte = preg_replace(',<!--(.*?)-->,is','',$texte);
-         $texte = preg_replace(',<\?(.*?)\?>,is','',$texte);
+       // enlever les commentaires
+       $charset = 'AUTO';
+       if ($clean === true) {
+               if (preg_match(",<\?xml\s(.*?)encoding=['\"]?(.*?)['\"]?(\s(.*))?\?>,im", $texte, $regs)) {
+                       $charset = $regs[2];
+               }
+               $texte = preg_replace(',<!--(.*?)-->,is', '', $texte);
+               $texte = preg_replace(',<\?(.*?)\?>,is', '', $texte);
                include_spip('inc/charsets');
                $clean = $charset;
                //$texte = importer_charset($texte,$charset);
-  }
-  if (is_string($clean)) $charset = $clean;
-  $txt = $texte;
+       }
+       if (is_string($clean)) {
+               $charset = $clean;
+       }
+       $txt = $texte;
 
        // tant qu'il y a des tags
-       $chars = preg_split(_SPIP_XML_TAG_SPLIT,$txt,2,PREG_SPLIT_DELIM_CAPTURE);
-       while(count($chars)>=2){
+       $chars = preg_split(_SPIP_XML_TAG_SPLIT, $txt, 2, PREG_SPLIT_DELIM_CAPTURE);
+       while (count($chars) >= 2) {
                // tag ouvrant
                //$chars = preg_split("{<([^>]*?)>}s",$txt,2,PREG_SPLIT_DELIM_CAPTURE);
-       
+
                // $before doit etre vide ou des espaces uniquements!
                $before = trim($chars[0]);
 
-               if (strlen($before)>0)
-                       return importer_charset($texte,$charset);//$texte; // before non vide, donc on est dans du texte
-       
+               if (strlen($before) > 0) {
+                       return importer_charset($texte, $charset);
+               }//$texte; // before non vide, donc on est dans du texte
+
                $tag = rtrim($chars[1]);
                $txt = $chars[2];
-               
-               if (strncmp($tag,'![CDATA[',8)==0) return importer_charset($texte,$charset);//$texte;
-               if(substr($tag,-1)=='/'){ // self closing tag
-                       $tag = rtrim(substr($tag,0,strlen($tag)-1));
-                       $out[$tag][]="";
-               }
-               else{
-                       $closing_tag = preg_split(",\s|\t|\n|\r,",trim($tag));
-                       $closing_tag=reset($closing_tag);
+
+               if (strncmp($tag, '![CDATA[', 8) == 0) {
+                       return importer_charset($texte, $charset);
+               }//$texte;
+               if (substr($tag, -1) == '/') { // self closing tag
+                       $tag = rtrim(substr($tag, 0, strlen($tag) - 1));
+                       $out[$tag][] = "";
+               } else {
+                       $closing_tag = preg_split(",\s|\t|\n|\r,", trim($tag));
+                       $closing_tag = reset($closing_tag);
                        // tag fermant
                        $ncclos = strlen("</$closing_tag>");
-                       $p = strpos($txt,"</$closing_tag>");
-                       if ($p!==FALSE  AND (strpos($txt,"<")<$p)){
-                               $nclose =0; $nopen = 0;
+                       $p = strpos($txt, "</$closing_tag>");
+                       if ($p !== false and (strpos($txt, "<") < $p)) {
+                               $nclose = 0;
+                               $nopen = 0;
                                $d = 0;
                                while (
-                                       $p!==FALSE
-                                       AND ($morceau = substr($txt,$d,$p-$d))
-                                       AND (($nopen+=preg_match_all("{<".preg_quote($closing_tag)."(\s*>|\s[^>]*[^/>]>)}is",$morceau,$matches,PREG_SET_ORDER))>$nclose)
-                                       ){
+                                       $p !== false
+                                       and ($morceau = substr($txt, $d, $p - $d))
+                                       and (($nopen += preg_match_all("{<" . preg_quote($closing_tag) . "(\s*>|\s[^>]*[^/>]>)}is", $morceau,
+                                                       $matches, PREG_SET_ORDER)) > $nclose)
+                               ) {
                                        $nclose++;
-                                       $d=$p+$ncclos;
-                                       $p = strpos($txt,"</$closing_tag>",$d);
+                                       $d = $p + $ncclos;
+                                       $p = strpos($txt, "</$closing_tag>", $d);
                                }
                        }
-                       if ($p===FALSE){
-                               if ($strict){
-                                       $out[$tag][]="erreur : tag fermant $tag manquant::$txt"; 
+                       if ($p === false) {
+                               if ($strict) {
+                                       $out[$tag][] = "erreur : tag fermant $tag manquant::$txt";
+
                                        return $out;
-                               }
-                               else return importer_charset($texte,$charset);//$texte // un tag qui constitue du texte a reporter dans $before
+                               } else {
+                                       return importer_charset($texte, $charset);
+                               }//$texte // un tag qui constitue du texte a reporter dans $before
+                       }
+                       $content = substr($txt, 0, $p);
+                       $txt = substr($txt, $p + $ncclos);
+                       if ($profondeur == 0 or strpos($content, "<") === false) // eviter une recursion si pas utile
+                       {
+                               $out[$tag][] = importer_charset($content, $charset);
+                       }//$content;
+                       else {
+                               $out[$tag][] = spip_xml_parse($content, $strict, $clean, $profondeur - 1);
                        }
-                       $content = substr($txt,0,$p);
-                       $txt = substr($txt,$p+$ncclos);
-                       if ($profondeur==0 OR strpos($content,"<")===FALSE) // eviter une recursion si pas utile
-                               $out[$tag][] = importer_charset($content,$charset);//$content;
-                       else
-                               $out[$tag][]=spip_xml_parse($content, $strict, $clean, $profondeur-1);
                }
-               $chars = preg_split(_SPIP_XML_TAG_SPLIT,$txt,2,PREG_SPLIT_DELIM_CAPTURE);
+               $chars = preg_split(_SPIP_XML_TAG_SPLIT, $txt, 2, PREG_SPLIT_DELIM_CAPTURE);
        }
-       if (count($out)&&(strlen(trim($txt))==0))
+       if (count($out) && (strlen(trim($txt)) == 0)) {
                return $out;
-       else
-               return importer_charset($texte,$charset);//$texte;
+       } else {
+               return importer_charset($texte, $charset);
+       }//$texte;
 }
 
-// http://doc.spip.org/@spip_xml_aplatit
-function spip_xml_aplatit($arbre,$separateur = " "){
+// http://code.spip.net/@spip_xml_aplatit
+function spip_xml_aplatit($arbre, $separateur = " ") {
        $s = "";
-       if (is_array($arbre))
-               foreach($arbre as $tag=>$feuille){
-                       if (is_array($feuille)){
-                               if ($tag!==intval($tag)){
+       if (is_array($arbre)) {
+               foreach ($arbre as $tag => $feuille) {
+                       if (is_array($feuille)) {
+                               if ($tag !== intval($tag)) {
                                        $f = spip_xml_aplatit($feuille, $separateur);
                                        if (strlen($f)) {
-                                               $tagf = explode(" ",$tag);
+                                               $tagf = explode(" ", $tag);
                                                $tagf = $tagf[0];
-                                               $s.="<$tag>$f</$tagf>";
+                                               $s .= "<$tag>$f</$tagf>";
+                                       } else {
+                                               $s .= "<$tag />";
                                        }
-                                       else $s.="<$tag />";
+                               } else {
+                                       $s .= spip_xml_aplatit($feuille);
                                }
-                               else
-                                       $s.=spip_xml_aplatit($feuille);
                                $s .= $separateur;
+                       } else {
+                               $s .= "$feuille$separateur";
                        }
-                       else
-                               $s.="$feuille$separateur";
                }
+       }
+
        return strlen($separateur) ? substr($s, 0, -strlen($separateur)) : $s;
 }
 
-// http://doc.spip.org/@spip_xml_tagname
-function spip_xml_tagname($tag){
-       if (preg_match(',^([a-z][\w:]*),i',$tag,$reg))
+// http://code.spip.net/@spip_xml_tagname
+function spip_xml_tagname($tag) {
+       if (preg_match(',^([a-z][\w:]*),i', $tag, $reg)) {
                return $reg[1];
+       }
+
        return "";
 }
-// http://doc.spip.org/@spip_xml_decompose_tag
-function spip_xml_decompose_tag($tag){
+
+// http://code.spip.net/@spip_xml_decompose_tag
+function spip_xml_decompose_tag($tag) {
        $tagname = spip_xml_tagname($tag);
        $liste = array();
-       $p=strpos($tag,' ');
-       $tag = substr($tag,$p);
-       $p=strpos($tag,'=');
-       while($p!==false){
-               $attr = trim(substr($tag,0,$p));
-               $tag = ltrim(substr($tag,$p+1));
+       $p = strpos($tag, ' ');
+       $tag = substr($tag, $p);
+       $p = strpos($tag, '=');
+       while ($p !== false) {
+               $attr = trim(substr($tag, 0, $p));
+               $tag = ltrim(substr($tag, $p + 1));
                $quote = $tag{0};
-               $p=strpos($tag,$quote,1);
-               $cont = substr($tag,1,$p-1);
+               $p = strpos($tag, $quote, 1);
+               $cont = substr($tag, 1, $p - 1);
                $liste[$attr] = $cont;
-               $tag = substr($tag,$p+1);
-               $p=strpos($tag,'=');
+               $tag = substr($tag, $p + 1);
+               $p = strpos($tag, '=');
        }
-       return array($tagname,$liste);
+
+       return array($tagname, $liste);
 }
 
-// http://doc.spip.org/@spip_xml_match_nodes
-function spip_xml_match_nodes($regexp,&$arbre,&$matches,$init=true){
-       if ($init)
+/**
+ * Recherche dans un arbre XML généré par `spip_xml_parse()` (ou une branche de cet arbre)
+ * les clés de l'arbre qui valident la regexp donnée.
+ *
+ * Les branches qui valident la regexp sont retournées dans le tableau `$matches`.
+ *
+ * @see spip_xml_parse()
+ * @see spip_xml_decompose_tag()
+ *
+ * @param string $regexp
+ *     Expression régulière
+ * @param array $arbre
+ *     Arbre XML
+ * @param array $matches
+ *     Branches de l'arbre validant la rexgep
+ * @param bool $init ?
+ * @return bool
+ *     false si aucun élément ne valide l'expression régulière, true sinon.
+ **/
+function spip_xml_match_nodes($regexp, &$arbre, &$matches, $init = true) {
+       if ($init) {
                $matches = array();
-       if(is_array($arbre) && count($arbre))
-               foreach(array_keys($arbre) as $tag){
-                       if (preg_match($regexp,$tag))
+       }
+       if (is_array($arbre) && count($arbre)) {
+               foreach (array_keys($arbre) as $tag) {
+                       if (preg_match($regexp, $tag)) {
                                $matches[$tag] = &$arbre[$tag];
-                       if (is_array($arbre[$tag]))
-                               foreach(array_keys($arbre[$tag]) as $occurences)
-                                       spip_xml_match_nodes($regexp,$arbre[$tag][$occurences],$matches,false);
+                       }
+                       if (is_array($arbre[$tag])) {
+                               foreach (array_keys($arbre[$tag]) as $occurences) {
+                                       spip_xml_match_nodes($regexp, $arbre[$tag][$occurences], $matches, false);
+                               }
+                       }
                }
+       }
+
        return (count($matches));
 }
-
-
-?>