<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>l'indicible blog &#187; Php</title>
	<atom:link href="http://www.lindicible.com/blog/category/dev/php-dev/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.lindicible.com/blog</link>
	<description>&#60;!--:en--&#62;the details of the inexpressible&#60;!--:--&#62;&#60;!--:fr--&#62;les détails de l'ineffable&#60;!--:--&#62;</description>
	<lastBuildDate>Fri, 02 Sep 2011 19:30:56 +0000</lastBuildDate>
	<language>fr</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>DOMDocument et UTF-8, un problème de charset en php</title>
		<link>http://www.lindicible.com/blog/2009/10/18/domdocument-et-utf-8-un-probleme-de-charset-en-php/</link>
		<comments>http://www.lindicible.com/blog/2009/10/18/domdocument-et-utf-8-un-probleme-de-charset-en-php/#comments</comments>
		<pubDate>Sat, 17 Oct 2009 23:44:11 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Développement]]></category>
		<category><![CDATA[Php]]></category>
		<category><![CDATA[SEO]]></category>
		<category><![CDATA[Tutoriaux]]></category>

		<guid isPermaLink="false">http://www.lindicible.com/blog/?p=481</guid>
		<description><![CDATA[Aujourd&#8217;hui, nous allons voir comment manipuler des éléments du DOM avec php. Nous prendrons pour exemple une fonction très pratique mais pourtant apparamment bien difficile à trouver : commenter ajouter un attribut spécifique à des éléments HTML. Ceci peut-être utile par exemple pour ajouter un attribut rel=&#160;&#187;nofollow&#160;&#187; à des liens pour signaler aux moteurs de [...]]]></description>
			<content:encoded><![CDATA[<p>Aujourd&#8217;hui, nous allons voir comment manipuler des éléments du <a href="http://fr.wikipedia.org/wiki/Document_Object_Model" rel="external">DOM</a> avec php.<br />
Nous prendrons pour exemple une fonction très pratique mais pourtant apparamment bien difficile à trouver : commenter ajouter un attribut spécifique à des éléments HTML.<br />
Ceci peut-être utile par exemple pour ajouter un attribut rel=&nbsp;&raquo;nofollow&nbsp;&raquo; à des liens pour signaler aux moteurs de recherche qu&#8217;ils n&#8217;ont pas à les suivre, tout en laissant ces liens accessibles pour vos utilisateurs. D&#8217;un point de vue référencement, ça peut être bien pratique puisque cela vous évite de voir votre PageRank être dispersé vers tous les liens présents sur vos pages.</p>
<p>Pour arriver à ce but, nous allons rencontrer plusieurs problèmes assez vicieux. Commençons par une fonction aboutie, pour faire gagner du temps au plus vifs d&#8217;entre vous :</p>
<pre>
function addAttribute($context, $tag, $attribute, $value)
{
	$initialEncoding = mb_detect_encoding($context);
	if( $initialEncoding != 'UTF-8' ){
		$context = utf8_encode($context);
	}

	$doc = new DOMDocument("4.01", "utf-8");

	$contentPrefix = '&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"&gt;&lt;html&gt;&lt;head&gt;&lt;title&gt;required meta for utf-8 handling!&lt;/title&gt;&lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8"&gt;&lt;/head&gt;&lt;body&gt;';
	$contentSuffix = '&lt;/body&gt;&lt;/html&gt;';

	$doc->loadHTML($contentPrefix . $context . $contentSuffix);

	$elements = $doc->getElementsByTagName($tag);

	if(!is_array($value)){
		$value = array($value);
	}

	foreach($elements as $element)
	{

		foreach($value as $currentValue)
		{
			$alreadySet = false;

			if($element->hasAttribute($attribute))
			{

				$attributeCurrentValue = $element->getAttribute($attribute);

				$attributeCurrentValues = explode(' ', $attributeCurrentValue);

				foreach( $attributeCurrentValues as $attributeCurrentValue )
				{
					if($attributeCurrentValue == $currentValue){
						$alreadySet = true;
					}
				}
				if(!$alreadySet){
					$element->setAttribute($attribute, implode(' ', $attributeCurrentValues) . ' ' . $currentValue);
				}
			} else {
				$element->setAttribute($attribute, $currentValue);
			}
		}
	}

	$output = mb_substr($doc->saveHTML(), 236, -16);

	if( $initialEncoding != 'UTF-8' ){
		mb_convert_encoding($output, $initialEncoding, 'UTF-8');
	}

	return $output;
}
</pre>
<h3>Explications</h3>
<pre>
$initialEncoding = mb_detect_encoding($context);
	if( $initialEncoding != 'UTF-8' ){
		$context = utf8_encode($context);
	}
</pre>
<p>On commence par détecter le format d&#8217;encodage actuellement utilisé dans le contexte fourni.<br />
On le stocke pour pouvoir retourner la version modifiée dans le même format, et on le converti en UTF-8.<br />
Pourquoi UTF-8 ? Ce format a l&#8217;avantage (énorme) de gérer tous les caractères, y compris les caractères accentués ou spéciaux de différents langages.</p>
<pre>
	$doc = new DOMDocument("4.01", "utf-8");
</pre>
<p>On crée ensuite un nouvel objet DOM, au constructeur duquel on passe deux paramètres : la version du document que l&#8217;on va utiliser (typiquement &laquo;&nbsp;1.0&#8243; pour du XML et &laquo;&nbsp;4.01&#8243; pour du HTML), et le jeu de caractères de ce document (charset).</p>
<pre>
	$contentPrefix = '&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"&gt;&lt;html&gt;&lt;head&gt;&lt;title&gt;required meta for utf-8 handling!&lt;/title&gt;&lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8"&gt;&lt;/head&gt;&lt;body&gt;';
	$contentSuffix = '&lt;/body&gt;&lt;/html&gt;';

	$doc->loadHTML($contentPrefix . $context . $contentSuffix);
</pre>
<p>On va ensuite ajouter un header au contexte passé. En effet, même si on a défini les valeurs <em>attendues</em> pour le document fourni, celles-ci seront effacées par le document si ces headers ne sont pas fournis. Et je peux vous assurer que lorsqu&#8217;on ne sait pas ça, il y a de quoi s&#8217;arracher les cheveux !! C&#8217;est sans doute le point le plus vicieux de la manipulation.<br />
On peut ensuite charger le contenu dans cet objet DOM.</p>
<pre>
	if(!is_array($value)){
		$value = array($value);
	}
</pre>
<p>Cette fonction prévoit de pouvoir ajouter plusieurs valeurs à un attribut donné. Si l&#8217;argument passé à la fonction est une chaine de caractères, on la transforme donc en tableau.</p>
<p>Je ne m&#8217;attarderai pas sur le reste de la fonction en elle même, qui est assez explicite.<br />
Notez simplement que l&#8217;on préserve les valeurs déjà existantes en les stockant dans un tableau, et que l&#8217;on vérifie avant d&#8217;ajouter la valeur de l&#8217;attribut si elle n&#8217;existe pas déjà.</p>
<pre>
	$output = mb_substr($doc->saveHTML(), 236, -16);
</pre>
<p>On va ensuite sauvegarder le résultat obtenu, et retirer les préfixe et suffixe que l&#8217;on avait ajouté grâce à une fonction gérant les caractères multibytes. En effet, un substr classique ne fonctionnerait pas convenablement avec certains caractères, puisque l&#8217;on est ici en UTF-8 qui utilise plusieurs octets pour stocker certains d&#8217;entre eux.</p>
<pre>
	if( $initialEncoding != 'UTF-8' ){
		mb_convert_encoding($output, $initialEncoding, 'UTF-8');
	}

	return $output;
</pre>
<p>Il est temps de remettre le résultat obtenu dans son jeu de caractère d&#8217;origine et de retourner le résultat.</p>
<p>Et&#8230; Voila! </p>

<div class="like">
<iframe src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fwww.lindicible.com%2Fblog%2F2009%2F10%2F18%2Fdomdocument-et-utf-8-un-probleme-de-charset-en-php%2F&amp;layout=standard&amp;show_faces=true&amp;width=450&amp;action=like&amp;font=&amp;colorscheme=light" scrolling="no" frameborder="0" allowTransparency="true" style="border:none; overflow:hidden; width:450px; height:62px; "></iframe>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.lindicible.com/blog/2009/10/18/domdocument-et-utf-8-un-probleme-de-charset-en-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

