diff --git a/ecrire/exec/calendrier.php b/ecrire/exec/calendrier.php
index 1acc2f1f46d7a974faa99520da55ad4bd0040e16..6c4964e1c3e371da9109a51d10290f4c93ccc1de 100644
--- a/ecrire/exec/calendrier.php
+++ b/ecrire/exec/calendrier.php
@@ -88,8 +88,8 @@ function http_calendrier_aide_mess()
   return
    "\n<br /><br /><br />\n<font face='arial,helvetica,sans-serif' size='2'><table width='700'>\n<tr><th style='text-align: $spip_lang_left; font-weight: bold;'> " . _T('info_aide').
     "</th></tr><tr><td>$bleu\n"._T('info_symbole_bleu')."\n" .
-    "</td></tr><tr><td>$vert\n"._T('info_symbole_vert')."\n" .
-    "</th></tr><tr><td>$jaune\n"._T('info_symbole_jaune')."\n" .
+    "</td></tr><tr>><td>$vert\n"._T('info_symbole_vert')."\n" .
+    "</td></tr><tr><td>$jaune\n"._T('info_symbole_jaune')."\n" .
     "</td></tr>\n</table></font>";
  }
 
diff --git a/ecrire/exec/naviguer.php b/ecrire/exec/naviguer.php
index 17d2ef3d0c789797b74d0a3f5462d92d145f1761..cde4aec71a14712f5668ab3d70b910592d49797d 100644
--- a/ecrire/exec/naviguer.php
+++ b/ecrire/exec/naviguer.php
@@ -190,7 +190,7 @@ function raccourcis_naviguer($id_rubrique, $id_parent)
 	}
 	else {
 		if ($connect_statut == '0minirezo') {
-			$res .= "<p>"._T('info_creation_rubrique');
+			$res .= "<br />"._T('info_creation_rubrique');
 		}
 	}
 	
@@ -342,7 +342,7 @@ function contenu_naviguer($id_rubrique, $id_parent) {
 
 	if ($GLOBALS['meta']["activer_sites"] == 'oui') {
 		include_spip('inc/sites_voir');
-		$res .= '<p>' . afficher_sites('<b>' . _T('titre_sites_references_rubrique') . '</b>', array("FROM" => 'spip_syndic', 'WHERE' => "id_rubrique='$id_rubrique' AND statut!='refuse' AND statut != 'prop' AND syndication NOT IN ('off','sus')", 'ORDER BY' => 'nom_site')) . '</p>';
+		$res .= '<br />' . afficher_sites('<b>' . _T('titre_sites_references_rubrique') . '</b>', array("FROM" => 'spip_syndic', 'WHERE' => "id_rubrique='$id_rubrique' AND statut!='refuse' AND statut != 'prop' AND syndication NOT IN ('off','sus')", 'ORDER BY' => 'nom_site'));
 
 		if ($id_rubrique > 0
 		AND ($GLOBALS['meta']["proposer_sites"]> 0 OR acces_rubrique($id_rubrique))) {
diff --git a/ecrire/inc/sax.php b/ecrire/inc/sax.php
index 14750760d414ee9dde0e7d941b01583d4cf341a2..63ed73713dae5636a19630f279f6f4aba29640dd 100644
--- a/ecrire/inc/sax.php
+++ b/ecrire/inc/sax.php
@@ -13,6 +13,7 @@
 if (!defined("_ECRIRE_INC_VERSION")) return;
 
 include_spip('inc/filtres');
+include_spip('inc/charsets');
 
 // http://doc.spip.org/@PhraseurXML
 class PhraseurXML {
@@ -76,10 +77,11 @@ function finElement($parser, $name)
   $t = $contenu[$depth];
   $depth = substr($depth, 2);
   $t = ereg_replace("[\n\t ]+$", "\n" . $depth, $t);
-  // fusion <balise></balise> en <balise />
-  // ATTENTION, ne pas le faire s'il y a des attributs
-  // ca trompe completement les clients http 
-  if ($t || ($ouv !=$name))
+  // fusion <balise></balise> en <balise />.
+  // ATTENTION, en presence d'attributs ne le faire que si la DTD le dit:
+  // pour les autres, certains clients http croient que fusion ==> pas d'att
+  // en particulier pour les balises Script et A.
+  if ($t || (($ouv !=$name) AND $phraseur_xml->elements[$name][0] != 'EMPTY'))
     $res .= ($ouv ? ('<' . $ouv . '>') : '') . $t . "</" . $name . ">";
   else
     $res .= ($ouv ? ('<' . $ouv  . ' />') : ("</" .  $name . ">"));
@@ -151,21 +153,19 @@ function xml_parsestring($xml_parser, $data)
 	if (!xml_parse($xml_parser, $data, true)) {
 	  // ne pas commencer le message par un "<" (cf inc_sax_dist)
 	  $r = xml_error_string(xml_get_error_code($xml_parser)) .
-	    _L(" ligne ") .
-	    xml_get_current_line_number($xml_parser) .
-	    _L(" colonne ") .
-	    xml_get_current_column_number($xml_parser) .
+	    coordonnees_erreur($xml_parser) . '<br />' .
 	    (!$phraseur_xml->depth ? '' :
-	     ('<br />' .
+	     (
 	      _L("derni&egrave;re balise non referm&eacute;e&nbsp;: ") .
 	      "<tt>" .
 	      $phraseur_xml->ouvrant[$phraseur_xml->depth] .
 	      "</tt>" .
 	      _L(" ligne ") .
-	      $phraseur_xml->reperes[$phraseur_xml->depth]));
+	      $phraseur_xml->reperes[$phraseur_xml->depth] .
+	      '<br />' ));
 
 	} else if ($phraseur_xml->err)
-	  $r = join(', ', $phraseur_xml->err);
+	  $r = join('<br />', $phraseur_xml->err) . '<br />';
 	else $r = $phraseur_xml->res;
 
 	return $r;
@@ -182,8 +182,6 @@ function xml_parsestring($xml_parser, $data)
  var $err = array();
 }
 
-
-
 // http://doc.spip.org/@inc_sax_dist
 function inc_sax_dist($page, $apply=false) {
 	global $phraseur_xml, $xml_parser;
@@ -205,18 +203,29 @@ function inc_sax_dist($page, $apply=false) {
 		ob_end_clean();
 	}
 	if ($GLOBALS['xml_validation']
-	AND $validateur = charger_fonction('validateur', 'inc', true))
+	AND $validateur = charger_fonction('validateur', 'inc', true)) {
 		$validateur($page);
+		if (isset($phraseur_xml->entites['HTMLsymbol']))
+			$page = unicode2charset(html2unicode($page, true));
+	}
 	$res = $phraseur_xml->xml_parsestring($xml_parser, $page);
 	xml_parser_free($xml_parser);
+
 	if ($res[0] != '<')
 		$GLOBALS['xhtml_error'] = $res;
 	else
-	  $page = $res;
+		$page = $res;
 	return $page;
 }
 
-
+function coordonnees_erreur($xml_parser)
+{
+  return
+	_L(" ligne ") .
+	xml_get_current_line_number($xml_parser) .
+	_L(" colonne ") .
+	xml_get_current_column_number($xml_parser);
+}
 
 $GLOBALS['phraseur_xml'] = new PhraseurXML();
 // exemple d'appel en ligne de commande:
diff --git a/ecrire/inc/validateur.php b/ecrire/inc/validateur.php
index e9fb7f30319fea5cac79c76cf29efdb40ab85a9e..be132ac09ab913dfdf5831a81a9a83be0f15219c 100644
--- a/ecrire/inc/validateur.php
+++ b/ecrire/inc/validateur.php
@@ -41,13 +41,13 @@ function inc_validateur_dist($data)
 
 	$res = array();
 
-	// on ignore les entites publiques. A ameliorer a terme
-	if (preg_match_all('/<!ENTITY\s+%\s+([.\w]+)\s+"([^"]*)"\s*>/', $dtd, $r, PREG_SET_ORDER)) {
+	// les entites publiques sont declarees vides. A ameliorer a terme
+	if (preg_match_all('/<!ENTITY\s+%\s+([.\w]+)\s+(PUBLIC)?\s*"([^"]*)"\s*("[^"]*")?\s*>/', $dtd, $r, PREG_SET_ORDER)) {
 	  foreach($r as $m) {
-	    list(,$nom, $val) = $m;
-	    $res[$nom] =  expanserEntite($val, $res);
+	    list(,$nom, $type, $val) = $m;
+	    $res[$nom] =  $type ? '': expanserEntite($val, $res) ;
 	  }
-	}
+	} 
 	$phraseur_xml->entites = $res;
 
 	// reperer pour chaque noeud ses fils potentiels, sans repetitions,
@@ -57,7 +57,7 @@ function inc_validateur_dist($data)
 	  foreach($r as $m) {
 	    list(,$nom, $val) = $m;
 	    $val = expanserEntite($val, $phraseur_xml->entites);
-	    $val = array_values(preg_split('/\W+/', $val));
+	    $val = array_values(preg_split('/\W+/', $val,-1,PREG_SPLIT_NO_EMPTY));
 	    $res[$nom]= $val;
 	  }
 	}
@@ -101,12 +101,9 @@ function validerElement($parser, $name, $attrs)
 
 	if (!isset($phraseur_xml->elements[$name]))
 
-		$phraseur_xml->err[]= $name 
-		. '&nbsp;:&nbsp;'
-		. _L('balise inconnue ')
-		. _L('ligne ')
-		. xml_get_current_line_number($parser)
-		. '<br />';
+		$phraseur_xml->err[]= " <b>$name</b>"
+		. _L(' balise inconnue ')
+		.  coordonnees_erreur($parser);
 	else {
 	  $depth = $phraseur_xml->depth;
 	  $ouvrant = $phraseur_xml->ouvrant;
@@ -114,24 +111,21 @@ function validerElement($parser, $name, $attrs)
 	    if (preg_match('/^\s*(\w+)/', $ouvrant[$depth], $r)) {
 	      $pere = $r[1];
 	      if (!@in_array($name, $phraseur_xml->elements[$pere]))
-		$phraseur_xml->err[]= $name 
-		. '&nbsp;:&nbsp;'
-		. _L(" n'est pas un fils de <b>")
-		. $pere
-		. _L('</b> ligne ')
-		. xml_get_current_line_number($parser)
-		. '<br />';
+		$phraseur_xml->err[]= " <b>$name</b>" 
+		. _L(" n'est pas un fils de ")
+		. '<b>'
+		.  $pere
+		. '</b>'
+		.  coordonnees_erreur($parser);
 	    }
 	  }
 	  foreach ($phraseur_xml->attributs[$name] as $n => $v)
 	    { if (($v == '#REQUIRED') AND (!isset($attrs[$n])))
-		$phraseur_xml->err[]= $n 
+		$phraseur_xml->err[]= " <b>$n</b>"
 		. '&nbsp;:&nbsp;'
-		. _L(" attribut obligatoire mais absent dans <b>")
-		. $name
-		. _L('</b> ligne ')
-		. xml_get_current_line_number($parser)
-		. '<br />';
+                . _L(" attribut obligatoire mais absent dans ")
+                . "<b>$name</b>"
+		.  coordonnees_erreur($parser);
 	    }
 	}
 }
@@ -145,13 +139,10 @@ function validerAttribut($parser, $name, $val, $bal)
 	if ($a = $phraseur_xml->attributs[$bal] 
 	    AND !isset($a[$name]))
 
-		$phraseur_xml->err[]= $name 
-		. '&nbsp;:&nbsp;'
-		. _L('attribut inconnu de ')
-		. $bal 
-		. _L(' ligne ')
-		. xml_get_current_line_number($parser)
-		. '<br />';
+		$phraseur_xml->err[]= " <b>$name</b>"
+		. _L(' attribut inconnu de ')
+		. "<b>$bal</b>"
+		.  coordonnees_erreur($parser);
 }
 
 
diff --git a/ecrire/public/debug.php b/ecrire/public/debug.php
index 917ccc28c71b6a7f008aa8b3f9c9cad25d0dcf7f..624b1ab126717dbfb32b21b2bba488fc55d7c6f4 100644
--- a/ecrire/public/debug.php
+++ b/ecrire/public/debug.php
@@ -437,6 +437,7 @@ function debug_dumpfile ($texte, $fonc, $type) {
 				$err = _T('impossible');
 			elseif ($err === true)
 			  $err = _T('correcte');
+			else $err = ": $err";
 		}
 
 		echo "<div id=\"debug_boucle\"><fieldset><legend>",
@@ -506,11 +507,24 @@ function debug_fin()
 // http://doc.spip.org/@emboite_texte
 function emboite_texte($texte, $fonc='',$self='')
 {
+ 
 	if (!$texte)
 		return array(ancre_texte($texte, array('','')), false);
-	elseif (!ereg("^[[:space:]]*([^<][^0-9]*)([0-9]*)(.*[^0-9])([0-9]*)$",
-		     $GLOBALS['xhtml_error'],
-		     $r))
+	elseif (preg_match_all(",([^0-9]* )([0-9]+)(.*?<br />),",
+				$GLOBALS['xhtml_error'],
+				$regs,
+				PREG_SET_ORDER)) {
+		$err = '';
+		$fautifs = array();
+		foreach($regs as $r) {
+			$err .= $r[1] .
+			  "<a href='#L" . $r[2] . "'>$r[2]</a>$r[3]";
+			$fautifs[]=$r[2];
+		}
+		return array(ancre_texte($texte, $fautifs), $err);
+	} elseif (!ereg("^[[:space:]]*([^<][^0-9]*)([0-9]*)(.*[^0-9])([0-9]*)$",
+                     $GLOBALS['xhtml_error'],
+                     $r))
 		return array(ancre_texte($texte, array('', '')), true);
 	else {
 		$fermant = $r[2];
@@ -519,11 +533,10 @@ function emboite_texte($texte, $fonc='',$self='')
 		  $rf = reference_boucle_debug($fermant, $fonc, $self);
 		  $ro = reference_boucle_debug($ouvrant, $fonc, $self);
 		} else $rf = $ro = '';
-		$err = ": " . $r[1] .
+		$err = $r[1] .
 		  "<a href='#L" . $r[2] . "'>$r[2]</a>$rf" .
 		  $r[3] ."<a href='#L" . $r[4] . "'>$r[4]</a>$ro";
 		return array(ancre_texte($texte, array($ouvrant, $fermant)), $err);
 	}
 }
-
 ?>