Aetae,
смотря насколько по молодости. Сейчас можно даже на PHP
<?php
header("Content-Type: text/plain; charset=utf-8");
/* Тут наш грязненький код */
$str = <<<EOD
<p mso:crap="enabled" mso:foo="" mso:bar><img src="foo.gif" alt="" mso:shit="enabled">Всем при<strong></strong>вет!</p><br />
<p mso:crap="enabled" mso:foo="" mso:bar> Я — <u><i>очень</u></i> <strong>грязный</strong> кусок кода!
EOD
;
/* Ошибок будет много. Они нам особо не нужны */
libxml_use_internal_errors(true);
/* Создаем "грязный" документ */
$in_document = new DOMDocument();
/* Флаг: продолжаем парсинг в любом случае */
$in_document->recover = true;
/* Загружаем в "грязный" документ данные */
$in_document->loadHTML('<?xml encoding="utf-8" ?><body>' . $str . '</body>');
/* DOM - это только модель. Имплементаций ее достаточно много. Создаем одну такую. */
$dom = new DomImplementation();
/* К ней создаем доктайп. Старый добрый XHTML 1.0 Strict */
$doctype = $dom->createDocumentType("html", "-//W3C//DTD XHTML 1.0 Strict//EN", "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd");
/* Наконец, создаем "чистый" документ из имплементации с доктайпом */
$document = $dom->createDocument("http://www.w3.org/1999/xhtml", "html", $doctype);
/* Устанавливаем кодировку явным образом */
$document->encoding = "utf-8";
/* Импортируем из "грязного" документа body */
/* Вот тут, кстати, имеет значение тот самый ownerDocument из соседней темы */
$document->body = $document->documentElement->appendChild($document->importNode($in_document->getElementsByTagName("body")->item(0), true));
/* Создаем объект XPath для "чистого" документа */
$xpath = new DOMXpath($document);
/* Начинаем чистить: */
/* Убираем аттрибуты, начинающиеся с mso: */
foreach ($xpath->query('//attribute::*[starts-with(name(), "mso:")]') as $attr) $attr->parentNode->removeAttributeNode($attr);
/* Убираем все пустые элементы, которые не img, br или hr */
foreach ($xpath->query('//*[not(local-name() = "img" or local-name() = "br" or local-name() = "hr" or local-name() = "link")][not(./node())]') as $element) $element->parentNode->removeChild($element);
/* Убираем все br, которые лежат непосредственно в body */
foreach ($xpath->query('/*/body/br') as $element) $element->parentNode->removeChild($element);
/* . . . ну и так далее, до полного просветления */
/* Вывод с отступами */
$document->formatOutput = true;
/* Выводим */
echo $document->saveXML();
/***
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<p><img src="foo.gif" alt="" />Всем привет!</p>
<p> Я — <u><i>очень</i></u> <strong>грязный</strong> кусок кода!</p>
</body>
</html>
**/
?>