WP_HTML_Tag_Processor : voilà le nom un peu austère de la classe apportée par WordPress 6.2 pour résoudre un problème que tout développeur de thème a rencontré au moins une fois — modifier un fragment de HTML déjà généré sans passer par une expression régulière hasardeuse ni reconstruire tout le rendu depuis zéro.
Le cas qui suit est concret : un vieux template part hérité d’une migration porte un attribut data-legacy-widget="true" sur sa balise <nav>, ajouté par un ancien système de widgets et devenu totalement inutile depuis le passage au thème de blocs. Cet attribut traîne dans le rendu final, pollue le HTML et déclenche même un avertissement dans un outil de validation d’accessibilité. Il faut le retirer, proprement, sans toucher au reste de la structure.
Pourquoi une expression régulière est une mauvaise idée
La tentation classique consiste à intercepter le HTML final avec preg_replace() pour supprimer la chaîne data-legacy-widget="true". Cela fonctionne, jusqu’au jour où l’attribut change d’ordre dans la balise, où des espaces supplémentaires apparaissent, ou où un attribut du même nom existe ailleurs dans un contexte différent. Une expression régulière ne comprend pas la structure HTML, elle manipule du texte brut : elle est donc fragile par construction.
WP_HTML_Tag_Processor résout ce problème en analysant réellement la structure des balises, sans construire d’arbre DOM complet (ce qui serait coûteux), mais en permettant de naviguer balise par balise et d’agir sur les attributs de façon fiable.
Cibler la balise et retirer l’attribut

La classe s’utilise en trois temps : on l’instancie avec le HTML à traiter, on avance jusqu’à la balise recherchée avec next_tag(), puis on agit sur ses attributs avec remove_attribute() ou set_attribute(). Voici le filtre appliqué au rendu du template part concerné :
add_filter( 'render_block_core/template-part', function( $contenu, $bloc ) {
if ( 'header' !== ( $bloc['attrs']['slug'] ?? '' ) ) {
return $contenu;
}
$processeur = new WP_HTML_Tag_Processor( $contenu );
while ( $processeur->next_tag( 'nav' ) ) {
if ( $processeur->get_attribute( 'data-legacy-widget' ) ) {
$processeur->remove_attribute( 'data-legacy-widget' );
}
}
return $processeur->get_updated_html();
}, 10, 2 );
Le point important est la boucle while : elle permet de traiter toutes les balises <nav> du fragment, au cas où le template part en contiendrait plusieurs imbriquées (un menu principal et un menu secondaire, par exemple). La méthode get_attribute() évite de modifier une balise qui ne porte pas l’attribut visé, ce qui rend le filtre sans effet de bord sur les balises propres.
Le piège du filtre générique
Un développeur pressé pourrait être tenté d’accrocher ce traitement sur render_block directement, sans condition de slug. C’est une erreur : ce hook s’exécute pour chaque bloc rendu sur la page, ce qui multiplie inutilement le coût de l’analyse HTML. Mieux vaut cibler précisément le hook dynamique du bloc concerné, comme render_block_core/template-part, et vérifier l’attribut slug avant d’instancier le processeur.
Vérifier le résultat sans casser le cache
Une fois le filtre en place, il faut vider le cache de rendu si le thème ou une extension de performance met en cache les fragments HTML des template parts. Sans cette précaution, l’ancien attribut continue d’apparaître dans la version mise en cache et le correctif semble ne pas fonctionner alors qu’il est parfaitement actif.
- Vérifier le rendu en navigation privée pour écarter tout cache navigateur.
- Purger explicitement le cache de fragments si une extension de performance est active.
- Contrôler le résultat avec l’inspecteur du navigateur plutôt qu’en relisant le code source brut, pour être certain de voir le HTML réellement servi.
Aller plus loin : renommer plutôt que supprimer
Dans certains cas, l’attribut hérité sert encore de point d’ancrage à une feuille de style tierce qu’on ne maîtrise pas totalement. Plutôt que de le supprimer, set_attribute() permet de le renommer en conservant sa valeur, le temps d’une transition en douceur :
if ( $processeur->get_attribute( 'data-legacy-widget' ) ) {
$processeur->set_attribute( 'data-migre', 'true' );
$processeur->remove_attribute( 'data-legacy-widget' );
}
Un correctif de ce type doit toujours être daté et commenté dans le code : dans six mois, personne ne se souviendra pourquoi cet attribut a disparu du template part.
En résumé
WP_HTML_Tag_Processor transforme un nettoyage de HTML hérité, autrefois source d’expressions régulières bancales, en une opération fiable et lisible. Pour un attribut isolé sur un template part, quelques lignes suffisent, et le résultat reste robuste face aux évolutions futures de la structure du gabarit.