CVE-2023-32070: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: XWiki Platform is a generic wiki platform. Prior to version 14.6-rc-1, HTML rendering didn't check for dangerous attributes/attribute values. This allowed cross-site scripting (XSS) attacks via attributes and link URLs, e.g., supported in XWiki syntax. This has been patched in XWiki 14.6-rc-1. There are no known workarounds apart from upgrading to a fixed version.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 6.1
Published: 2023-05-10T18:15Z
Repository: https://github.com/xwiki/xwiki-rendering
Language: Other
Files changed: xwiki-rendering-integration-tests/src/test/resources/simple/escape/escape15.test, xwiki-rendering-integration-tests/src/test/resources/simple/group/group9.test, xwiki-rendering-integration-tests/src/test/resources/simple/horizontalline/horizontalline5.test, xwiki-rendering-integration-tests/src/test/resources/simple/italic/italic8.test, xwiki-rendering-integration-tests/src/test/resources/simple/list/definitionlist7.test, xwiki-rendering-integration-tests/src/test/resources/simple/list/list13.test, xwiki-rendering-integration-tests/src/test/resources/simple/list/list8.test, xwiki-rendering-integration-tests/src/test/resources/simple/macros/macro10.test, xwiki-rendering-integration-tests/src/test/resources/simple/paragraph/paragraph6.test, xwiki-rendering-integration-tests/src/test/resources/simple/quote/quote3.test, xwiki-rendering-integration-tests/src/test/resources/simple/section/section6.test, xwiki-rendering-integration-tests/src/test/resources/simple/strikedout/strikedout4.test, xwiki-rendering-integration-tests/src/test/resources/simple/subscript/subscript2.test, xwiki-rendering-integration-tests/src/test/resources/simple/superscript/superscript2.test, xwiki-rendering-integration-tests/src/test/resources/simple/table/table3.test, xwiki-rendering-integration-tests/src/test/resources/simple/verbatim/verbatim6.test, xwiki-rendering-integration-tests/src/test/resources/simple/verbatim/verbatim7.test, xwiki-rendering-integration-tests/src/test/resources/wiki/image/image1.test, xwiki-rendering-integration-tests/src/test/resources/wiki/image/image12.test, xwiki-rendering-integration-tests/src/test/resources/wiki/image/image8.test, xwiki-rendering-integration-tests/src/test/resources/wiki/image/image9.test, xwiki-rendering-integration-tests/src/test/resources/wiki/link/links14.test, xwiki-rendering-integration-tests/src/test/resources/wiki/link/links15.test, xwiki-rendering-integration-tests/src/test/resources/wiki/link/links19.test, xwiki-rendering-integration-tests/src/test/resources/wiki/link/links2.test, xwiki-rendering-integration-tests/src/test/resources/wiki/link/links8.test, xwiki-rendering-macros/xwiki-rendering-macro-html/src/main/java/org/xwiki/rendering/internal/macro/html/HTMLMacroXHTMLRenderer.java, xwiki-rendering-macros/xwiki-rendering-macro-html/src/main/java/org/xwiki/rendering/internal/macro/html/renderers/annotatedhtml5/HTMLMacroAnnotatedHTML5Renderer.java, xwiki-rendering-macros/xwiki-rendering-macro-html/src/main/java/org/xwiki/rendering/internal/macro/html/renderers/annotatedxhtml/HTMLMacroAnnotatedXHTMLRenderer.java, xwiki-rendering-macros/xwiki-rendering-macro-html/src/main/java/org/xwiki/rendering/internal/macro/html/renderers/html5/HTMLMacroHTML5Renderer.java, xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedhtml5/src/main/java/org/xwiki/rendering/internal/renderer/html5/AnnotatedHTML5ChainingRenderer.java, xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedhtml5/src/main/java/org/xwiki/rendering/internal/renderer/html5/AnnotatedHTML5Renderer.java, xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedhtml5/src/test/resources/annotatedhtml50/simple/monospace/monospace2.out.txt, xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedxhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLChainingRenderer.java, xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedxhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLRenderer.java, xwiki-rendering-syntaxes/xwiki-rendering-syntax-html5/src/main/java/org/xwiki/rendering/internal/renderer/html5/HTML5ChainingRenderer.java, xwiki-rendering-syntaxes/xwiki-rendering-syntax-html5/src/main/java/org/xwiki/rendering/internal/renderer/html5/HTML5Renderer.java, xwiki-rendering-syntaxes/xwiki-rendering-syntax-html5/src/test/java/org/xwiki/rendering/internal/html5/HTML5ChainingRendererTest.java, xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/main/java/org/xwiki/rendering/internal/parser/xhtml/wikimodel/XHTMLXWikiGeneratorListener.java, xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLChainingRenderer.java, xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLRenderer.java, xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLChainingRendererTest.java, xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/resources/xhtml10/simple/monospace/monospace2.inout.txt, xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/resources/xhtml10/specific/bold/bold4.test, xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/resources/xhtml10/specific/encoding/encoding1.test, xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/resources/xhtml10/specific/group/group1.test, xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml5/src/test/resources/xhtml5/simple/monospace/monospace2.inout.txt, xwiki-rendering-xml/src/main/java/org/xwiki/rendering/renderer/printer/XHTMLWikiPrinter.java
Commit date: 2022-06-30 16:47:21 +0200
Commit message: XRENDERING-663: Restrict allowed attributes in HTML rendering

* Change HTML renderers to only print allowed attributes and elements.
* Add prefix to forbidden attributes to preserve them in XWiki syntax.
* Adapt tests to expect that invalid attributes get a prefix.

Diff: diff --git a/xwiki-rendering-integration-tests/src/test/resources/simple/escape/escape15.test b/xwiki-rendering-integration-tests/src/test/resources/simple/escape/escape15.test
index be4017ec..3dc50f45 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/simple/escape/escape15.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/simple/escape/escape15.test
@@ -18,18 +18,18 @@ endLink [Typed = [false] Type = [url] Reference = [refe||rence]] [false] [[param
 endParagraph
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<p><span class="wikiexternallink"><a param="value" href="refe||rence">lab&gt;&gt;el~</a></span></p>
+<p><span class="wikiexternallink"><a data-xwiki-translated-attribute-param="value" href="refe||rence">lab&gt;&gt;el~</a></span></p>
 .#-----------------------------------------------------
 .expect|annotatedxhtml/1.0
 .#-----------------------------------------------------
-<p><!--startwikilink:false|-|url|-|refe||rence--><span class="wikiexternallink"><a param="value" href="refe||rence">lab&gt;&gt;el~</a></span><!--stopwikilink--></p>
+<p><!--startwikilink:false|-|url|-|refe||rence--><span class="wikiexternallink"><a data-xwiki-translated-attribute-param="value" href="refe||rence">lab&gt;&gt;el~</a></span><!--stopwikilink--></p>
 .#-----------------------------------------------------
 .expect|xwiki/2.0
 .#-----------------------------------------------------
 [[lab~>~>el~~~~>>refe~|~|rence||param="value"]]
 .#-----------------------------------------------------
 .input|xhtml/1.0
 .#-----------------------------------------------------
-<p><!--startwikilink:false|-|url|-|refe||rence--><span class="wikiexternallink"><a param="value" href="refe||rence">lab&gt;&gt;el~</a></span><!--stopwikilink--></p>
\ No newline at end of file
+<p><!--startwikilink:false|-|url|-|refe||rence--><span class="wikiexternallink"><a data-xwiki-translated-attribute-param="value" href="refe||rence">lab&gt;&gt;el~</a></span><!--stopwikilink--></p>
\ No newline at end of file
diff --git a/xwiki-rendering-integration-tests/src/test/resources/simple/group/group9.test b/xwiki-rendering-integration-tests/src/test/resources/simple/group/group9.test
index 4558bcc3..4f4a28bf 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/simple/group/group9.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/simple/group/group9.test
@@ -27,11 +27,11 @@ endParagraph
 endGroup [[param]=[value]]
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<div param="value"><p>some text</p></div><div param="value"><p>some text</p></div>
+<div data-xwiki-translated-attribute-param="value"><p>some text</p></div><div data-xwiki-translated-attribute-param="value"><p>some text</p></div>
 .#-----------------------------------------------------
 .expect|xwiki/2.0
 .#-----------------------------------------------------
 (% param="value" %)
 (((
@@ -43,6 +43,6 @@ some text
 some text
 )))
 .#-----------------------------------------------------
 .input|xhtml/1.0
 .#-----------------------------------------------------
-<div param="value"><p>some text</p></div><div param="value"><p>some text</p></div>
\ No newline at end of file
+<div data-xwiki-translated-attribute-param="value"><p>some text</p></div><div data-xwiki-translated-attribute-param="value"><p>some text</p></div>
\ No newline at end of file
diff --git a/xwiki-rendering-integration-tests/src/test/resources/simple/horizontalline/horizontalline5.test b/xwiki-rendering-integration-tests/src/test/resources/simple/horizontalline/horizontalline5.test
index 4e961580..77926059 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/simple/horizontalline/horizontalline5.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/simple/horizontalline/horizontalline5.test
@@ -10,15 +10,15 @@ beginDocument
 onHorizontalLine [[param]=[value]]
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<hr param="value"/>
+<hr data-xwiki-translated-attribute-param="value"/>
 .#-----------------------------------------------------
 .expect|xwiki/2.0
 .#-----------------------------------------------------
 (% param="value" %)
 ----
 .#-----------------------------------------------------
 .input|xhtml/1.0
 .#-----------------------------------------------------
-<html><hr param="value"/></html>
\ No newline at end of file
+<html><hr data-xwiki-translated-attribute-param="value"/></html>
\ No newline at end of file
diff --git a/xwiki-rendering-integration-tests/src/test/resources/simple/italic/italic8.test b/xwiki-rendering-integration-tests/src/test/resources/simple/italic/italic8.test
index ed9d6b98..c54995c5 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/simple/italic/italic8.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/simple/italic/italic8.test
@@ -14,10 +14,10 @@ endFormat [ITALIC] [[a]=[b]]
 endParagraph
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<p><em><span a="b">something</span></em></p>
+<p><em><span data-xwiki-translated-attribute-a="b">something</span></em></p>
 .#-----------------------------------------------------
 .expect|xwiki/2.0
 .#-----------------------------------------------------
 (% a="b" %)//something//
\ No newline at end of file
diff --git a/xwiki-rendering-integration-tests/src/test/resources/simple/list/definitionlist7.test b/xwiki-rendering-integration-tests/src/test/resources/simple/list/definitionlist7.test
index 6a29ba11..49376267 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/simple/list/definitionlist7.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/simple/list/definitionlist7.test
@@ -19,21 +19,21 @@ endDefinitionDescription
 endDefinitionList [[param]=[value]]
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<dl param="value"><dt>title</dt><dd>definition</dd></dl>
+<dl data-xwiki-translated-attribute-param="value"><dt>title</dt><dd>definition</dd></dl>
 .#-----------------------------------------------------
 .expect|xwiki/2.0
 .#-----------------------------------------------------
 (% param="value" %)
 ; title
 : definition
 .#-----------------------------------------------------
 .input|xhtml/1.0
 .#-----------------------------------------------------
-<dl param="value"><dt>title</dt><dd>definition</dd></dl>
+<dl data-xwiki-translated-attribute-param="value"><dt>title</dt><dd>definition</dd></dl>
 .#-----------------------------------------------------
 .expect|plain/1.0
 .#-----------------------------------------------------
 title
 definition
\ No newline at end of file
diff --git a/xwiki-rendering-integration-tests/src/test/resources/simple/list/list13.test b/xwiki-rendering-integration-tests/src/test/resources/simple/list/list13.test
index 0c6261ac..501c1a98 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/simple/list/list13.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/simple/list/list13.test
@@ -40,11 +40,11 @@ endListItem
 endList [BULLETED] [[param]=[value]]
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<ul param="value"><li>item 1<ul param2="value2"><li>item 1.1<ul><li>item 1.1.1</li></ul></li></ul></li></ul>
+<ul data-xwiki-translated-attribute-param="value"><li>item 1<ul data-xwiki-translated-attribute-param2="value2"><li>item 1.1<ul><li>item 1.1.1</li></ul></li></ul></li></ul>
 .#-----------------------------------------------------
 .expect|xwiki/2.0
 .#-----------------------------------------------------
 (% param="value" %)
 * item 1
@@ -52,6 +52,6 @@ endDocument
 ** item 1.1
 *** item 1.1.1
 .#-----------------------------------------------------
 .input|xhtml/1.0
 .#-----------------------------------------------------
-<ul param="value"><li>item 1<ul param2="value2"><li>item 1.1<ul><li>item 1.1.1</li></ul></li></ul></li></ul>
\ No newline at end of file
+<ul data-xwiki-translated-attribute-param="value"><li>item 1<ul data-xwiki-translated-attribute-param2="value2"><li>item 1.1<ul><li>item 1.1.1</li></ul></li></ul></li></ul>
\ No newline at end of file
diff --git a/xwiki-rendering-integration-tests/src/test/resources/simple/list/list8.test b/xwiki-rendering-integration-tests/src/test/resources/simple/list/list8.test
index 12ea8688..fbf15aa0 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/simple/list/list8.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/simple/list/list8.test
@@ -14,15 +14,15 @@ endListItem
 endList [BULLETED] [[param1]=[value1][param2]=[value2]]
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<ul param1="value1" param2="value2"><li>item</li></ul>
+<ul data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2"><li>item</li></ul>
 .#-----------------------------------------------------
 .expect|xwiki/2.0
 .#-----------------------------------------------------
 (% param1="value1" param2="value2" %)
 * item
 .#-----------------------------------------------------
 .input|xhtml/1.0
 .#-----------------------------------------------------
-<html><ul param1="value1" param2="value2"><li>item</li></ul></html>
\ No newline at end of file
+<html><ul data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2"><li>item</li></ul></html>
\ No newline at end of file
diff --git a/xwiki-rendering-integration-tests/src/test/resources/simple/macros/macro10.test b/xwiki-rendering-integration-tests/src/test/resources/simple/macros/macro10.test
index e06d1aa7..dc6594bc 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/simple/macros/macro10.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/simple/macros/macro10.test
@@ -42,14 +42,14 @@ endMacroMarkerInline [testformatmacro] []
 endParagraph
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<span param="value">formatmacro2</span><p><span a="b"><span param="value">formatmacro3</span> text</span></p><p><span a="b">text</span><span param="value">formatmacro4</span></p>
+<span data-xwiki-translated-attribute-param="value">formatmacro2</span><p><span data-xwiki-translated-attribute-a="b"><span data-xwiki-translated-attribute-param="value">formatmacro3</span> text</span></p><p><span data-xwiki-translated-attribute-a="b">text</span><span data-xwiki-translated-attribute-param="value">formatmacro4</span></p>
 .#-----------------------------------------------------
 .expect|annotatedxhtml/1.0
 .#-----------------------------------------------------
-<!--startmacro:testformatmacro|-|--><span param="value">formatmacro2</span><!--stopmacro--><p><span a="b"><!--startmacro:testformatmacro|-|--><span param="value">formatmacro3</span><!--stopmacro--> text</span></p><p><span a="b">text</span><!--startmacro:testformatmacro|-|--><span param="value">formatmacro4</span><!--stopmacro--></p>
+<!--startmacro:testformatmacro|-|--><span data-xwiki-translated-attribute-param="value">formatmacro2</span><!--stopmacro--><p><span data-xwiki-translated-attribute-a="b"><!--startmacro:testformatmacro|-|--><span data-xwiki-translated-attribute-param="value">formatmacro3</span><!--stopmacro--> text</span></p><p><span data-xwiki-translated-attribute-a="b">text</span><!--startmacro:testformatmacro|-|--><span data-xwiki-translated-attribute-param="value">formatmacro4</span><!--stopmacro--></p>
 .#-----------------------------------------------------
 .input|xhtml/1.0
 .#-----------------------------------------------------
-<!--startmacro:testformatmacro|-|--><span param="value">formatmacro2</span><!--stopmacro--><p><span a="b"><!--startmacro:testformatmacro|-|--><span param="value">formatmacro3</span><!--stopmacro--> text</span></p><p><span a="b">text</span><!--startmacro:testformatmacro|-|--><span param="value">formatmacro4</span><!--stopmacro--></p>
\ No newline at end of file
+<!--startmacro:testformatmacro|-|--><span data-xwiki-translated-attribute-param="value">formatmacro2</span><!--stopmacro--><p><span data-xwiki-translated-attribute-a="b"><!--startmacro:testformatmacro|-|--><span data-xwiki-translated-attribute-param="value">formatmacro3</span><!--stopmacro--> text</span></p><p><span data-xwiki-translated-attribute-a="b">text</span><!--startmacro:testformatmacro|-|--><span data-xwiki-translated-attribute-param="value">formatmacro4</span><!--stopmacro--></p>
\ No newline at end of file
diff --git a/xwiki-rendering-integration-tests/src/test/resources/simple/paragraph/paragraph6.test b/xwiki-rendering-integration-tests/src/test/resources/simple/paragraph/paragraph6.test
index 4e40072a..e94b7a37 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/simple/paragraph/paragraph6.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/simple/paragraph/paragraph6.test
@@ -103,11 +103,11 @@ endFormat [BOLD] [[param2]=[value2]]
 endParagraph
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<p param1="value1" param2="value2"><span param3="value3">hello</span> world</p><p><span param4="valueA">hello&nbsp;</span><span param4="valueB">world</span></p><p><strong><span param5="value4">hello</span></strong><span param5="value4">&nbsp;world</span></p><p><span param6="valueA">hello&nbsp;</span><span param7="valueB">world</span></p><p>before<span param="value">x</span><strong>y</strong>after</p><p>12<strong>34<span param="value">56</span>78</strong>90</p><p><span param="value">1<em>2</em></span><em>3</em></p><p><strong><span param1="value1">1</span></strong><strong><span param2="value2">2</span></strong></p>
+<p data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2"><span data-xwiki-translated-attribute-param3="value3">hello</span> world</p><p><span data-xwiki-translated-attribute-param4="valueA">hello&nbsp;</span><span data-xwiki-translated-attribute-param4="valueB">world</span></p><p><strong><span data-xwiki-translated-attribute-param5="value4">hello</span></strong><span data-xwiki-translated-attribute-param5="value4">&nbsp;world</span></p><p><span data-xwiki-translated-attribute-param6="valueA">hello&nbsp;</span><span data-xwiki-translated-attribute-param7="valueB">world</span></p><p>before<span data-xwiki-translated-attribute-param="value">x</span><strong>y</strong>after</p><p>12<strong>34<span data-xwiki-translated-attribute-param="value">56</span>78</strong>90</p><p><span data-xwiki-translated-attribute-param="value">1<em>2</em></span><em>3</em></p><p><strong><span data-xwiki-translated-attribute-param1="value1">1</span></strong><strong><span data-xwiki-translated-attribute-param2="value2">2</span></strong></p>
 .#-----------------------------------------------------
 .expect|xwiki/2.0
 .#-----------------------------------------------------
 (% param1="value1" param2="value2" %)
 (% param3="value3" %)hello(%%) world
diff --git a/xwiki-rendering-integration-tests/src/test/resources/simple/quote/quote3.test b/xwiki-rendering-integration-tests/src/test/resources/simple/quote/quote3.test
index e1e30972..813066e1 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/simple/quote/quote3.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/simple/quote/quote3.test
@@ -14,15 +14,15 @@ endQuotationLine
 endQuotation [[param1]=[value1][param2]=[value2]]
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<blockquote param1="value1" param2="value2"><p>line</p></blockquote>
+<blockquote data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2"><p>line</p></blockquote>
 .#-----------------------------------------------------
 .expect|xwiki/2.0
 .#-----------------------------------------------------
 (% param1="value1" param2="value2" %)
 >line
 .#-----------------------------------------------------
 .input|xhtml/1.0
 .#-----------------------------------------------------
-<blockquote param1="value1" param2="value2"><p>line</p></blockquote>
\ No newline at end of file
+<blockquote data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2"><p>line</p></blockquote>
\ No newline at end of file
diff --git a/xwiki-rendering-integration-tests/src/test/resources/simple/section/section6.test b/xwiki-rendering-integration-tests/src/test/resources/simple/section/section6.test
index 68eb843c..322323d9 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/simple/section/section6.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/simple/section/section6.test
@@ -15,15 +15,15 @@ endHeader [1, Hheader] [[param]=[value]]
 endSection
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<h1 id="Hheader" class="wikigeneratedid" param="value"><span>header</span></h1>
+<h1 id="Hheader" class="wikigeneratedid" data-xwiki-translated-attribute-param="value"><span>header</span></h1>
 .#-----------------------------------------------------
 .expect|xwiki/2.0
 .#-----------------------------------------------------
 (% param="value" %)
 = header =
 .#-----------------------------------------------------
 .input|xhtml/1.0
 .#-----------------------------------------------------
-<html><h1 id="Hheader" class="wikigeneratedid" param="value"><span>header</span></h1></html>
\ No newline at end of file
+<html><h1 id="Hheader" class="wikigeneratedid" data-xwiki-translated-attribute-param="value"><span>header</span></h1></html>
\ No newline at end of file
diff --git a/xwiki-rendering-integration-tests/src/test/resources/simple/strikedout/strikedout4.test b/xwiki-rendering-integration-tests/src/test/resources/simple/strikedout/strikedout4.test
index f32eff38..5f0e7819 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/simple/strikedout/strikedout4.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/simple/strikedout/strikedout4.test
@@ -14,10 +14,10 @@ endFormat [STRIKEDOUT] [[a]=[b]]
 endParagraph
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<p><del><span a="b">something</span></del></p>
+<p><del><span data-xwiki-translated-attribute-a="b">something</span></del></p>
 .#-----------------------------------------------------
 .expect|xwiki/2.0
 .#-----------------------------------------------------
 (% a="b" %)--something--
\ No newline at end of file
diff --git a/xwiki-rendering-integration-tests/src/test/resources/simple/subscript/subscript2.test b/xwiki-rendering-integration-tests/src/test/resources/simple/subscript/subscript2.test
index 9793fd4e..32997b8c 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/simple/subscript/subscript2.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/simple/subscript/subscript2.test
@@ -1,10 +1,10 @@
 .#-----------------------------------------------------
 .input|xhtml/1.0
 .# Verify that SUB tag parameters are recognized.
 .#-----------------------------------------------------
-<html><p><sub a="b">something</sub></p></html>
+<html><p><sub data-xwiki-translated-attribute-a="b">something</sub></p></html>
 .#-----------------------------------------------------
 .expect|event/1.0
 .#-----------------------------------------------------
 beginDocument
 beginParagraph
@@ -14,10 +14,10 @@ endFormat [SUBSCRIPT] [[a]=[b]]
 endParagraph
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<p><sub><span a="b">something</span></sub></p>
+<p><sub><span data-xwiki-translated-attribute-a="b">something</span></sub></p>
 .#-----------------------------------------------------
 .expect|xwiki/2.0
 .#-----------------------------------------------------
 (% a="b" %),,something,,
\ No newline at end of file
diff --git a/xwiki-rendering-integration-tests/src/test/resources/simple/superscript/superscript2.test b/xwiki-rendering-integration-tests/src/test/resources/simple/superscript/superscript2.test
index b22a5104..bac160af 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/simple/superscript/superscript2.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/simple/superscript/superscript2.test
@@ -1,10 +1,10 @@
 .#-----------------------------------------------------
 .input|xhtml/1.0
 .# Verify that SUP tag parameters are recognized.
 .#-----------------------------------------------------
-<html><p><sup a="b">something</sup></p></html>
+<html><p><sup data-xwiki-translated-attribute-a="b">something</sup></p></html>
 .#-----------------------------------------------------
 .expect|event/1.0
 .#-----------------------------------------------------
 beginDocument
 beginParagraph
@@ -14,10 +14,10 @@ endFormat [SUPERSCRIPT] [[a]=[b]]
 endParagraph
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<p><sup><span a="b">something</span></sup></p>
+<p><sup><span data-xwiki-translated-attribute-a="b">something</span></sup></p>
 .#-----------------------------------------------------
 .expect|xwiki/2.0
 .#-----------------------------------------------------
 (% a="b" %)^^something^^
\ No newline at end of file
diff --git a/xwiki-rendering-integration-tests/src/test/resources/simple/table/table3.test b/xwiki-rendering-integration-tests/src/test/resources/simple/table/table3.test
index 52864bde..e7093764 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/simple/table/table3.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/simple/table/table3.test
@@ -41,11 +41,11 @@ endTableRow [[c]=[d]]
 endTable [[a]=[b]]
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<table a="b"><tr c="d"><th e="f" scope="col"><span g="h">cell1</span></th><td i="j"><span k="l">cell2</span></td></tr></table><table a="b"><tr c="d"><th e="f" scope="col"><span g="h">cell1</span></th><td i="j"><span k="l">cell2</span></td></tr></table>
+<table data-xwiki-translated-attribute-a="b"><tr data-xwiki-translated-attribute-c="d"><th data-xwiki-translated-attribute-e="f" scope="col"><span data-xwiki-translated-attribute-g="h">cell1</span></th><td data-xwiki-translated-attribute-i="j"><span k="l">cell2</span></td></tr></table><table data-xwiki-translated-attribute-a="b"><tr data-xwiki-translated-attribute-c="d"><th data-xwiki-translated-attribute-e="f" scope="col"><span data-xwiki-translated-attribute-g="h">cell1</span></th><td data-xwiki-translated-attribute-i="j"><span k="l">cell2</span></td></tr></table>
 .#-----------------------------------------------------
 .expect|xwiki/2.0
 .#-----------------------------------------------------
 (% a="b" %)
 (% c="d" %)|=(% e="f" %)(% g="h" %)cell1|(% i="j" %)(% k="l" %)cell2
@@ -53,6 +53,6 @@ endDocument
 (% a="b" %)
 (% c="d" %)|=(% e="f" %)(% g="h" %)cell1|(% i="j" %)(% k="l" %)cell2
 .#-----------------------------------------------------
 .input|xhtml/1.0
 .#-----------------------------------------------------
-<table a="b"><tr c="d"><th e="f" scope="col"><span g="h">cell1</span></th><td i="j"><span k="l">cell2</span></td></tr></table><table a="b"><tr c="d"><th e="f" scope="col"><span g="h">cell1</span></th><td i="j"><span k="l">cell2</span></td></tr></table>
\ No newline at end of file
+<table data-xwiki-translated-attribute-a="b"><tr data-xwiki-translated-attribute-c="d"><th data-xwiki-translated-attribute-e="f" scope="col"><span data-xwiki-translated-attribute-g="h">cell1</span></th><td data-xwiki-translated-attribute-i="j"><span k="l">cell2</span></td></tr></table><table data-xwiki-translated-attribute-a="b"><tr data-xwiki-translated-attribute-c="d"><th data-xwiki-translated-attribute-e="f" scope="col"><span data-xwiki-translated-attribute-g="h">cell1</span></th><td data-xwiki-translated-attribute-i="j"><span k="l">cell2</span></td></tr></table>
\ No newline at end of file
diff --git a/xwiki-rendering-integration-tests/src/test/resources/simple/verbatim/verbatim6.test b/xwiki-rendering-integration-tests/src/test/resources/simple/verbatim/verbatim6.test
index d50322ec..936819a6 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/simple/verbatim/verbatim6.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/simple/verbatim/verbatim6.test
@@ -10,15 +10,15 @@ beginDocument
 onVerbatim [abc] [false] [[param]=[value]]
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<pre param="value">abc</pre>
+<pre data-xwiki-translated-attribute-param="value">abc</pre>
 .#-----------------------------------------------------
 .expect|xwiki/2.0
 .#-----------------------------------------------------
 (% param="value" %)
 {{{abc}}}
 .#-----------------------------------------------------
 .input|xhtml/1.0
 .#-----------------------------------------------------
-<html><pre param="value">abc</pre></html>
+<html><pre data-xwiki-translated-attribute-param="value">abc</pre></html>
diff --git a/xwiki-rendering-integration-tests/src/test/resources/simple/verbatim/verbatim7.test b/xwiki-rendering-integration-tests/src/test/resources/simple/verbatim/verbatim7.test
index 4256f509..356cbbdf 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/simple/verbatim/verbatim7.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/simple/verbatim/verbatim7.test
@@ -14,15 +14,15 @@ endFormat [NONE] [[param2]=[value2]]
 endParagraph [[param]=[value]]
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<p param="value"><span param2="value2"><tt class="wikimodel-verbatim">abc</tt></span></p>
+<p data-xwiki-translated-attribute-param="value"><span data-xwiki-translated-attribute-param2="value2"><tt class="wikimodel-verbatim">abc</tt></span></p>
 .#-----------------------------------------------------
 .expect|xwiki/2.0
 .#-----------------------------------------------------
 (% param="value" %)
 (% param2="value2" %){{{abc}}}
 .#-----------------------------------------------------
 .input|xhtml/1.0
 .#-----------------------------------------------------
-<p param="value"><span param2="value2"><tt class="wikimodel-verbatim">abc</tt></span></p>
\ No newline at end of file
+<p data-xwiki-translated-attribute-param="value"><span data-xwiki-translated-attribute-param2="value2"><tt class="wikimodel-verbatim">abc</tt></span></p>
\ No newline at end of file
diff --git a/xwiki-rendering-integration-tests/src/test/resources/wiki/image/image1.test b/xwiki-rendering-integration-tests/src/test/resources/wiki/image/image1.test
index 29012830..c2d35111 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/wiki/image/image1.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/wiki/image/image1.test
@@ -14,19 +14,19 @@ onImage [Typed = [false] Type = [attach] Reference = [Space.ExistingPage@my.png]
 endParagraph
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<p><img src="imageurl" param1="value1" param2="value2" id="Imy.png" class="wikigeneratedid" alt="my.png"/><br/><img src="imageurl" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/></p>
+<p><img src="imageurl" data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2" id="Imy.png" class="wikigeneratedid" alt="my.png"/><br/><img src="imageurl" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/></p>
 .#-----------------------------------------------------
 .expect|annotatedxhtml/1.0
 .#-----------------------------------------------------
-<p><!--startimage:false|-|attach|-|my.png--><img src="imageurl" param1="value1" param2="value2" id="Imy.png" class="wikigeneratedid" alt="my.png"/><!--stopimage--><br/><!--startimage:false|-|attach|-|Space.ExistingPage@my.png--><img src="imageurl" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/><!--stopimage--></p>
+<p><!--startimage:false|-|attach|-|my.png--><img src="imageurl" data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2" id="Imy.png" class="wikigeneratedid" alt="my.png"/><!--stopimage--><br/><!--startimage:false|-|attach|-|Space.ExistingPage@my.png--><img src="imageurl" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/><!--stopimage--></p>
 .#-----------------------------------------------------
 .expect|xwiki/2.0
 .#-----------------------------------------------------
 [[image:my.png||param1="value1" param2="value2"]]
 [[image:Space.ExistingPage@my.png]]
 .#-----------------------------------------------------
 .input|xhtml/1.0
 .#-----------------------------------------------------
-<p><!--startimage:false|-|attach|-|my.png--><img src="imageurl" param1="value1" param2="value2" id="Imy.png" class="wikigeneratedid" alt="my.png"/><!--stopimage--><br/><!--startimage:false|-|attach|-|Space.ExistingPage@my.png--><img src="imageurl" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/><!--stopimage--></p>
\ No newline at end of file
+<p><!--startimage:false|-|attach|-|my.png--><img src="imageurl" data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2" id="Imy.png" class="wikigeneratedid" alt="my.png"/><!--stopimage--><br/><!--startimage:false|-|attach|-|Space.ExistingPage@my.png--><img src="imageurl" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/><!--stopimage--></p>
\ No newline at end of file
diff --git a/xwiki-rendering-integration-tests/src/test/resources/wiki/image/image12.test b/xwiki-rendering-integration-tests/src/test/resources/wiki/image/image12.test
index c5c46c7c..9757979c 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/wiki/image/image12.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/wiki/image/image12.test
@@ -63,10 +63,10 @@ endFigureCaption
 endFigure [[class]=[image]]
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<img src="imageurl" param1="value1" param2="value2" id="Imy.png" class="wikigeneratedid" alt="my.png"/><div class="figcaption"><p>Image <strong>Caption</strong></p></div><img src="imageurl" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/><div class="figcaption"><p>Caption</p><ul><li>With</li><li>nested</li><li>list <span class="wikiexternallink"><a href="https://xwiki.org">and link</a></span> and [[fake link]].</li></ul></div>
+<img src="imageurl" data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2" id="Imy.png" class="wikigeneratedid" alt="my.png"/><div class="figcaption"><p>Image <strong>Caption</strong></p></div><img src="imageurl" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/><div class="figcaption"><p>Caption</p><ul><li>With</li><li>nested</li><li>list <span class="wikiexternallink"><a href="https://xwiki.org">and link</a></span> and [[fake link]].</li></ul></div>
 .#-----------------------------------------------------
 .expect|html/5.0
 .#-----------------------------------------------------
-<figure class="image"><img src="imageurl" param1="value1" param2="value2" id="Imy.png" class="wikigeneratedid" alt="my.png"/><figcaption><p>Image <strong>Caption</strong></p></figcaption></figure><figure class="image"><img src="imageurl" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/><figcaption><p>Caption</p><ul><li>With</li><li>nested</li><li>list <span class="wikiexternallink"><a href="https://xwiki.org">and link</a></span> and [[fake link]].</li></ul></figcaption></figure>
\ No newline at end of file
+<figure class="image"><img src="imageurl" data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2" id="Imy.png" class="wikigeneratedid" alt="my.png"/><figcaption><p>Image <strong>Caption</strong></p></figcaption></figure><figure class="image"><img src="imageurl" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/><figcaption><p>Caption</p><ul><li>With</li><li>nested</li><li>list <span class="wikiexternallink"><a href="https://xwiki.org">and link</a></span> and [[fake link]].</li></ul></figcaption></figure>
\ No newline at end of file
diff --git a/xwiki-rendering-integration-tests/src/test/resources/wiki/image/image8.test b/xwiki-rendering-integration-tests/src/test/resources/wiki/image/image8.test
index 57810db8..ed5ac8e5 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/wiki/image/image8.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/wiki/image/image8.test
@@ -13,18 +13,18 @@ onImage [Typed = [false] Type = [attach] Reference = [Space.ExistingPage@my.png?
 endParagraph
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<p><img src="imageurl" param2="value2" id="ISpace.ExistingPage40my.png3Fparam13Dvalue1" class="wikigeneratedid" alt="Space.ExistingPage@my.png?param1=value1"/></p>
+<p><img src="imageurl" data-xwiki-translated-attribute-param2="value2" id="ISpace.ExistingPage40my.png3Fparam13Dvalue1" class="wikigeneratedid" alt="Space.ExistingPage@my.png?param1=value1"/></p>
 .#-----------------------------------------------------
 .expect|annotatedxhtml/1.0
 .#-----------------------------------------------------
-<p><!--startimage:false|-|attach|-|Space.ExistingPage@my.png?param1=value1--><img src="imageurl" param2="value2" id="ISpace.ExistingPage40my.png3Fparam13Dvalue1" class="wikigeneratedid" alt="Space.ExistingPage@my.png?param1=value1"/><!--stopimage--></p>
+<p><!--startimage:false|-|attach|-|Space.ExistingPage@my.png?param1=value1--><img src="imageurl" data-xwiki-translated-attribute-param2="value2" id="ISpace.ExistingPage40my.png3Fparam13Dvalue1" class="wikigeneratedid" alt="Space.ExistingPage@my.png?param1=value1"/><!--stopimage--></p>
 .#-----------------------------------------------------
 .expect|xwiki/2.0
 .#-----------------------------------------------------
 [[image:Space.ExistingPage@my.png?param1=value1||param2="value2"]]
 .#-----------------------------------------------------
 .input|xhtml/1.0
 .#-----------------------------------------------------
-<p><!--startimage:false|-|attach|-|Space.ExistingPage@my.png?param1=value1--><img src="imageurl" param2="value2" id="ISpace.ExistingPage40my.png3Fparam13Dvalue1" class="wikigeneratedid" alt="Space.ExistingPage@my.png?param1=value1"/><!--stopimage--></p>
\ No newline at end of file
+<p><!--startimage:false|-|attach|-|Space.ExistingPage@my.png?param1=value1--><img src="imageurl" data-xwiki-translated-attribute-param2="value2" id="ISpace.ExistingPage40my.png3Fparam13Dvalue1" class="wikigeneratedid" alt="Space.ExistingPage@my.png?param1=value1"/><!--stopimage--></p>
\ No newline at end of file
diff --git a/xwiki-rendering-integration-tests/src/test/resources/wiki/image/image9.test b/xwiki-rendering-integration-tests/src/test/resources/wiki/image/image9.test
index d3525c0b..693fd233 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/wiki/image/image9.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/wiki/image/image9.test
@@ -13,18 +13,18 @@ onImage [Typed = [false] Type = [attach] Reference = [Space.ExistingPage@my.png]
 endParagraph
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<p><img src="imageurl?param1=value1" param2="value2" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/></p>
+<p><img src="imageurl?param1=value1" data-xwiki-translated-attribute-param2="value2" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/></p>
 .#-----------------------------------------------------
 .expect|annotatedxhtml/1.0
 .#-----------------------------------------------------
-<p><!--startimage:false|-|attach|-|Space.ExistingPage@my.png|-|queryString="param1=value1"--><img src="imageurl?param1=value1" param2="value2" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/><!--stopimage--></p>
+<p><!--startimage:false|-|attach|-|Space.ExistingPage@my.png|-|queryString="param1=value1"--><img src="imageurl?param1=value1" data-xwiki-translated-attribute-param2="value2" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/><!--stopimage--></p>
 .#-----------------------------------------------------
 .expect|xwiki/2.1
 .#-----------------------------------------------------
 [[image:Space.ExistingPage@my.png||queryString="param1=value1" param2="value2"]]
 .#-----------------------------------------------------
 .input|xhtml/1.0
 .#-----------------------------------------------------
-<p><!--startimage:false|-|attach|-|Space.ExistingPage@my.png|-|queryString="param1=value1"--><img src="imageurl?param1=value1" param2="value2" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/><!--stopimage--></p>
\ No newline at end of file
+<p><!--startimage:false|-|attach|-|Space.ExistingPage@my.png|-|queryString="param1=value1"--><img src="imageurl?param1=value1" data-xwiki-translated-attribute-param2="value2" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/><!--stopimage--></p>
\ No newline at end of file
diff --git a/xwiki-rendering-integration-tests/src/test/resources/wiki/link/links14.test b/xwiki-rendering-integration-tests/src/test/resources/wiki/link/links14.test
index 2a59e7a2..3a8b8b94 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/wiki/link/links14.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/wiki/link/links14.test
@@ -14,18 +14,18 @@ endLink [Typed = [false] Type = [url] Reference = [http://xwiki.org]] [false] [[
 endParagraph
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<p><span class="wikiexternallink"><a param="value" href="http://xwiki.org"><img src="imageurl" height="100" width="100" id="Iattach.png" class="wikigeneratedid" alt="attach.png"/></a></span></p>
+<p><span class="wikiexternallink"><a data-xwiki-translated-attribute-param="value" href="http://xwiki.org"><img src="imageurl" height="100" width="100" id="Iattach.png" class="wikigeneratedid" alt="attach.png"/></a></span></p>
 .#-----------------------------------------------------
 .expect|annotatedxhtml/1.0
 .#-----------------------------------------------------
-<p><!--startwikilink:false|-|url|-|http://xwiki.org--><span class="wikiexternallink"><a param="value" href="http://xwiki.org"><!--startimage:false|-|attach|-|attach.png--><img src="imageurl" height="100" width="100" id="Iattach.png" class="wikigeneratedid" alt="attach.png"/><!--stopimage--></a></span><!--stopwikilink--></p>
+<p><!--startwikilink:false|-|url|-|http://xwiki.org--><span class="wikiexternallink"><a data-xwiki-translated-attribute-param="value" href="http://xwiki.org"><!--startimage:false|-|attach|-|attach.png--><img src="imageurl" height="100" width="100" id="Iattach.png" class="wikigeneratedid" alt="attach.png"/><!--stopimage--></a></span><!--stopwikilink--></p>
 .#-----------------------------------------------------
 .expect|xwiki/2.0
 .#-----------------------------------------------------
 [[~[~[image:attach.png~|~|height="100" width="100"~]~]>>http://xwiki.org||param="value"]]
 .#-----------------------------------------------------
 .input|xhtml/1.0
 .#-----------------------------------------------------
-<p><!--startwikilink:false|-|url|-|http://xwiki.org--><span class="wikiexternallink"><a param="value" href="http://xwiki.org"><!--startimage:false|-|attach|-|attach.png--><img src="imageurl" height="100" width="100" id="Iattach.png" class="wikigeneratedid" alt="attach.png"/><!--stopimage--></a></span><!--stopwikilink--></p>
\ No newline at end of file
+<p><!--startwikilink:false|-|url|-|http://xwiki.org--><span class="wikiexternallink"><a data-xwiki-translated-attribute-param="value" href="http://xwiki.org"><!--startimage:false|-|attach|-|attach.png--><img src="imageurl" height="100" width="100" id="Iattach.png" class="wikigeneratedid" alt="attach.png"/><!--stopimage--></a></span><!--stopwikilink--></p>
\ No newline at end of file
diff --git a/xwiki-rendering-integration-tests/src/test/resources/wiki/link/links15.test b/xwiki-rendering-integration-tests/src/test/resources/wiki/link/links15.test
index bded0253..24d00a90 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/wiki/link/links15.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/wiki/link/links15.test
@@ -16,19 +16,19 @@ endLink [Typed = [true] Type = [attach] Reference = [Space.ExistingPage@my.png]]
 endParagraph
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<p><span class="wikiattachmentlink"><a param1="value1" param2="value2" href="attachmenturl"><span class="wikigeneratedlinkcontent">my.png</span></a></span><br/><span class="wikiattachmentlink"><a href="attachmenturl"><span class="wikigeneratedlinkcontent">Space.ExistingPage@my.png</span></a></span></p>
+<p><span class="wikiattachmentlink"><a data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2" href="attachmenturl"><span class="wikigeneratedlinkcontent">my.png</span></a></span><br/><span class="wikiattachmentlink"><a href="attachmenturl"><span class="wikigeneratedlinkcontent">Space.ExistingPage@my.png</span></a></span></p>
 .#-----------------------------------------------------
 .expect|annotatedxhtml/1.0
 .#-----------------------------------------------------
-<p><!--startwikilink:true|-|attach|-|my.png--><span class="wikiattachmentlink"><a param1="value1" param2="value2" href="attachmenturl"><span class="wikigeneratedlinkcontent">my.png</span></a></span><!--stopwikilink--><br/><!--startwikilink:true|-|attach|-|Space.ExistingPage@my.png--><span class="wikiattachmentlink"><a href="attachmenturl"><span class="wikigeneratedlinkcontent">Space.ExistingPage@my.png</span></a></span><!--stopwikilink--></p>
+<p><!--startwikilink:true|-|attach|-|my.png--><span class="wikiattachmentlink"><a data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2" href="attachmenturl"><span class="wikigeneratedlinkcontent">my.png</span></a></span><!--stopwikilink--><br/><!--startwikilink:true|-|attach|-|Space.ExistingPage@my.png--><span class="wikiattachmentlink"><a href="attachmenturl"><span class="wikigeneratedlinkcontent">Space.ExistingPage@my.png</span></a></span><!--stopwikilink--></p>
 .#-----------------------------------------------------
 .expect|xwiki/2.0
 .#-----------------------------------------------------
 [[attach:my.png||param1="value1" param2="value2"]]
 [[attach:Space.ExistingPage@my.png]]
 .#-----------------------------------------------------
 .input|xhtml/1.0
 .#-----------------------------------------------------
-<p><!--startwikilink:true|-|attach|-|my.png--><span class="wikiattachmentlink"><a param1="value1" param2="value2" href="attachmenturl"><span class="wikigeneratedlinkcontent">my.png</span></a></span><!--stopwikilink--><br/><!--startwikilink:true|-|attach|-|Space.ExistingPage@my.png--><span class="wikiattachmentlink"><a href="attachmenturl"><span class="wikigeneratedlinkcontent">Space.ExistingPage@my.png</span></a></span><!--stopwikilink--></p>
\ No newline at end of file
+<p><!--startwikilink:true|-|attach|-|my.png--><span class="wikiattachmentlink"><a data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2" href="attachmenturl"><span class="wikigeneratedlinkcontent">my.png</span></a></span><!--stopwikilink--><br/><!--startwikilink:true|-|attach|-|Space.ExistingPage@my.png--><span class="wikiattachmentlink"><a href="attachmenturl"><span class="wikigeneratedlinkcontent">Space.ExistingPage@my.png</span></a></span><!--stopwikilink--></p>
\ No newline at end of file
diff --git a/xwiki-rendering-integration-tests/src/test/resources/wiki/link/links19.test b/xwiki-rendering-integration-tests/src/test/resources/wiki/link/links19.test
index bc4a356e..145c9224 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/wiki/link/links19.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/wiki/link/links19.test
@@ -2,11 +2,11 @@
 .input|xhtml/1.0
 .# Verify that the XHTML parser can understand anchors without the special anchor comment format
 .# that the XHTML Renderer uses. Note that for now the HREF value is considered containing
 .# XWiki link syntax.
 .#----------------------------------------------------------------------------------------------
-<p><a href="http://reference" param1="value1">http://reference</a></p>
+<p><a href="http://reference" data-xwiki-translated-attribute-param1="value1">http://reference</a></p>
 .#-----------------------------------------------------
 .expect|xwiki/2.0
 .#-----------------------------------------------------
 .#-----------------------------------------------------
 .expect|event/1.0
@@ -27,6 +27,6 @@ endDocument
 .#-----------------------------------------------------
 [[http:~~/~~/reference>>http://reference||param1="value1"]]
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<p><span class="wikiexternallink"><a param1="value1" href="http://reference">http://reference</a></span></p>
\ No newline at end of file
+<p><span class="wikiexternallink"><a data-xwiki-translated-attribute-param1="value1" href="http://reference">http://reference</a></span></p>
\ No newline at end of file
diff --git a/xwiki-rendering-integration-tests/src/test/resources/wiki/link/links2.test b/xwiki-rendering-integration-tests/src/test/resources/wiki/link/links2.test
index 13ce8030..21f63c23 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/wiki/link/links2.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/wiki/link/links2.test
@@ -19,15 +19,15 @@ endLink [Typed = [false] Type = [doc] Reference = [Space.ExistingPage] Parameter
 endParagraph
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<p><span class="wikilink"><a param2="value2" href="viewurl?param1=value1#anchor"><span class="wikigeneratedlinkcontent">Space.ExistingPage</span></a></span></p>
+<p><span class="wikilink"><a data-xwiki-translated-attribute-param2="value2" href="viewurl?param1=value1#anchor"><span class="wikigeneratedlinkcontent">Space.ExistingPage</span></a></span></p>
 .#-----------------------------------------------------
 .expect|annotatedxhtml/1.0
 .#-----------------------------------------------------
-<p><!--startwikilink:false|-|doc|-|Space.ExistingPage|-|queryString="param1=value1" anchor="anchor"--><span class="wikilink"><a param2="value2" href="viewurl?param1=value1#anchor"><span class="wikigeneratedlinkcontent">Space.ExistingPage</span></a></span><!--stopwikilink--></p>
+<p><!--startwikilink:false|-|doc|-|Space.ExistingPage|-|queryString="param1=value1" anchor="anchor"--><span class="wikilink"><a data-xwiki-translated-attribute-param2="value2" href="viewurl?param1=value1#anchor"><span class="wikigeneratedlinkcontent">Space.ExistingPage</span></a></span><!--stopwikilink--></p>
 .#-----------------------------------------------------
 .expect|xwiki/2.0
 .#-----------------------------------------------------
 [[Space.ExistingPage#anchor?param1=value1||param2="value2"]]
 .#-----------------------------------------------------
@@ -35,6 +35,6 @@ endDocument
 .#-----------------------------------------------------
 [[Space.ExistingPage||queryString="param1=value1" anchor="anchor" param2="value2"]]
 .#-----------------------------------------------------
 .input|xhtml/1.0
 .#-----------------------------------------------------
-<p><!--startwikilink:false|-|doc|-|Space.ExistingPage|-|queryString="param1=value1" anchor="anchor"--><span class="wikilink"><a param2="value2" href="viewurl?param1=value1#anchor"><span class="wikigeneratedlinkcontent">Space.ExistingPage</span></a></span><!--stopwikilink--></p>
\ No newline at end of file
+<p><!--startwikilink:false|-|doc|-|Space.ExistingPage|-|queryString="param1=value1" anchor="anchor"--><span class="wikilink"><a data-xwiki-translated-attribute-param2="value2" href="viewurl?param1=value1#anchor"><span class="wikigeneratedlinkcontent">Space.ExistingPage</span></a></span><!--stopwikilink--></p>
\ No newline at end of file
diff --git a/xwiki-rendering-integration-tests/src/test/resources/wiki/link/links8.test b/xwiki-rendering-integration-tests/src/test/resources/wiki/link/links8.test
index 638378cf..17ee7f72 100644
--- a/xwiki-rendering-integration-tests/src/test/resources/wiki/link/links8.test
+++ b/xwiki-rendering-integration-tests/src/test/resources/wiki/link/links8.test
@@ -17,19 +17,19 @@ endLink [Typed = [false] Type = [doc] Reference = [Space.UnknownPage]] [false] [
 endParagraph
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<p><span class="wikilink"><a param1="value1" param2="value2" href="viewurl"><span class="wikigeneratedlinkcontent">Space.ExistingPage</span></a></span><br/><span class="wikicreatelink"><a param="value" href="editurl">label</a></span></p>
+<p><span class="wikilink"><a data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2" href="viewurl"><span class="wikigeneratedlinkcontent">Space.ExistingPage</span></a></span><br/><span class="wikicreatelink"><a data-xwiki-translated-attribute-param="value" href="editurl">label</a></span></p>
 .#-----------------------------------------------------
 .expect|annotatedxhtml/1.0
 .#-----------------------------------------------------
-<p><!--startwikilink:false|-|doc|-|Space.ExistingPage--><span class="wikilink"><a param1="value1" param2="value2" href="viewurl"><span class="wikigeneratedlinkcontent">Space.ExistingPage</span></a></span><!--stopwikilink--><br/><!--startwikilink:false|-|doc|-|Space.UnknownPage--><span class="wikicreatelink"><a param="value" href="editurl">label</a></span><!--stopwikilink--></p>
+<p><!--startwikilink:false|-|doc|-|Space.ExistingPage--><span class="wikilink"><a data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2" href="viewurl"><span class="wikigeneratedlinkcontent">Space.ExistingPage</span></a></span><!--stopwikilink--><br/><!--startwikilink:false|-|doc|-|Space.UnknownPage--><span class="wikicreatelink"><a data-xwiki-translated-attribute-param="value" href="editurl">label</a></span><!--stopwikilink--></p>
 .#-----------------------------------------------------
 .expect|xwiki/2.0
 .#-----------------------------------------------------
 [[Space.ExistingPage||param1="value1" param2="value2"]]
 [[label>>Space.UnknownPage||param="value"]]
 .#-----------------------------------------------------
 .input|xhtml/1.0
 .#-----------------------------------------------------
-<p><!--startwikilink:false|-|doc|-|Space.ExistingPage--><span class="wikilink"><a param1="value1" param2="value2" href="viewurl"><span class="wikigeneratedlinkcontent">Space.ExistingPage</span></a></span><!--stopwikilink--><br/><!--startwikilink:false|-|doc|-|Space.UnknownPage--><span class="wikicreatelink"><a param="value" href="editurl">label</a></span><!--stopwikilink--></p>
\ No newline at end of file
+<p><!--startwikilink:false|-|doc|-|Space.ExistingPage--><span class="wikilink"><a data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2" href="viewurl"><span class="wikigeneratedlinkcontent">Space.ExistingPage</span></a></span><!--stopwikilink--><br/><!--startwikilink:false|-|doc|-|Space.UnknownPage--><span class="wikicreatelink"><a data-xwiki-translated-attribute-param="value" href="editurl">label</a></span><!--stopwikilink--></p>
\ No newline at end of file
diff --git a/xwiki-rendering-macros/xwiki-rendering-macro-html/src/main/java/org/xwiki/rendering/internal/macro/html/HTMLMacroXHTMLRenderer.java b/xwiki-rendering-macros/xwiki-rendering-macro-html/src/main/java/org/xwiki/rendering/internal/macro/html/HTMLMacroXHTMLRenderer.java
index 04d9e4c5..0b995480 100644
--- a/xwiki-rendering-macros/xwiki-rendering-macro-html/src/main/java/org/xwiki/rendering/internal/macro/html/HTMLMacroXHTMLRenderer.java
+++ b/xwiki-rendering-macros/xwiki-rendering-macro-html/src/main/java/org/xwiki/rendering/internal/macro/html/HTMLMacroXHTMLRenderer.java
@@ -27,10 +27,11 @@
 import org.xwiki.component.descriptor.ComponentInstantiationStrategy;
 import org.xwiki.rendering.internal.renderer.xhtml.XHTMLChainingRenderer;
 import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
 import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
 import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;
+import org.xwiki.xml.html.HTMLElementSanitizer;
 
 /**
  * Renderer that generates XHTML from a XDOM resulting from the parsing of text containing HTML mixed with wiki syntax.
  *
  * @version $Id$
@@ -55,11 +56,15 @@ public class HTMLMacroXHTMLRenderer extends AbstractHTMLMacroRenderer
      * attachments, we get its URL, etc.
      */
     @Inject
     private XHTMLImageRenderer imageRenderer;
 
+    @Inject
+    private HTMLElementSanitizer htmlElementSanitizer;
+
     @Override
     protected AbstractChainingPrintRenderer getSyntaxRenderer()
     {
-        return new XHTMLChainingRenderer(this.linkRenderer, this.imageRenderer, getListenerChain());
+        return new XHTMLChainingRenderer(this.linkRenderer, this.imageRenderer, this.htmlElementSanitizer,
+            getListenerChain());
     }
 }
diff --git a/xwiki-rendering-macros/xwiki-rendering-macro-html/src/main/java/org/xwiki/rendering/internal/macro/html/renderers/annotatedhtml5/HTMLMacroAnnotatedHTML5Renderer.java b/xwiki-rendering-macros/xwiki-rendering-macro-html/src/main/java/org/xwiki/rendering/internal/macro/html/renderers/annotatedhtml5/HTMLMacroAnnotatedHTML5Renderer.java
index b7d149a6..65f423a6 100644
--- a/xwiki-rendering-macros/xwiki-rendering-macro-html/src/main/java/org/xwiki/rendering/internal/macro/html/renderers/annotatedhtml5/HTMLMacroAnnotatedHTML5Renderer.java
+++ b/xwiki-rendering-macros/xwiki-rendering-macro-html/src/main/java/org/xwiki/rendering/internal/macro/html/renderers/annotatedhtml5/HTMLMacroAnnotatedHTML5Renderer.java
@@ -28,10 +28,11 @@
 import org.xwiki.rendering.internal.macro.html.AbstractHTMLMacroRenderer;
 import org.xwiki.rendering.internal.renderer.html5.AnnotatedHTML5ChainingRenderer;
 import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
 import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
 import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;
+import org.xwiki.xml.html.HTMLElementSanitizer;
 
 /**
  * Renderer that generates Annotated HTML5 from a XDOM resulting from the parsing of text containing HTML mixed with
  * wiki syntax.
  *
@@ -57,11 +58,15 @@ public class HTMLMacroAnnotatedHTML5Renderer extends AbstractHTMLMacroRenderer
      * attachments, we get its URL, etc.
      */
     @Inject
     private XHTMLImageRenderer imageRenderer;
 
+    @Inject
+    private HTMLElementSanitizer htmlElementSanitizer;
+
     @Override
     protected AbstractChainingPrintRenderer getSyntaxRenderer()
     {
-        return new AnnotatedHTML5ChainingRenderer(this.linkRenderer, this.imageRenderer, getListenerChain());
+        return new AnnotatedHTML5ChainingRenderer(this.linkRenderer, this.imageRenderer, this.htmlElementSanitizer,
+            getListenerChain());
     }
 }
diff --git a/xwiki-rendering-macros/xwiki-rendering-macro-html/src/main/java/org/xwiki/rendering/internal/macro/html/renderers/annotatedxhtml/HTMLMacroAnnotatedXHTMLRenderer.java b/xwiki-rendering-macros/xwiki-rendering-macro-html/src/main/java/org/xwiki/rendering/internal/macro/html/renderers/annotatedxhtml/HTMLMacroAnnotatedXHTMLRenderer.java
index d8205803..e6897a4f 100644
--- a/xwiki-rendering-macros/xwiki-rendering-macro-html/src/main/java/org/xwiki/rendering/internal/macro/html/renderers/annotatedxhtml/HTMLMacroAnnotatedXHTMLRenderer.java
+++ b/xwiki-rendering-macros/xwiki-rendering-macro-html/src/main/java/org/xwiki/rendering/internal/macro/html/renderers/annotatedxhtml/HTMLMacroAnnotatedXHTMLRenderer.java
@@ -28,10 +28,11 @@
 import org.xwiki.rendering.internal.macro.html.AbstractHTMLMacroRenderer;
 import org.xwiki.rendering.internal.renderer.xhtml.AnnotatedXHTMLChainingRenderer;
 import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
 import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
 import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;
+import org.xwiki.xml.html.HTMLElementSanitizer;
 
 /**
  * Renderer that generates Annotated XHTML from a XDOM resulting from the parsing of text containing HTML mixed with
  * wiki syntax.
  *
@@ -59,11 +60,15 @@ public class HTMLMacroAnnotatedXHTMLRenderer extends AbstractHTMLMacroRenderer
      */
     @Inject
     @Named("annotated")
     private XHTMLImageRenderer imageRenderer;
 
+    @Inject
+    private HTMLElementSanitizer htmlElementSanitizer;
+
     @Override
     protected AbstractChainingPrintRenderer getSyntaxRenderer()
     {
-        return new AnnotatedXHTMLChainingRenderer(this.linkRenderer, this.imageRenderer, getListenerChain());
+        return new AnnotatedXHTMLChainingRenderer(this.linkRenderer, this.imageRenderer, this.htmlElementSanitizer,
+            getListenerChain());
     }
 }
diff --git a/xwiki-rendering-macros/xwiki-rendering-macro-html/src/main/java/org/xwiki/rendering/internal/macro/html/renderers/html5/HTMLMacroHTML5Renderer.java b/xwiki-rendering-macros/xwiki-rendering-macro-html/src/main/java/org/xwiki/rendering/internal/macro/html/renderers/html5/HTMLMacroHTML5Renderer.java
index 132e3a05..4792d170 100644
--- a/xwiki-rendering-macros/xwiki-rendering-macro-html/src/main/java/org/xwiki/rendering/internal/macro/html/renderers/html5/HTMLMacroHTML5Renderer.java
+++ b/xwiki-rendering-macros/xwiki-rendering-macro-html/src/main/java/org/xwiki/rendering/internal/macro/html/renderers/html5/HTMLMacroHTML5Renderer.java
@@ -28,10 +28,11 @@
 import org.xwiki.rendering.internal.macro.html.AbstractHTMLMacroRenderer;
 import org.xwiki.rendering.internal.renderer.html5.HTML5ChainingRenderer;
 import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
 import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
 import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;
+import org.xwiki.xml.html.HTMLElementSanitizer;
 
 /**
  * Renderer that generates HTML5 from a XDOM resulting from the parsing of text containing HTML mixed with
  * wiki syntax.
  *
@@ -57,11 +58,15 @@ public class HTMLMacroHTML5Renderer extends AbstractHTMLMacroRenderer
      * attachments, we get its URL, etc.
      */
     @Inject
     private XHTMLImageRenderer imageRenderer;
 
+    @Inject
+    private HTMLElementSanitizer htmlElementSanitizer;
+
     @Override
     protected AbstractChainingPrintRenderer getSyntaxRenderer()
     {
-        return new HTML5ChainingRenderer(this.linkRenderer, this.imageRenderer, getListenerChain());
+        return new HTML5ChainingRenderer(this.linkRenderer, this.imageRenderer, this.htmlElementSanitizer,
+            getListenerChain());
     }
 }
diff --git a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedhtml5/src/main/java/org/xwiki/rendering/internal/renderer/html5/AnnotatedHTML5ChainingRenderer.java b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedhtml5/src/main/java/org/xwiki/rendering/internal/renderer/html5/AnnotatedHTML5ChainingRenderer.java
index ee6f818f..c37d941d 100644
--- a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedhtml5/src/main/java/org/xwiki/rendering/internal/renderer/html5/AnnotatedHTML5ChainingRenderer.java
+++ b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedhtml5/src/main/java/org/xwiki/rendering/internal/renderer/html5/AnnotatedHTML5ChainingRenderer.java
@@ -26,10 +26,11 @@
 import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
 import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
 import org.xwiki.rendering.listener.MetaData;
 import org.xwiki.rendering.listener.chaining.BlockStateChainingListener;
 import org.xwiki.rendering.listener.chaining.ListenerChain;
+import org.xwiki.xml.html.HTMLElementSanitizer;
 
 /**
  * Convert listener events to annotated HTML5. See {@link AnnotatedHTML5Renderer} for more details on what Annotated
  * HTML5 is.
  *
@@ -53,16 +54,17 @@ public class AnnotatedHTML5ChainingRenderer extends HTML5ChainingRenderer
      *            rendering depends on how the underlying system wants to handle it. For example for XWiki we check if
      *            the document exists, we get the document URL, etc.
      * @param imageRenderer the object to render image events into XHTML. This is done so that it's pluggable because
      *            image rendering depends on how the underlying system wants to handle it. For example for XWiki we
      *            check if the image exists as a document attachments, we get its URL, etc.
+     * @param htmlElementSanitizer the HTML element sanitizer to use
      * @param listenerChain the chain of listener filters used to compute various states
      */
     public AnnotatedHTML5ChainingRenderer(XHTMLLinkRenderer linkRenderer,
-            XHTMLImageRenderer imageRenderer, ListenerChain listenerChain)
+            XHTMLImageRenderer imageRenderer, HTMLElementSanitizer htmlElementSanitizer, ListenerChain listenerChain)
     {
-        super(linkRenderer, imageRenderer, listenerChain);
+        super(linkRenderer, imageRenderer, htmlElementSanitizer, listenerChain);
 
         this.macroRenderer = new XHTMLMacroRenderer();
 
         this.metaDataRenderer = new XHTMLMetaDataRenderer();
     }
diff --git a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedhtml5/src/main/java/org/xwiki/rendering/internal/renderer/html5/AnnotatedHTML5Renderer.java b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedhtml5/src/main/java/org/xwiki/rendering/internal/renderer/html5/AnnotatedHTML5Renderer.java
index 750d08f5..43540bf1 100644
--- a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedhtml5/src/main/java/org/xwiki/rendering/internal/renderer/html5/AnnotatedHTML5Renderer.java
+++ b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedhtml5/src/main/java/org/xwiki/rendering/internal/renderer/html5/AnnotatedHTML5Renderer.java
@@ -32,10 +32,11 @@
 import org.xwiki.rendering.listener.chaining.BlockStateChainingListener;
 import org.xwiki.rendering.listener.chaining.EmptyBlockChainingListener;
 import org.xwiki.rendering.listener.chaining.ListenerChain;
 import org.xwiki.rendering.listener.chaining.MetaDataStateChainingListener;
 import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;
+import org.xwiki.xml.html.HTMLElementSanitizer;
 
 /**
  * Generates Annotated HTML5 (ie HTML5 containing metadata information, for example macro definition or
  * link definition) from a {@link org.xwiki.rendering.block.XDOM} object being traversed.
  * The annotations allow initial source content to be fully reconstructed from the generated HTML5. This is required
@@ -65,10 +66,13 @@ public class AnnotatedHTML5Renderer extends AbstractChainingPrintRenderer implem
      */
     @Inject
     @Named("annotated")
     private XHTMLImageRenderer imageRenderer;
 
+    @Inject
+    private HTMLElementSanitizer htmlElementSanitizer;
+
     @Override
     public void initialize() throws InitializationException
     {
         ListenerChain chain = new ListenerChain();
         setListenerChain(chain);
@@ -77,8 +81,9 @@ public void initialize() throws InitializationException
         // placed later in the chain.
         chain.addListener(this);
         chain.addListener(new BlockStateChainingListener(chain));
         chain.addListener(new EmptyBlockChainingListener(chain));
         chain.addListener(new MetaDataStateChainingListener(chain));
-        chain.addListener(new AnnotatedHTML5ChainingRenderer(this.linkRenderer, this.imageRenderer, chain));
+        chain.addListener(new AnnotatedHTML5ChainingRenderer(this.linkRenderer, this.imageRenderer,
+            this.htmlElementSanitizer, chain));
     }
 }
diff --git a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedhtml5/src/test/resources/annotatedhtml50/simple/monospace/monospace2.out.txt b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedhtml5/src/test/resources/annotatedhtml50/simple/monospace/monospace2.out.txt
index 03c918ef..cfa6a7cb 100644
--- a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedhtml5/src/test/resources/annotatedhtml50/simple/monospace/monospace2.out.txt
+++ b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedhtml5/src/test/resources/annotatedhtml50/simple/monospace/monospace2.out.txt
@@ -1 +1 @@
-<p><span a="b" class="monospace">monospace</span></p>
\ No newline at end of file
+<p><span data-xwiki-translated-attribute-a="b" class="monospace">monospace</span></p>
\ No newline at end of file
diff --git a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedxhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLChainingRenderer.java b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedxhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLChainingRenderer.java
index 4dae991b..d3388b05 100644
--- a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedxhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLChainingRenderer.java
+++ b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedxhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLChainingRenderer.java
@@ -23,10 +23,11 @@
 
 import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
 import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
 import org.xwiki.rendering.listener.MetaData;
 import org.xwiki.rendering.listener.chaining.ListenerChain;
+import org.xwiki.xml.html.HTMLElementSanitizer;
 
 /**
  * Convert listener events to annotated XHTML. See {@link AnnotatedXHTMLChainingRenderer} for more details on
  * what Annotated XHTML is.
  *
@@ -50,16 +51,17 @@ public class AnnotatedXHTMLChainingRenderer extends XHTMLChainingRenderer
      *            rendering depends on how the underlying system wants to handle it. For example for XWiki we check if
      *            the document exists, we get the document URL, etc.
      * @param imageRenderer the object to render image events into XHTML. This is done so that it's pluggable because
      *            image rendering depends on how the underlying system wants to handle it. For example for XWiki we
      *            check if the image exists as a document attachments, we get its URL, etc.
+     * @param htmlElementSanitizer the sanitizer to use for sanitizing HTML elements and attributes
      * @param listenerChain the chain of listener filters used to compute various states
      */
     public AnnotatedXHTMLChainingRenderer(XHTMLLinkRenderer linkRenderer,
-        XHTMLImageRenderer imageRenderer, ListenerChain listenerChain)
+        XHTMLImageRenderer imageRenderer, HTMLElementSanitizer htmlElementSanitizer, ListenerChain listenerChain)
     {
-        super(linkRenderer, imageRenderer, listenerChain);
+        super(linkRenderer, imageRenderer, htmlElementSanitizer, listenerChain);
 
         this.macroRenderer = new XHTMLMacroRenderer();
 
         this.metaDataRenderer = new XHTMLMetaDataRenderer();
     }
diff --git a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedxhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLRenderer.java b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedxhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLRenderer.java
index b182ac65..c41195ad 100644
--- a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedxhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLRenderer.java
+++ b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-annotatedxhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/AnnotatedXHTMLRenderer.java
@@ -32,10 +32,11 @@
 import org.xwiki.rendering.listener.chaining.BlockStateChainingListener;
 import org.xwiki.rendering.listener.chaining.EmptyBlockChainingListener;
 import org.xwiki.rendering.listener.chaining.ListenerChain;
 import org.xwiki.rendering.listener.chaining.MetaDataStateChainingListener;
 import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;
+import org.xwiki.xml.html.HTMLElementSanitizer;
 
 /**
  * Generates Annotated XHTML (ie XHTML containing metadata information, for example macro definition or
  * link definition) from a {@link org.xwiki.rendering.block.XDOM} object being traversed.
  * The annotations allow initial source content to be fully reconstructed from the generated XHTML. This is required
@@ -65,10 +66,13 @@ public class AnnotatedXHTMLRenderer extends AbstractChainingPrintRenderer implem
      */
     @Inject
     @Named("annotated")
     private XHTMLImageRenderer imageRenderer;
 
+    @Inject
+    private HTMLElementSanitizer htmlElementSanitizer;
+
     @Override
     public void initialize() throws InitializationException
     {
         ListenerChain chain = new ListenerChain();
         setListenerChain(chain);
@@ -77,8 +81,9 @@ public void initialize() throws InitializationException
         // placed later in the chain.
         chain.addListener(this);
         chain.addListener(new BlockStateChainingListener(chain));
         chain.addListener(new EmptyBlockChainingListener(chain));
         chain.addListener(new MetaDataStateChainingListener(chain));
-        chain.addListener(new AnnotatedXHTMLChainingRenderer(this.linkRenderer, this.imageRenderer, chain));
+        chain.addListener(new AnnotatedXHTMLChainingRenderer(this.linkRenderer, this.imageRenderer,
+            this.htmlElementSanitizer, chain));
     }
 }
diff --git a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-html5/src/main/java/org/xwiki/rendering/internal/renderer/html5/HTML5ChainingRenderer.java b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-html5/src/main/java/org/xwiki/rendering/internal/renderer/html5/HTML5ChainingRenderer.java
index f9d8f0be..e818f161 100644
--- a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-html5/src/main/java/org/xwiki/rendering/internal/renderer/html5/HTML5ChainingRenderer.java
+++ b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-html5/src/main/java/org/xwiki/rendering/internal/renderer/html5/HTML5ChainingRenderer.java
@@ -18,17 +18,19 @@
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
 package org.xwiki.rendering.internal.renderer.html5;
 
 import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.Map;
 
 import org.xwiki.rendering.internal.renderer.xhtml.XHTMLChainingRenderer;
 import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
 import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
 import org.xwiki.rendering.listener.Format;
 import org.xwiki.rendering.listener.chaining.ListenerChain;
+import org.xwiki.xml.html.HTMLElementSanitizer;
 
 /**
  * Convert listener events to HTML5.
  *
  * @version $Id$
@@ -51,26 +53,26 @@ public class HTML5ChainingRenderer extends XHTMLChainingRenderer
      * rendering depends on how the underlying system wants to handle it. For example for XWiki we check if the document
      * exists, we get the document URL, etc.
      * @param imageRenderer the object to render image events into XHTML. This is done so that it's pluggable because
      * image rendering depends on how the underlying system wants to handle it. For example for XWiki we check if the
      * image exists as a document attachments, we get its URL, etc.
+     * @param htmlElementSanitizer the sanitizer to use for sanitizing HTML elements and attributes
      * @param listenerChain the chain of listener filters used to compute various states
      */
     public HTML5ChainingRenderer(XHTMLLinkRenderer linkRenderer,
-            XHTMLImageRenderer imageRenderer,
+            XHTMLImageRenderer imageRenderer, HTMLElementSanitizer htmlElementSanitizer,
             ListenerChain listenerChain)
     {
-        super(linkRenderer, imageRenderer, listenerChain);
+        super(linkRenderer, imageRenderer, htmlElementSanitizer, listenerChain);
     }
 
     @Override
     public void beginFormat(Format format, Map<String, String> parameters)
     {
         // Right now, the only difference with the super class is about the "monospace" format
         if (format == Format.MONOSPACE) {
-            Map<String, String> attributes = new HashMap<>();
-            attributes.putAll(parameters);
+            Map<String, String> attributes = new LinkedHashMap<>(parameters);
             String cssClass = "monospace";
             // The element may already have a class
             if (attributes.containsKey(PROP_CLASS)) {
                 cssClass = String.format("%s %s", cssClass, attributes.get(PROP_CLASS));
             }
diff --git a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-html5/src/main/java/org/xwiki/rendering/internal/renderer/html5/HTML5Renderer.java b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-html5/src/main/java/org/xwiki/rendering/internal/renderer/html5/HTML5Renderer.java
index f112c50f..43ddf624 100644
--- a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-html5/src/main/java/org/xwiki/rendering/internal/renderer/html5/HTML5Renderer.java
+++ b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-html5/src/main/java/org/xwiki/rendering/internal/renderer/html5/HTML5Renderer.java
@@ -32,10 +32,11 @@
 import org.xwiki.rendering.listener.chaining.BlockStateChainingListener;
 import org.xwiki.rendering.listener.chaining.EmptyBlockChainingListener;
 import org.xwiki.rendering.listener.chaining.ListenerChain;
 import org.xwiki.rendering.listener.chaining.MetaDataStateChainingListener;
 import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;
+import org.xwiki.xml.html.HTMLElementSanitizer;
 
 /**
  * Generates HTML5 from a {@link org.xwiki.rendering.block.XDOM} object being traversed.
  *
  * @version $Id$
@@ -60,10 +61,13 @@ public class HTML5Renderer extends AbstractChainingPrintRenderer implements Init
      * attachments, we get its URL, etc.
      */
     @Inject
     private XHTMLImageRenderer imageRenderer;
 
+    @Inject
+    private HTMLElementSanitizer htmlElementSanitizer;
+
     @Override
     public void initialize() throws InitializationException
     {
         ListenerChain chain = new ListenerChain();
         setListenerChain(chain);
@@ -72,9 +76,10 @@ public void initialize() throws InitializationException
         // placed later in the chain.
         chain.addListener(this);
         chain.addListener(new BlockStateChainingListener(chain));
         chain.addListener(new EmptyBlockChainingListener(chain));
         chain.addListener(new MetaDataStateChainingListener(chain));
-        chain.addListener(new HTML5ChainingRenderer(this.linkRenderer, this.imageRenderer, chain));
+        chain.addListener(new HTML5ChainingRenderer(this.linkRenderer, this.imageRenderer, this.htmlElementSanitizer,
+            chain));
     }
 }
 
diff --git a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-html5/src/test/java/org/xwiki/rendering/internal/html5/HTML5ChainingRendererTest.java b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-html5/src/test/java/org/xwiki/rendering/internal/html5/HTML5ChainingRendererTest.java
index 0d4cd31b..782e5daf 100644
--- a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-html5/src/test/java/org/xwiki/rendering/internal/html5/HTML5ChainingRendererTest.java
+++ b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-html5/src/test/java/org/xwiki/rendering/internal/html5/HTML5ChainingRendererTest.java
@@ -22,13 +22,13 @@
 import java.util.HashMap;
 import java.util.Map;
 
 import org.junit.Before;
 import org.junit.Test;
+import org.xwiki.rendering.internal.renderer.html5.HTML5ChainingRenderer;
 import org.xwiki.rendering.internal.renderer.xhtml.image.XHTMLImageRenderer;
 import org.xwiki.rendering.internal.renderer.xhtml.link.XHTMLLinkRenderer;
-import org.xwiki.rendering.internal.renderer.html5.HTML5ChainingRenderer;
 import org.xwiki.rendering.listener.Format;
 import org.xwiki.rendering.listener.chaining.ListenerChain;
 import org.xwiki.rendering.renderer.printer.DefaultWikiPrinter;
 
 import static org.junit.Assert.assertEquals;
@@ -56,11 +56,11 @@
     public void setUp() throws Exception
     {
         linkRenderer = mock(XHTMLLinkRenderer.class);
         imageRenderer = mock(XHTMLImageRenderer.class);
         listenerChain = new ListenerChain();
-        chainingRenderer = new HTML5ChainingRenderer(linkRenderer, imageRenderer, listenerChain);
+        chainingRenderer = new HTML5ChainingRenderer(linkRenderer, imageRenderer, null, listenerChain);
         printer = new DefaultWikiPrinter();
         chainingRenderer.setPrinter(printer);
     }
     
     @Test
diff --git a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/main/java/org/xwiki/rendering/internal/parser/xhtml/wikimodel/XHTMLXWikiGeneratorListener.java b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/main/java/org/xwiki/rendering/internal/parser/xhtml/wikimodel/XHTMLXWikiGeneratorListener.java
index 8be3d814..688bde1c 100644
--- a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/main/java/org/xwiki/rendering/internal/parser/xhtml/wikimodel/XHTMLXWikiGeneratorListener.java
+++ b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/main/java/org/xwiki/rendering/internal/parser/xhtml/wikimodel/XHTMLXWikiGeneratorListener.java
@@ -17,23 +17,26 @@
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
 package org.xwiki.rendering.internal.parser.xhtml.wikimodel;
 
+import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
 import org.xwiki.rendering.internal.parser.wikimodel.DefaultXWikiGeneratorListener;
 import org.xwiki.rendering.listener.Listener;
 import org.xwiki.rendering.listener.MetaData;
 import org.xwiki.rendering.listener.reference.ResourceReference;
 import org.xwiki.rendering.listener.reference.ResourceType;
 import org.xwiki.rendering.parser.ResourceReferenceParser;
 import org.xwiki.rendering.parser.StreamParser;
 import org.xwiki.rendering.renderer.PrintRendererFactory;
+import org.xwiki.rendering.renderer.printer.XHTMLWikiPrinter;
 import org.xwiki.rendering.syntax.Syntax;
 import org.xwiki.rendering.util.IdGenerator;
 import org.xwiki.rendering.wikimodel.WikiFormat;
 import org.xwiki.rendering.wikimodel.WikiParameter;
 import org.xwiki.rendering.wikimodel.WikiParameters;
@@ -202,11 +205,11 @@ private static WikiParameters cleanParametersFromMetadata(WikiParameters paramet
         WikiParameters wikiParameters = new WikiParameters();
 
         for (WikiParameter parameter : parameters) {
             boolean acceptParameter = !(parameter.getKey().startsWith(METADATA_ATTRIBUTE_PREFIX)
                 || (
-                    parameter.getKey().equals(CLASS_ATTRIBUTE) && parameter.getValue().equals(METADATA_CONTAINER_CLASS)
+                parameter.getKey().equals(CLASS_ATTRIBUTE) && parameter.getValue().equals(METADATA_CONTAINER_CLASS)
             ));
             if (acceptParameter) {
                 wikiParameters = wikiParameters.addParameter(parameter.getKey(), parameter.getValue());
             }
         }
@@ -286,6 +289,49 @@ public void endFormat(WikiFormat format)
             }
         } else {
             super.endFormat(format);
         }
     }
+
+    @Override
+    protected Map<String, String> convertParameters(WikiParameters params)
+    {
+        return maybeRemoveAttributePrefix(super.convertParameters(params));
+    }
+
+    @Override
+    protected Pair<Map<String, String>, Map<String, String>> convertAndSeparateParameters(WikiParameters params)
+    {
+        Pair<Map<String, String>, Map<String, String>> result = super.convertAndSeparateParameters(params);
+        Map<String, String> genericParameters = result.getRight();
+
+        if (!genericParameters.isEmpty()) {
+            genericParameters = maybeRemoveAttributePrefix(genericParameters);
+        }
+
+        return new ImmutablePair<>(result.getLeft(), genericParameters);
+    }
+
+    private Map<String, String> maybeRemoveAttributePrefix(Map<String, String> attributes)
+    {
+        Map<String, String> result;
+
+        if (!attributes.isEmpty()) {
+            result = new LinkedHashMap<>();
+
+            for (Map.Entry<String, String> entry : attributes.entrySet()) {
+                String newKey;
+                if (entry.getKey().startsWith(XHTMLWikiPrinter.TRANSLATED_ATTRIBUTE_PREFIX)) {
+                    newKey = entry.getKey().substring(XHTMLWikiPrinter.TRANSLATED_ATTRIBUTE_PREFIX.length());
+                } else {
+                    newKey = entry.getKey();
+                }
+
+                result.put(newKey, entry.getValue());
+            }
+        } else {
+            result = attributes;
+        }
+
+        return result;
+    }
 }
diff --git a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLChainingRenderer.java b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLChainingRenderer.java
index 4ed29bbc..58b61861 100644
--- a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLChainingRenderer.java
+++ b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLChainingRenderer.java
@@ -39,10 +39,11 @@
 import org.xwiki.rendering.renderer.printer.WikiPrinter;
 import org.xwiki.rendering.renderer.printer.XHTMLWikiPrinter;
 import org.xwiki.rendering.syntax.Syntax;
 import org.xwiki.rendering.syntax.SyntaxType;
 import org.xwiki.xml.html.HTMLConstants;
+import org.xwiki.xml.html.HTMLElementSanitizer;
 
 /**
  * Convert listener events to XHTML.
  *
  * @version $Id$
@@ -63,28 +64,32 @@ public class XHTMLChainingRenderer extends AbstractChainingPrintRenderer
 
     private XHTMLLinkRenderer linkRenderer;
 
     private XHTMLImageRenderer imageRenderer;
 
+    private final HTMLElementSanitizer htmlElementSanitizer;
+
     private XHTMLWikiPrinter xhtmlWikiPrinter;
 
     /**
-     * @param linkRenderer the object to render link events into XHTML. This is done so that it's pluggable because link
-     *            rendering depends on how the underlying system wants to handle it. For example for XWiki we check if
-     *            the document exists, we get the document URL, etc.
-     * @param imageRenderer the object to render image events into XHTML. This is done so that it's pluggable because
-     *            image rendering depends on how the underlying system wants to handle it. For example for XWiki we
-     *            check if the image exists as a document attachments, we get its URL, etc.
+     * @param linkRenderer the object to render link events into XHTML. This is done so that it's pluggable because
+     *     link rendering depends on how the underlying system wants to handle it. For example for XWiki we check if the
+     *     document exists, we get the document URL, etc.
+     * @param imageRenderer the object to render image events into XHTML. This is done so that it's pluggable
+     *     because image rendering depends on how the underlying system wants to handle it. For example for XWiki we
+     *     check if the image exists as a document attachments, we get its URL, etc.
+     * @param htmlElementSanitizer the sanitizer for XHTML elements
      * @param listenerChain the chain of listener filters used to compute various states
      */
     public XHTMLChainingRenderer(XHTMLLinkRenderer linkRenderer, XHTMLImageRenderer imageRenderer,
-        ListenerChain listenerChain)
+        HTMLElementSanitizer htmlElementSanitizer, ListenerChain listenerChain)
     {
         setListenerChain(listenerChain);
 
         this.linkRenderer = linkRenderer;
         this.imageRenderer = imageRenderer;
+        this.htmlElementSanitizer = htmlElementSanitizer;
     }
 
     // State
 
     protected BlockStateChainingListener getBlockState()
@@ -119,15 +124,20 @@ protected void popPrinter()
     }
 
     protected XHTMLWikiPrinter getXHTMLWikiPrinter()
     {
         if (this.xhtmlWikiPrinter == null) {
-            this.xhtmlWikiPrinter = new XHTMLWikiPrinter(getPrinter());
+            this.xhtmlWikiPrinter = new XHTMLWikiPrinter(getPrinter(), getHtmlElementSanitizer());
         }
         return this.xhtmlWikiPrinter;
     }
 
+    protected HTMLElementSanitizer getHtmlElementSanitizer()
+    {
+        return this.htmlElementSanitizer;
+    }
+
     // Events
 
     @Override
     public void beginGroup(Map<String, String> parameters)
     {
diff --git a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLRenderer.java b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLRenderer.java
index 0fb9967d..def1f32a 100644
--- a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLRenderer.java
+++ b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLRenderer.java
@@ -32,10 +32,11 @@
 import org.xwiki.rendering.listener.chaining.BlockStateChainingListener;
 import org.xwiki.rendering.listener.chaining.EmptyBlockChainingListener;
 import org.xwiki.rendering.listener.chaining.ListenerChain;
 import org.xwiki.rendering.listener.chaining.MetaDataStateChainingListener;
 import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;
+import org.xwiki.xml.html.HTMLElementSanitizer;
 
 /**
  * Generates XHTML from a {@link org.xwiki.rendering.block.XDOM} object being traversed.
  *
  * @version $Id$
@@ -60,10 +61,13 @@ public class XHTMLRenderer extends AbstractChainingPrintRenderer implements Init
      * attachments, we get its URL, etc.
      */
     @Inject
     private XHTMLImageRenderer imageRenderer;
 
+    @Inject
+    private HTMLElementSanitizer htmlElementSanitizer;
+
     @Override
     public void initialize() throws InitializationException
     {
         ListenerChain chain = new ListenerChain();
         setListenerChain(chain);
@@ -72,8 +76,9 @@ public void initialize() throws InitializationException
         // placed later in the chain.
         chain.addListener(this);
         chain.addListener(new BlockStateChainingListener(chain));
         chain.addListener(new EmptyBlockChainingListener(chain));
         chain.addListener(new MetaDataStateChainingListener(chain));
-        chain.addListener(new XHTMLChainingRenderer(this.linkRenderer, this.imageRenderer, chain));
+        chain.addListener(new XHTMLChainingRenderer(this.linkRenderer, this.imageRenderer, this.htmlElementSanitizer,
+            chain));
     }
 }
diff --git a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLChainingRendererTest.java b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLChainingRendererTest.java
index 8fce2baa..cd96e9ef 100644
--- a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLChainingRendererTest.java
+++ b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/java/org/xwiki/rendering/internal/renderer/xhtml/XHTMLChainingRendererTest.java
@@ -42,11 +42,11 @@
      * Macro transformation applied).
      */
     @Test
     void outputFigureCaptionEvents()
     {
-        XHTMLChainingRenderer renderer = new XHTMLChainingRenderer(null, null, new ListenerChain());
+        XHTMLChainingRenderer renderer = new XHTMLChainingRenderer(null, null, null, new ListenerChain());
         WikiPrinter wikiPrinter = new DefaultWikiPrinter();
         renderer.setPrinter(wikiPrinter);
         renderer.beginFigureCaption(Collections.emptyMap());
         renderer.onWord("caption");
         renderer.endFigureCaption(Collections.emptyMap());
@@ -55,11 +55,11 @@ void outputFigureCaptionEvents()
     }
 
     @Test
     void onRawText()
     {
-        XHTMLChainingRenderer renderer = new XHTMLChainingRenderer(null, null, new ListenerChain());
+        XHTMLChainingRenderer renderer = new XHTMLChainingRenderer(null, null, null, new ListenerChain());
         WikiPrinter wikiPrinter = new DefaultWikiPrinter();
         renderer.setPrinter(wikiPrinter);
         renderer.onRawText("xhtml/1.0", Syntax.XHTML_1_0);
         renderer.onRawText("html/4.01", Syntax.HTML_4_01);
         renderer.onRawText("html/5.0", Syntax.HTML_5_0);
diff --git a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/resources/xhtml10/simple/monospace/monospace2.inout.txt b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/resources/xhtml10/simple/monospace/monospace2.inout.txt
index bdd537d8..e637cfde 100644
--- a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/resources/xhtml10/simple/monospace/monospace2.inout.txt
+++ b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/resources/xhtml10/simple/monospace/monospace2.inout.txt
@@ -1 +1 @@
-<p><tt><span a="b">monospace</span></tt></p>
\ No newline at end of file
+<p><tt><span data-xwiki-translated-attribute-a="b">monospace</span></tt></p>
\ No newline at end of file
diff --git a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/resources/xhtml10/specific/bold/bold4.test b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/resources/xhtml10/specific/bold/bold4.test
index 440e92a9..156a5a64 100644
--- a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/resources/xhtml10/specific/bold/bold4.test
+++ b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/resources/xhtml10/specific/bold/bold4.test
@@ -1,10 +1,10 @@
 .#-----------------------------------------------------
 .input|xhtml/1.0
 .# Verify that STRONG tag parameters are recognized.
 .#-----------------------------------------------------
-<p><strong a="b" data-xwiki-parameter="value">something</strong></p>
+<p><strong data-xwiki-translated-attribute-a="b" data-xwiki-parameter="value">something</strong></p>
 .#-----------------------------------------------------
 .expect|event/1.0
 .#-----------------------------------------------------
 beginDocument
 beginParagraph
@@ -14,6 +14,6 @@ endFormat [BOLD] [[a]=[b][data-xwiki-parameter]=[value]]
 endParagraph
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<p><strong><span a="b" data-xwiki-parameter="value">something</span></strong></p>
\ No newline at end of file
+<p><strong><span data-xwiki-translated-attribute-a="b" data-xwiki-parameter="value">something</span></strong></p>
\ No newline at end of file
diff --git a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/resources/xhtml10/specific/encoding/encoding1.test b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/resources/xhtml10/specific/encoding/encoding1.test
index ca70f251..b9b2b41c 100644
--- a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/resources/xhtml10/specific/encoding/encoding1.test
+++ b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/resources/xhtml10/specific/encoding/encoding1.test
@@ -1,11 +1,11 @@
 .#-------------------------------------------------------------------------------------
 .input|xhtml/1.0
 .# Verify that HTML entities can be parsed by the XHTML parser and are encoded properly
 .# Note that &nbsp; is transformed into a space.
 .#-------------------------------------------------------------------------------------
-<p>&nbsp;&tilde;&euro;</p><p param1="val&#252;e">&#160;&#732;&#8364;</p>
+<p>&nbsp;&tilde;&euro;</p><p data-xwiki-translated-attribute-param1="val&#252;e">&#160;&#732;&#8364;</p>
 .#-----------------------------------------------------
 .expect|event/1.0
 .#-----------------------------------------------------
 beginDocument
 beginParagraph
@@ -18,6 +18,6 @@ onWord [(((732)))(((8364)))]
 endParagraph [[param1]=[val(((252)))e]]
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<p>&nbsp;˜€</p><p param1="valüe">&nbsp;˜€</p>
\ No newline at end of file
+<p>&nbsp;˜€</p><p data-xwiki-translated-attribute-param1="valüe">&nbsp;˜€</p>
\ No newline at end of file
diff --git a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/resources/xhtml10/specific/group/group1.test b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/resources/xhtml10/specific/group/group1.test
index 99ad9ef8..3ad665ee 100644
--- a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/resources/xhtml10/specific/group/group1.test
+++ b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/test/resources/xhtml10/specific/group/group1.test
@@ -1,10 +1,10 @@
 .#-----------------------------------------------------
 .input|xhtml/1.0
 .# Verify that div tag parameters, also starting with data-xwiki-, are recognized.
 .#-----------------------------------------------------
-<div a="b" data-xwiki-parameter="value">something</div>
+<div data-xwiki-translated-attribute-a="b" data-xwiki-parameter="value">something</div>
 .#-----------------------------------------------------
 .expect|event/1.0
 .#-----------------------------------------------------
 beginDocument
 beginGroup [[a]=[b][data-xwiki-parameter]=[value]]
@@ -14,6 +14,6 @@ endParagraph
 endGroup [[a]=[b][data-xwiki-parameter]=[value]]
 endDocument
 .#-----------------------------------------------------
 .expect|xhtml/1.0
 .#-----------------------------------------------------
-<div a="b" data-xwiki-parameter="value"><p>something</p></div>
\ No newline at end of file
+<div data-xwiki-translated-attribute-a="b" data-xwiki-parameter="value"><p>something</p></div>
\ No newline at end of file
diff --git a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml5/src/test/resources/xhtml5/simple/monospace/monospace2.inout.txt b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml5/src/test/resources/xhtml5/simple/monospace/monospace2.inout.txt
index 03c918ef..cfa6a7cb 100644
--- a/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml5/src/test/resources/xhtml5/simple/monospace/monospace2.inout.txt
+++ b/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml5/src/test/resources/xhtml5/simple/monospace/monospace2.inout.txt
@@ -1 +1 @@
-<p><span a="b" class="monospace">monospace</span></p>
\ No newline at end of file
+<p><span data-xwiki-translated-attribute-a="b" class="monospace">monospace</span></p>
\ No newline at end of file
diff --git a/xwiki-rendering-xml/src/main/java/org/xwiki/rendering/renderer/printer/XHTMLWikiPrinter.java b/xwiki-rendering-xml/src/main/java/org/xwiki/rendering/renderer/printer/XHTMLWikiPrinter.java
index 867df085..28492300 100644
--- a/xwiki-rendering-xml/src/main/java/org/xwiki/rendering/renderer/printer/XHTMLWikiPrinter.java
+++ b/xwiki-rendering-xml/src/main/java/org/xwiki/rendering/renderer/printer/XHTMLWikiPrinter.java
@@ -17,14 +17,19 @@
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
 package org.xwiki.rendering.renderer.printer;
 
+import java.util.Arrays;
+import java.util.LinkedHashMap;
 import java.util.Map;
 
 import org.apache.commons.lang3.StringUtils;
 import org.xml.sax.Attributes;
+import org.xml.sax.helpers.AttributesImpl;
+import org.xwiki.stability.Unstable;
+import org.xwiki.xml.html.HTMLElementSanitizer;
 
 /**
  * Base toolkit class for all XHTML-based renderers. This printer handles whitespaces so that it prints "&nbsp;" when
  * needed (i.e. when the spaces are at the beginning or at the end of an element's content or when there are more than 1
  * contiguous spaces, except for CDATA sections and inside PRE elements. It also knows how to handle XHTML comments).
@@ -32,10 +37,25 @@
  * @version $Id$
  * @since 1.7M1
  */
 public class XHTMLWikiPrinter extends XMLWikiPrinter
 {
+    /**
+     * Prefix that is used for invalid/disallowed attributes.
+     *
+     * @since 14.6RC1
+     */
+    @Unstable
+    public static final String TRANSLATED_ATTRIBUTE_PREFIX = "data-xwiki-translated-attribute-";
+
+    /**
+     * The sanitizer used to restrict allowed elements and attributes, can be null (no restrictions).
+     *
+     * @since 14.6RC1
+     */
+    protected final HTMLElementSanitizer htmlElementSanitizer;
+
     private int spaceCount;
 
     private boolean isInCData;
 
     private boolean isInPreserveElement;
@@ -48,19 +68,29 @@ public class XHTMLWikiPrinter extends XMLWikiPrinter
 
     /**
      * @param printer the object to which to write the XHTML output to
      */
     public XHTMLWikiPrinter(WikiPrinter printer)
+    {
+        this(printer, null);
+    }
+
+    /**
+     * @param printer the object to which to write the XHTML output to
+     * @param htmlElementSanitizer the sanitizer to use for sanitizing elements and attributes
+     */
+    public XHTMLWikiPrinter(WikiPrinter printer, HTMLElementSanitizer htmlElementSanitizer)
     {
         super(printer);
+        this.htmlElementSanitizer = htmlElementSanitizer;
     }
 
     /**
-     * Use it to specify that the current element to print is standalone.
-     * This value might be used to know if the first space should be printed with a simple space or a {@code &nbsp;}
-     * entity. Note that the standalone value is automatically reset after first printing of a space, or when a text
-     * is printed.
+     * Use it to specify that the current element to print is standalone. This value might be used to know if the first
+     * space should be printed with a simple space or a {@code &nbsp;} entity. Note that the standalone value is
+     * automatically reset after first printing of a space, or when a text is printed.
+     *
      * @since 12.2
      */
     public void setStandalone()
     {
         this.isStandalone = true;
@@ -76,62 +106,78 @@ public void printXML(String str)
     }
 
     @Override
     public void printXMLElement(String name)
     {
-        handleSpaceWhenStartElement();
-        super.printXMLElement(name);
+        if (this.htmlElementSanitizer == null || this.htmlElementSanitizer.isElementAllowed(name)) {
+            handleSpaceWhenStartElement();
+            super.printXMLElement(name);
+        }
     }
 
     @Override
     public void printXMLElement(String name, String[][] attributes)
     {
-        handleSpaceWhenStartElement();
-        super.printXMLElement(name, attributes);
+        if (this.htmlElementSanitizer == null || this.htmlElementSanitizer.isElementAllowed(name)) {
+            handleSpaceWhenStartElement();
+            super.printXMLElement(name, cleanAttributes(name, attributes));
+        }
     }
 
     @Override
     public void printXMLElement(String name, Map<String, String> attributes)
     {
-        handleSpaceWhenStartElement();
-        super.printXMLElement(name, attributes);
+        if (this.htmlElementSanitizer == null || this.htmlElementSanitizer.isElementAllowed(name)) {
+            handleSpaceWhenStartElement();
+            super.printXMLElement(name, cleanAttributes(name, attributes));
+        }
     }
 
     @Override
     public void printXMLStartElement(String name)
     {
-        handleSpaceWhenStartElement();
-        super.printXMLStartElement(name);
+        if (this.htmlElementSanitizer == null || this.htmlElementSanitizer.isElementAllowed(name)) {
+            handleSpaceWhenStartElement();
+            super.printXMLStartElement(name);
+        }
     }
 
     @Override
     public void printXMLStartElement(String name, String[][] attributes)
     {
-        handleSpaceWhenStartElement();
-        super.printXMLStartElement(name, attributes);
+        if (this.htmlElementSanitizer == null || this.htmlElementSanitizer.isElementAllowed(name)) {
+            handleSpaceWhenStartElement();
+            super.printXMLStartElement(name, cleanAttributes(name, attributes));
+        }
     }
 
     @Override
     public void printXMLStartElement(String name, Map<String, String> attributes)
     {
-        handleSpaceWhenStartElement();
-        super.printXMLStartElement(name, attributes);
+        if (this.htmlElementSanitizer == null || this.htmlElementSanitizer.isElementAllowed(name)) {
+            handleSpaceWhenStartElement();
+            super.printXMLStartElement(name, cleanAttributes(name, attributes));
+        }
     }
 
     @Override
     public void printXMLStartElement(String name, Attributes attributes)
     {
-        handleSpaceWhenStartElement();
-        super.printXMLStartElement(name, attributes);
+        if (this.htmlElementSanitizer == null || this.htmlElementSanitizer.isElementAllowed(name)) {
+            handleSpaceWhenStartElement();
+            super.printXMLStartElement(name, cleanAttributes(name, attributes));
+        }
     }
 
     @Override
     public void printXMLEndElement(String name)
     {
-        handleSpaceWhenEndlement();
-        super.printXMLEndElement(name);
-        this.elementEnded = true;
+        if (this.htmlElementSanitizer == null || this.htmlElementSanitizer.isElementAllowed(name)) {
+            handleSpaceWhenEndlement();
+            super.printXMLEndElement(name);
+            this.elementEnded = true;
+        }
     }
 
     @Override
     public void printXMLComment(String content)
     {
@@ -183,10 +229,75 @@ private void handleSpaceWhenInText()
         } else {
             handleSpaceWhenEndlement();
         }
     }
 
+    private Map<String, String> cleanAttributes(String elementName, Map<String, String> attributes)
+    {
+        Map<String, String> cleanAttributes;
+
+        if (this.htmlElementSanitizer == null || attributes == null) {
+            cleanAttributes = attributes;
+        } else {
+            cleanAttributes = new LinkedHashMap<>();
+            for (Map.Entry<String, String> e : attributes.entrySet()) {
+                if (this.htmlElementSanitizer.isAttributeAllowed(elementName, e.getKey(), e.getValue())) {
+                    cleanAttributes.put(e.getKey(), e.getValue());
+                } else {
+                    cleanAttributes.put(TRANSLATED_ATTRIBUTE_PREFIX + e.getKey(), e.getValue());
+                }
+            }
+        }
+
+        return cleanAttributes;
+    }
+
+    private String[][] cleanAttributes(String elementName, String[][] attributes)
+    {
+        String[][] allowedAttributes;
+        if (this.htmlElementSanitizer == null || attributes == null) {
+            allowedAttributes = attributes;
+        } else {
+            allowedAttributes = Arrays.stream(attributes)
+                .map(entry -> {
+                    if (this.htmlElementSanitizer.isAttributeAllowed(elementName, entry[0], entry[1])) {
+                        return entry;
+                    } else {
+                        return new String[] { TRANSLATED_ATTRIBUTE_PREFIX + entry[0], entry[1] };
+                    }
+                })
+                .toArray(String[][]::new);
+        }
+
+        return allowedAttributes;
+    }
+
+    private Attributes cleanAttributes(String elementName, Attributes attributes)
+    {
+        Attributes allowedAttribute;
+
+        if (this.htmlElementSanitizer == null || attributes == null) {
+            allowedAttribute = attributes;
+        } else {
+            allowedAttribute = new AttributesImpl();
+
+            for (int i = 0; i < attributes.getLength(); ++i) {
+                if (this.htmlElementSanitizer.isAttributeAllowed(elementName, attributes.getQName(i),
+                    attributes.getValue(i)))
+                {
+                    ((AttributesImpl) allowedAttribute).addAttribute(null, null, attributes.getQName(i),
+                        null, attributes.getValue(i));
+                } else {
+                    ((AttributesImpl) allowedAttribute).addAttribute(null, null,
+                        TRANSLATED_ATTRIBUTE_PREFIX + attributes.getQName(i), null, attributes.getValue(i));
+                }
+            }
+        }
+
+        return allowedAttribute;
+    }
+
     private void handleSpaceWhenStartElement()
     {
         // Use case: <tag1>something <tag2>...
         // Use case: <tag1>something <!--...
         if (this.spaceCount > 0) {

Vulnerable code: <p><span class="wikiexternallink"><a param="value" href="refe||rence">lab&gt;&gt;el~</a></span></p>
<p><!--startwikilink:false|-|url|-|refe||rence--><span class="wikiexternallink"><a param="value" href="refe||rence">lab&gt;&gt;el~</a></span><!--stopwikilink--></p>
<p><!--startwikilink:false|-|url|-|refe||rence--><span class="wikiexternallink"><a param="value" href="refe||rence">lab&gt;&gt;el~</a></span><!--stopwikilink--></p>
<div param="value"><p>some text</p></div><div param="value"><p>some text</p></div>
<div param="value"><p>some text</p></div><div param="value"><p>some text</p></div>
<hr param="value"/>
<html><hr param="value"/></html>
<p><em><span a="b">something</span></em></p>
<dl param="value"><dt>title</dt><dd>definition</dd></dl>
<dl param="value"><dt>title</dt><dd>definition</dd></dl>
<ul param="value"><li>item 1<ul param2="value2"><li>item 1.1<ul><li>item 1.1.1</li></ul></li></ul></li></ul>
<ul param="value"><li>item 1<ul param2="value2"><li>item 1.1<ul><li>item 1.1.1</li></ul></li></ul></li></ul>
<ul param1="value1" param2="value2"><li>item</li></ul>
<html><ul param1="value1" param2="value2"><li>item</li></ul></html>
<span param="value">formatmacro2</span><p><span a="b"><span param="value">formatmacro3</span> text</span></p><p><span a="b">text</span><span param="value">formatmacro4</span></p>
<!--startmacro:testformatmacro|-|--><span param="value">formatmacro2</span><!--stopmacro--><p><span a="b"><!--startmacro:testformatmacro|-|--><span param="value">formatmacro3</span><!--stopmacro--> text</span></p><p><span a="b">text</span><!--startmacro:testformatmacro|-|--><span param="value">formatmacro4</span><!--stopmacro--></p>
<!--startmacro:testformatmacro|-|--><span param="value">formatmacro2</span><!--stopmacro--><p><span a="b"><!--startmacro:testformatmacro|-|--><span param="value">formatmacro3</span><!--stopmacro--> text</span></p><p><span a="b">text</span><!--startmacro:testformatmacro|-|--><span param="value">formatmacro4</span><!--stopmacro--></p>
<p param1="value1" param2="value2"><span param3="value3">hello</span> world</p><p><span param4="valueA">hello&nbsp;</span><span param4="valueB">world</span></p><p><strong><span param5="value4">hello</span></strong><span param5="value4">&nbsp;world</span></p><p><span param6="valueA">hello&nbsp;</span><span param7="valueB">world</span></p><p>before<span param="value">x</span><strong>y</strong>after</p><p>12<strong>34<span param="value">56</span>78</strong>90</p><p><span param="value">1<em>2</em></span><em>3</em></p><p><strong><span param1="value1">1</span></strong><strong><span param2="value2">2</span></strong></p>
<blockquote param1="value1" param2="value2"><p>line</p></blockquote>
<blockquote param1="value1" param2="value2"><p>line</p></blockquote>
<h1 id="Hheader" class="wikigeneratedid" param="value"><span>header</span></h1>
<html><h1 id="Hheader" class="wikigeneratedid" param="value"><span>header</span></h1></html>
<p><del><span a="b">something</span></del></p>
<html><p><sub a="b">something</sub></p></html>
<p><sub><span a="b">something</span></sub></p>
<html><p><sup a="b">something</sup></p></html>
<p><sup><span a="b">something</span></sup></p>
<table a="b"><tr c="d"><th e="f" scope="col"><span g="h">cell1</span></th><td i="j"><span k="l">cell2</span></td></tr></table><table a="b"><tr c="d"><th e="f" scope="col"><span g="h">cell1</span></th><td i="j"><span k="l">cell2</span></td></tr></table>
<table a="b"><tr c="d"><th e="f" scope="col"><span g="h">cell1</span></th><td i="j"><span k="l">cell2</span></td></tr></table><table a="b"><tr c="d"><th e="f" scope="col"><span g="h">cell1</span></th><td i="j"><span k="l">cell2</span></td></tr></table>
<pre param="value">abc</pre>
<html><pre param="value">abc</pre></html>
<p param="value"><span param2="value2"><tt class="wikimodel-verbatim">abc</tt></span></p>
<p param="value"><span param2="value2"><tt class="wikimodel-verbatim">abc</tt></span></p>
<p><img src="imageurl" param1="value1" param2="value2" id="Imy.png" class="wikigeneratedid" alt="my.png"/><br/><img src="imageurl" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/></p>
<p><!--startimage:false|-|attach|-|my.png--><img src="imageurl" param1="value1" param2="value2" id="Imy.png" class="wikigeneratedid" alt="my.png"/><!--stopimage--><br/><!--startimage:false|-|attach|-|Space.ExistingPage@my.png--><img src="imageurl" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/><!--stopimage--></p>
<p><!--startimage:false|-|attach|-|my.png--><img src="imageurl" param1="value1" param2="value2" id="Imy.png" class="wikigeneratedid" alt="my.png"/><!--stopimage--><br/><!--startimage:false|-|attach|-|Space.ExistingPage@my.png--><img src="imageurl" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/><!--stopimage--></p>
<img src="imageurl" param1="value1" param2="value2" id="Imy.png" class="wikigeneratedid" alt="my.png"/><div class="figcaption"><p>Image <strong>Caption</strong></p></div><img src="imageurl" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/><div class="figcaption"><p>Caption</p><ul><li>With</li><li>nested</li><li>list <span class="wikiexternallink"><a href="https://xwiki.org">and link</a></span> and [[fake link]].</li></ul></div>
<figure class="image"><img src="imageurl" param1="value1" param2="value2" id="Imy.png" class="wikigeneratedid" alt="my.png"/><figcaption><p>Image <strong>Caption</strong></p></figcaption></figure><figure class="image"><img src="imageurl" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/><figcaption><p>Caption</p><ul><li>With</li><li>nested</li><li>list <span class="wikiexternallink"><a href="https://xwiki.org">and link</a></span> and [[fake link]].</li></ul></figcaption></figure>
<p><img src="imageurl" param2="value2" id="ISpace.ExistingPage40my.png3Fparam13Dvalue1" class="wikigeneratedid" alt="Space.ExistingPage@my.png?param1=value1"/></p>
<p><!--startimage:false|-|attach|-|Space.ExistingPage@my.png?param1=value1--><img src="imageurl" param2="value2" id="ISpace.ExistingPage40my.png3Fparam13Dvalue1" class="wikigeneratedid" alt="Space.ExistingPage@my.png?param1=value1"/><!--stopimage--></p>
<p><!--startimage:false|-|attach|-|Space.ExistingPage@my.png?param1=value1--><img src="imageurl" param2="value2" id="ISpace.ExistingPage40my.png3Fparam13Dvalue1" class="wikigeneratedid" alt="Space.ExistingPage@my.png?param1=value1"/><!--stopimage--></p>
<p><img src="imageurl?param1=value1" param2="value2" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/></p>
<p><!--startimage:false|-|attach|-|Space.ExistingPage@my.png|-|queryString="param1=value1"--><img src="imageurl?param1=value1" param2="value2" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/><!--stopimage--></p>
<p><!--startimage:false|-|attach|-|Space.ExistingPage@my.png|-|queryString="param1=value1"--><img src="imageurl?param1=value1" param2="value2" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/><!--stopimage--></p>
<p><span class="wikiexternallink"><a param="value" href="http://xwiki.org"><img src="imageurl" height="100" width="100" id="Iattach.png" class="wikigeneratedid" alt="attach.png"/></a></span></p>
<p><!--startwikilink:false|-|url|-|http://xwiki.org--><span class="wikiexternallink"><a param="value" href="http://xwiki.org"><!--startimage:false|-|attach|-|attach.png--><img src="imageurl" height="100" width="100" id="Iattach.png" class="wikigeneratedid" alt="attach.png"/><!--stopimage--></a></span><!--stopwikilink--></p>
<p><!--startwikilink:false|-|url|-|http://xwiki.org--><span class="wikiexternallink"><a param="value" href="http://xwiki.org"><!--startimage:false|-|attach|-|attach.png--><img src="imageurl" height="100" width="100" id="Iattach.png" class="wikigeneratedid" alt="attach.png"/><!--stopimage--></a></span><!--stopwikilink--></p>
<p><span class="wikiattachmentlink"><a param1="value1" param2="value2" href="attachmenturl"><span class="wikigeneratedlinkcontent">my.png</span></a></span><br/><span class="wikiattachmentlink"><a href="attachmenturl"><span class="wikigeneratedlinkcontent">Space.ExistingPage@my.png</span></a></span></p>
<p><!--startwikilink:true|-|attach|-|my.png--><span class="wikiattachmentlink"><a param1="value1" param2="value2" href="attachmenturl"><span class="wikigeneratedlinkcontent">my.png</span></a></span><!--stopwikilink--><br/><!--startwikilink:true|-|attach|-|Space.ExistingPage@my.png--><span class="wikiattachmentlink"><a href="attachmenturl"><span class="wikigeneratedlinkcontent">Space.ExistingPage@my.png</span></a></span><!--stopwikilink--></p>
<p><!--startwikilink:true|-|attach|-|my.png--><span class="wikiattachmentlink"><a param1="value1" param2="value2" href="attachmenturl"><span class="wikigeneratedlinkcontent">my.png</span></a></span><!--stopwikilink--><br/><!--startwikilink:true|-|attach|-|Space.ExistingPage@my.png--><span class="wikiattachmentlink"><a href="attachmenturl"><span class="wikigeneratedlinkcontent">Space.ExistingPage@my.png</span></a></span><!--stopwikilink--></p>
<p><a href="http://reference" param1="value1">http://reference</a></p>
<p><span class="wikiexternallink"><a param1="value1" href="http://reference">http://reference</a></span></p>
<p><span class="wikilink"><a param2="value2" href="viewurl?param1=value1#anchor"><span class="wikigeneratedlinkcontent">Space.ExistingPage</span></a></span></p>
<p><!--startwikilink:false|-|doc|-|Space.ExistingPage|-|queryString="param1=value1" anchor="anchor"--><span class="wikilink"><a param2="value2" href="viewurl?param1=value1#anchor"><span class="wikigeneratedlinkcontent">Space.ExistingPage</span></a></span><!--stopwikilink--></p>
<p><!--startwikilink:false|-|doc|-|Space.ExistingPage|-|queryString="param1=value1" anchor="anchor"--><span class="wikilink"><a param2="value2" href="viewurl?param1=value1#anchor"><span class="wikigeneratedlinkcontent">Space.ExistingPage</span></a></span><!--stopwikilink--></p>
<p><span class="wikilink"><a param1="value1" param2="value2" href="viewurl"><span class="wikigeneratedlinkcontent">Space.ExistingPage</span></a></span><br/><span class="wikicreatelink"><a param="value" href="editurl">label</a></span></p>
<p><!--startwikilink:false|-|doc|-|Space.ExistingPage--><span class="wikilink"><a param1="value1" param2="value2" href="viewurl"><span class="wikigeneratedlinkcontent">Space.ExistingPage</span></a></span><!--stopwikilink--><br/><!--startwikilink:false|-|doc|-|Space.UnknownPage--><span class="wikicreatelink"><a param="value" href="editurl">label</a></span><!--stopwikilink--></p>
<p><!--startwikilink:false|-|doc|-|Space.ExistingPage--><span class="wikilink"><a param1="value1" param2="value2" href="viewurl"><span class="wikigeneratedlinkcontent">Space.ExistingPage</span></a></span><!--stopwikilink--><br/><!--startwikilink:false|-|doc|-|Space.UnknownPage--><span class="wikicreatelink"><a param="value" href="editurl">label</a></span><!--stopwikilink--></p>
        return new XHTMLChainingRenderer(this.linkRenderer, this.imageRenderer, getListenerChain());
        return new AnnotatedHTML5ChainingRenderer(this.linkRenderer, this.imageRenderer, getListenerChain());
        return new AnnotatedXHTMLChainingRenderer(this.linkRenderer, this.imageRenderer, getListenerChain());
        return new HTML5ChainingRenderer(this.linkRenderer, this.imageRenderer, getListenerChain());
            XHTMLImageRenderer imageRenderer, ListenerChain listenerChain)
        super(linkRenderer, imageRenderer, listenerChain);
        chain.addListener(new AnnotatedHTML5ChainingRenderer(this.linkRenderer, this.imageRenderer, chain));
<p><span a="b" class="monospace">monospace</span></p>
        XHTMLImageRenderer imageRenderer, ListenerChain listenerChain)
        super(linkRenderer, imageRenderer, listenerChain);
        chain.addListener(new AnnotatedXHTMLChainingRenderer(this.linkRenderer, this.imageRenderer, chain));
            XHTMLImageRenderer imageRenderer,
        super(linkRenderer, imageRenderer, listenerChain);
            Map<String, String> attributes = new HashMap<>();
            attributes.putAll(parameters);
        chain.addListener(new HTML5ChainingRenderer(this.linkRenderer, this.imageRenderer, chain));
import org.xwiki.rendering.internal.renderer.html5.HTML5ChainingRenderer;
        chainingRenderer = new HTML5ChainingRenderer(linkRenderer, imageRenderer, listenerChain);
                    parameter.getKey().equals(CLASS_ATTRIBUTE) && parameter.getValue().equals(METADATA_CONTAINER_CLASS)
     * @param linkRenderer the object to render link events into XHTML. This is done so that it's pluggable because link
     *            rendering depends on how the underlying system wants to handle it. For example for XWiki we check if
     *            the document exists, we get the document URL, etc.
     * @param imageRenderer the object to render image events into XHTML. This is done so that it's pluggable because
     *            image rendering depends on how the underlying system wants to handle it. For example for XWiki we
     *            check if the image exists as a document attachments, we get its URL, etc.
        ListenerChain listenerChain)
            this.xhtmlWikiPrinter = new XHTMLWikiPrinter(getPrinter());
        chain.addListener(new XHTMLChainingRenderer(this.linkRenderer, this.imageRenderer, chain));
        XHTMLChainingRenderer renderer = new XHTMLChainingRenderer(null, null, new ListenerChain());
        XHTMLChainingRenderer renderer = new XHTMLChainingRenderer(null, null, new ListenerChain());
<p><tt><span a="b">monospace</span></tt></p>
<p><strong a="b" data-xwiki-parameter="value">something</strong></p>
<p><strong><span a="b" data-xwiki-parameter="value">something</span></strong></p>
<p>&nbsp;&tilde;&euro;</p><p param1="val&#252;e">&#160;&#732;&#8364;</p>
<p>&nbsp;˜€</p><p param1="valüe">&nbsp;˜€</p>
<div a="b" data-xwiki-parameter="value">something</div>
<div a="b" data-xwiki-parameter="value"><p>something</p></div>
<p><span a="b" class="monospace">monospace</span></p>
     * Use it to specify that the current element to print is standalone.
     * This value might be used to know if the first space should be printed with a simple space or a {@code &nbsp;}
     * entity. Note that the standalone value is automatically reset after first printing of a space, or when a text
     * is printed.
        handleSpaceWhenStartElement();
        super.printXMLElement(name);
        handleSpaceWhenStartElement();
        super.printXMLElement(name, attributes);
        handleSpaceWhenStartElement();
        super.printXMLElement(name, attributes);
        handleSpaceWhenStartElement();
        super.printXMLStartElement(name);
        handleSpaceWhenStartElement();
        super.printXMLStartElement(name, attributes);
        handleSpaceWhenStartElement();
        super.printXMLStartElement(name, attributes);
        handleSpaceWhenStartElement();
        super.printXMLStartElement(name, attributes);
        handleSpaceWhenEndlement();
        super.printXMLEndElement(name);
        this.elementEnded = true;
Fixed code: <p><span class="wikiexternallink"><a data-xwiki-translated-attribute-param="value" href="refe||rence">lab&gt;&gt;el~</a></span></p>
<p><!--startwikilink:false|-|url|-|refe||rence--><span class="wikiexternallink"><a data-xwiki-translated-attribute-param="value" href="refe||rence">lab&gt;&gt;el~</a></span><!--stopwikilink--></p>
<p><!--startwikilink:false|-|url|-|refe||rence--><span class="wikiexternallink"><a data-xwiki-translated-attribute-param="value" href="refe||rence">lab&gt;&gt;el~</a></span><!--stopwikilink--></p>
<div data-xwiki-translated-attribute-param="value"><p>some text</p></div><div data-xwiki-translated-attribute-param="value"><p>some text</p></div>
<div data-xwiki-translated-attribute-param="value"><p>some text</p></div><div data-xwiki-translated-attribute-param="value"><p>some text</p></div>
<hr data-xwiki-translated-attribute-param="value"/>
<html><hr data-xwiki-translated-attribute-param="value"/></html>
<p><em><span data-xwiki-translated-attribute-a="b">something</span></em></p>
<dl data-xwiki-translated-attribute-param="value"><dt>title</dt><dd>definition</dd></dl>
<dl data-xwiki-translated-attribute-param="value"><dt>title</dt><dd>definition</dd></dl>
<ul data-xwiki-translated-attribute-param="value"><li>item 1<ul data-xwiki-translated-attribute-param2="value2"><li>item 1.1<ul><li>item 1.1.1</li></ul></li></ul></li></ul>
<ul data-xwiki-translated-attribute-param="value"><li>item 1<ul data-xwiki-translated-attribute-param2="value2"><li>item 1.1<ul><li>item 1.1.1</li></ul></li></ul></li></ul>
<ul data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2"><li>item</li></ul>
<html><ul data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2"><li>item</li></ul></html>
<span data-xwiki-translated-attribute-param="value">formatmacro2</span><p><span data-xwiki-translated-attribute-a="b"><span data-xwiki-translated-attribute-param="value">formatmacro3</span> text</span></p><p><span data-xwiki-translated-attribute-a="b">text</span><span data-xwiki-translated-attribute-param="value">formatmacro4</span></p>
<!--startmacro:testformatmacro|-|--><span data-xwiki-translated-attribute-param="value">formatmacro2</span><!--stopmacro--><p><span data-xwiki-translated-attribute-a="b"><!--startmacro:testformatmacro|-|--><span data-xwiki-translated-attribute-param="value">formatmacro3</span><!--stopmacro--> text</span></p><p><span data-xwiki-translated-attribute-a="b">text</span><!--startmacro:testformatmacro|-|--><span data-xwiki-translated-attribute-param="value">formatmacro4</span><!--stopmacro--></p>
<!--startmacro:testformatmacro|-|--><span data-xwiki-translated-attribute-param="value">formatmacro2</span><!--stopmacro--><p><span data-xwiki-translated-attribute-a="b"><!--startmacro:testformatmacro|-|--><span data-xwiki-translated-attribute-param="value">formatmacro3</span><!--stopmacro--> text</span></p><p><span data-xwiki-translated-attribute-a="b">text</span><!--startmacro:testformatmacro|-|--><span data-xwiki-translated-attribute-param="value">formatmacro4</span><!--stopmacro--></p>
<p data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2"><span data-xwiki-translated-attribute-param3="value3">hello</span> world</p><p><span data-xwiki-translated-attribute-param4="valueA">hello&nbsp;</span><span data-xwiki-translated-attribute-param4="valueB">world</span></p><p><strong><span data-xwiki-translated-attribute-param5="value4">hello</span></strong><span data-xwiki-translated-attribute-param5="value4">&nbsp;world</span></p><p><span data-xwiki-translated-attribute-param6="valueA">hello&nbsp;</span><span data-xwiki-translated-attribute-param7="valueB">world</span></p><p>before<span data-xwiki-translated-attribute-param="value">x</span><strong>y</strong>after</p><p>12<strong>34<span data-xwiki-translated-attribute-param="value">56</span>78</strong>90</p><p><span data-xwiki-translated-attribute-param="value">1<em>2</em></span><em>3</em></p><p><strong><span data-xwiki-translated-attribute-param1="value1">1</span></strong><strong><span data-xwiki-translated-attribute-param2="value2">2</span></strong></p>
<blockquote data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2"><p>line</p></blockquote>
<blockquote data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2"><p>line</p></blockquote>
<h1 id="Hheader" class="wikigeneratedid" data-xwiki-translated-attribute-param="value"><span>header</span></h1>
<html><h1 id="Hheader" class="wikigeneratedid" data-xwiki-translated-attribute-param="value"><span>header</span></h1></html>
<p><del><span data-xwiki-translated-attribute-a="b">something</span></del></p>
<html><p><sub data-xwiki-translated-attribute-a="b">something</sub></p></html>
<p><sub><span data-xwiki-translated-attribute-a="b">something</span></sub></p>
<html><p><sup data-xwiki-translated-attribute-a="b">something</sup></p></html>
<p><sup><span data-xwiki-translated-attribute-a="b">something</span></sup></p>
<table data-xwiki-translated-attribute-a="b"><tr data-xwiki-translated-attribute-c="d"><th data-xwiki-translated-attribute-e="f" scope="col"><span data-xwiki-translated-attribute-g="h">cell1</span></th><td data-xwiki-translated-attribute-i="j"><span k="l">cell2</span></td></tr></table><table data-xwiki-translated-attribute-a="b"><tr data-xwiki-translated-attribute-c="d"><th data-xwiki-translated-attribute-e="f" scope="col"><span data-xwiki-translated-attribute-g="h">cell1</span></th><td data-xwiki-translated-attribute-i="j"><span k="l">cell2</span></td></tr></table>
<table data-xwiki-translated-attribute-a="b"><tr data-xwiki-translated-attribute-c="d"><th data-xwiki-translated-attribute-e="f" scope="col"><span data-xwiki-translated-attribute-g="h">cell1</span></th><td data-xwiki-translated-attribute-i="j"><span k="l">cell2</span></td></tr></table><table data-xwiki-translated-attribute-a="b"><tr data-xwiki-translated-attribute-c="d"><th data-xwiki-translated-attribute-e="f" scope="col"><span data-xwiki-translated-attribute-g="h">cell1</span></th><td data-xwiki-translated-attribute-i="j"><span k="l">cell2</span></td></tr></table>
<pre data-xwiki-translated-attribute-param="value">abc</pre>
<html><pre data-xwiki-translated-attribute-param="value">abc</pre></html>
<p data-xwiki-translated-attribute-param="value"><span data-xwiki-translated-attribute-param2="value2"><tt class="wikimodel-verbatim">abc</tt></span></p>
<p data-xwiki-translated-attribute-param="value"><span data-xwiki-translated-attribute-param2="value2"><tt class="wikimodel-verbatim">abc</tt></span></p>
<p><img src="imageurl" data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2" id="Imy.png" class="wikigeneratedid" alt="my.png"/><br/><img src="imageurl" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/></p>
<p><!--startimage:false|-|attach|-|my.png--><img src="imageurl" data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2" id="Imy.png" class="wikigeneratedid" alt="my.png"/><!--stopimage--><br/><!--startimage:false|-|attach|-|Space.ExistingPage@my.png--><img src="imageurl" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/><!--stopimage--></p>
<p><!--startimage:false|-|attach|-|my.png--><img src="imageurl" data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2" id="Imy.png" class="wikigeneratedid" alt="my.png"/><!--stopimage--><br/><!--startimage:false|-|attach|-|Space.ExistingPage@my.png--><img src="imageurl" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/><!--stopimage--></p>
<img src="imageurl" data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2" id="Imy.png" class="wikigeneratedid" alt="my.png"/><div class="figcaption"><p>Image <strong>Caption</strong></p></div><img src="imageurl" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/><div class="figcaption"><p>Caption</p><ul><li>With</li><li>nested</li><li>list <span class="wikiexternallink"><a href="https://xwiki.org">and link</a></span> and [[fake link]].</li></ul></div>
<figure class="image"><img src="imageurl" data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2" id="Imy.png" class="wikigeneratedid" alt="my.png"/><figcaption><p>Image <strong>Caption</strong></p></figcaption></figure><figure class="image"><img src="imageurl" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/><figcaption><p>Caption</p><ul><li>With</li><li>nested</li><li>list <span class="wikiexternallink"><a href="https://xwiki.org">and link</a></span> and [[fake link]].</li></ul></figcaption></figure>
<p><img src="imageurl" data-xwiki-translated-attribute-param2="value2" id="ISpace.ExistingPage40my.png3Fparam13Dvalue1" class="wikigeneratedid" alt="Space.ExistingPage@my.png?param1=value1"/></p>
<p><!--startimage:false|-|attach|-|Space.ExistingPage@my.png?param1=value1--><img src="imageurl" data-xwiki-translated-attribute-param2="value2" id="ISpace.ExistingPage40my.png3Fparam13Dvalue1" class="wikigeneratedid" alt="Space.ExistingPage@my.png?param1=value1"/><!--stopimage--></p>
<p><!--startimage:false|-|attach|-|Space.ExistingPage@my.png?param1=value1--><img src="imageurl" data-xwiki-translated-attribute-param2="value2" id="ISpace.ExistingPage40my.png3Fparam13Dvalue1" class="wikigeneratedid" alt="Space.ExistingPage@my.png?param1=value1"/><!--stopimage--></p>
<p><img src="imageurl?param1=value1" data-xwiki-translated-attribute-param2="value2" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/></p>
<p><!--startimage:false|-|attach|-|Space.ExistingPage@my.png|-|queryString="param1=value1"--><img src="imageurl?param1=value1" data-xwiki-translated-attribute-param2="value2" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/><!--stopimage--></p>
<p><!--startimage:false|-|attach|-|Space.ExistingPage@my.png|-|queryString="param1=value1"--><img src="imageurl?param1=value1" data-xwiki-translated-attribute-param2="value2" id="ISpace.ExistingPage40my.png" class="wikigeneratedid" alt="Space.ExistingPage@my.png"/><!--stopimage--></p>
<p><span class="wikiexternallink"><a data-xwiki-translated-attribute-param="value" href="http://xwiki.org"><img src="imageurl" height="100" width="100" id="Iattach.png" class="wikigeneratedid" alt="attach.png"/></a></span></p>
<p><!--startwikilink:false|-|url|-|http://xwiki.org--><span class="wikiexternallink"><a data-xwiki-translated-attribute-param="value" href="http://xwiki.org"><!--startimage:false|-|attach|-|attach.png--><img src="imageurl" height="100" width="100" id="Iattach.png" class="wikigeneratedid" alt="attach.png"/><!--stopimage--></a></span><!--stopwikilink--></p>
<p><!--startwikilink:false|-|url|-|http://xwiki.org--><span class="wikiexternallink"><a data-xwiki-translated-attribute-param="value" href="http://xwiki.org"><!--startimage:false|-|attach|-|attach.png--><img src="imageurl" height="100" width="100" id="Iattach.png" class="wikigeneratedid" alt="attach.png"/><!--stopimage--></a></span><!--stopwikilink--></p>
<p><span class="wikiattachmentlink"><a data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2" href="attachmenturl"><span class="wikigeneratedlinkcontent">my.png</span></a></span><br/><span class="wikiattachmentlink"><a href="attachmenturl"><span class="wikigeneratedlinkcontent">Space.ExistingPage@my.png</span></a></span></p>
<p><!--startwikilink:true|-|attach|-|my.png--><span class="wikiattachmentlink"><a data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2" href="attachmenturl"><span class="wikigeneratedlinkcontent">my.png</span></a></span><!--stopwikilink--><br/><!--startwikilink:true|-|attach|-|Space.ExistingPage@my.png--><span class="wikiattachmentlink"><a href="attachmenturl"><span class="wikigeneratedlinkcontent">Space.ExistingPage@my.png</span></a></span><!--stopwikilink--></p>
<p><!--startwikilink:true|-|attach|-|my.png--><span class="wikiattachmentlink"><a data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2" href="attachmenturl"><span class="wikigeneratedlinkcontent">my.png</span></a></span><!--stopwikilink--><br/><!--startwikilink:true|-|attach|-|Space.ExistingPage@my.png--><span class="wikiattachmentlink"><a href="attachmenturl"><span class="wikigeneratedlinkcontent">Space.ExistingPage@my.png</span></a></span><!--stopwikilink--></p>
<p><a href="http://reference" data-xwiki-translated-attribute-param1="value1">http://reference</a></p>
<p><span class="wikiexternallink"><a data-xwiki-translated-attribute-param1="value1" href="http://reference">http://reference</a></span></p>
<p><span class="wikilink"><a data-xwiki-translated-attribute-param2="value2" href="viewurl?param1=value1#anchor"><span class="wikigeneratedlinkcontent">Space.ExistingPage</span></a></span></p>
<p><!--startwikilink:false|-|doc|-|Space.ExistingPage|-|queryString="param1=value1" anchor="anchor"--><span class="wikilink"><a data-xwiki-translated-attribute-param2="value2" href="viewurl?param1=value1#anchor"><span class="wikigeneratedlinkcontent">Space.ExistingPage</span></a></span><!--stopwikilink--></p>
<p><!--startwikilink:false|-|doc|-|Space.ExistingPage|-|queryString="param1=value1" anchor="anchor"--><span class="wikilink"><a data-xwiki-translated-attribute-param2="value2" href="viewurl?param1=value1#anchor"><span class="wikigeneratedlinkcontent">Space.ExistingPage</span></a></span><!--stopwikilink--></p>
<p><span class="wikilink"><a data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2" href="viewurl"><span class="wikigeneratedlinkcontent">Space.ExistingPage</span></a></span><br/><span class="wikicreatelink"><a data-xwiki-translated-attribute-param="value" href="editurl">label</a></span></p>
<p><!--startwikilink:false|-|doc|-|Space.ExistingPage--><span class="wikilink"><a data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2" href="viewurl"><span class="wikigeneratedlinkcontent">Space.ExistingPage</span></a></span><!--stopwikilink--><br/><!--startwikilink:false|-|doc|-|Space.UnknownPage--><span class="wikicreatelink"><a data-xwiki-translated-attribute-param="value" href="editurl">label</a></span><!--stopwikilink--></p>
<p><!--startwikilink:false|-|doc|-|Space.ExistingPage--><span class="wikilink"><a data-xwiki-translated-attribute-param1="value1" data-xwiki-translated-attribute-param2="value2" href="viewurl"><span class="wikigeneratedlinkcontent">Space.ExistingPage</span></a></span><!--stopwikilink--><br/><!--startwikilink:false|-|doc|-|Space.UnknownPage--><span class="wikicreatelink"><a data-xwiki-translated-attribute-param="value" href="editurl">label</a></span><!--stopwikilink--></p>
import org.xwiki.xml.html.HTMLElementSanitizer;
    @Inject
    private HTMLElementSanitizer htmlElementSanitizer;

        return new XHTMLChainingRenderer(this.linkRenderer, this.imageRenderer, this.htmlElementSanitizer,
            getListenerChain());
import org.xwiki.xml.html.HTMLElementSanitizer;
    @Inject
    private HTMLElementSanitizer htmlElementSanitizer;

        return new AnnotatedHTML5ChainingRenderer(this.linkRenderer, this.imageRenderer, this.htmlElementSanitizer,
            getListenerChain());
import org.xwiki.xml.html.HTMLElementSanitizer;
    @Inject
    private HTMLElementSanitizer htmlElementSanitizer;

        return new AnnotatedXHTMLChainingRenderer(this.linkRenderer, this.imageRenderer, this.htmlElementSanitizer,
            getListenerChain());
import org.xwiki.xml.html.HTMLElementSanitizer;
    @Inject
    private HTMLElementSanitizer htmlElementSanitizer;

        return new HTML5ChainingRenderer(this.linkRenderer, this.imageRenderer, this.htmlElementSanitizer,
            getListenerChain());
import org.xwiki.xml.html.HTMLElementSanitizer;
     * @param htmlElementSanitizer the HTML element sanitizer to use
            XHTMLImageRenderer imageRenderer, HTMLElementSanitizer htmlElementSanitizer, ListenerChain listenerChain)
        super(linkRenderer, imageRenderer, htmlElementSanitizer, listenerChain);
import org.xwiki.xml.html.HTMLElementSanitizer;
    @Inject
    private HTMLElementSanitizer htmlElementSanitizer;

        chain.addListener(new AnnotatedHTML5ChainingRenderer(this.linkRenderer, this.imageRenderer,
            this.htmlElementSanitizer, chain));
<p><span data-xwiki-translated-attribute-a="b" class="monospace">monospace</span></p>
import org.xwiki.xml.html.HTMLElementSanitizer;
     * @param htmlElementSanitizer the sanitizer to use for sanitizing HTML elements and attributes
        XHTMLImageRenderer imageRenderer, HTMLElementSanitizer htmlElementSanitizer, ListenerChain listenerChain)
        super(linkRenderer, imageRenderer, htmlElementSanitizer, listenerChain);
import org.xwiki.xml.html.HTMLElementSanitizer;
    @Inject
    private HTMLElementSanitizer htmlElementSanitizer;

        chain.addListener(new AnnotatedXHTMLChainingRenderer(this.linkRenderer, this.imageRenderer,
            this.htmlElementSanitizer, chain));
import java.util.LinkedHashMap;
import org.xwiki.xml.html.HTMLElementSanitizer;
     * @param htmlElementSanitizer the sanitizer to use for sanitizing HTML elements and attributes
            XHTMLImageRenderer imageRenderer, HTMLElementSanitizer htmlElementSanitizer,
        super(linkRenderer, imageRenderer, htmlElementSanitizer, listenerChain);
            Map<String, String> attributes = new LinkedHashMap<>(parameters);
import org.xwiki.xml.html.HTMLElementSanitizer;
    @Inject
    private HTMLElementSanitizer htmlElementSanitizer;

        chain.addListener(new HTML5ChainingRenderer(this.linkRenderer, this.imageRenderer, this.htmlElementSanitizer,
            chain));
import org.xwiki.rendering.internal.renderer.html5.HTML5ChainingRenderer;
        chainingRenderer = new HTML5ChainingRenderer(linkRenderer, imageRenderer, null, listenerChain);
import java.util.LinkedHashMap;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.xwiki.rendering.renderer.printer.XHTMLWikiPrinter;
                parameter.getKey().equals(CLASS_ATTRIBUTE) && parameter.getValue().equals(METADATA_CONTAINER_CLASS)

    @Override
    protected Map<String, String> convertParameters(WikiParameters params)
    {
        return maybeRemoveAttributePrefix(super.convertParameters(params));
    }

    @Override
    protected Pair<Map<String, String>, Map<String, String>> convertAndSeparateParameters(WikiParameters params)
    {
        Pair<Map<String, String>, Map<String, String>> result = super.convertAndSeparateParameters(params);
        Map<String, String> genericParameters = result.getRight();

        if (!genericParameters.isEmpty()) {
            genericParameters = maybeRemoveAttributePrefix(genericParameters);
        }

        return new ImmutablePair<>(result.getLeft(), genericParameters);
    }

    private Map<String, String> maybeRemoveAttributePrefix(Map<String, String> attributes)
    {
        Map<String, String> result;

        if (!attributes.isEmpty()) {
            result = new LinkedHashMap<>();

            for (Map.Entry<String, String> entry : attributes.entrySet()) {
                String newKey;
                if (entry.getKey().startsWith(XHTMLWikiPrinter.TRANSLATED_ATTRIBUTE_PREFIX)) {
                    newKey = entry.getKey().substring(XHTMLWikiPrinter.TRANSLATED_ATTRIBUTE_PREFIX.length());
                } else {
                    newKey = entry.getKey();
                }

                result.put(newKey, entry.getValue());
            }
        } else {
            result = attributes;
        }

        return result;
    }
import org.xwiki.xml.html.HTMLElementSanitizer;
    private final HTMLElementSanitizer htmlElementSanitizer;

     * @param linkRenderer the object to render link events into XHTML. This is done so that it's pluggable because
     *     link rendering depends on how the underlying system wants to handle it. For example for XWiki we check if the
     *     document exists, we get the document URL, etc.
     * @param imageRenderer the object to render image events into XHTML. This is done so that it's pluggable
     *     because image rendering depends on how the underlying system wants to handle it. For example for XWiki we
     *     check if the image exists as a document attachments, we get its URL, etc.
     * @param htmlElementSanitizer the sanitizer for XHTML elements
        HTMLElementSanitizer htmlElementSanitizer, ListenerChain listenerChain)
        this.htmlElementSanitizer = htmlElementSanitizer;
            this.xhtmlWikiPrinter = new XHTMLWikiPrinter(getPrinter(), getHtmlElementSanitizer());
    protected HTMLElementSanitizer getHtmlElementSanitizer()
    {
        return this.htmlElementSanitizer;
    }

import org.xwiki.xml.html.HTMLElementSanitizer;
    @Inject
    private HTMLElementSanitizer htmlElementSanitizer;

        chain.addListener(new XHTMLChainingRenderer(this.linkRenderer, this.imageRenderer, this.htmlElementSanitizer,
            chain));
        XHTMLChainingRenderer renderer = new XHTMLChainingRenderer(null, null, null, new ListenerChain());
        XHTMLChainingRenderer renderer = new XHTMLChainingRenderer(null, null, null, new ListenerChain());
<p><tt><span data-xwiki-translated-attribute-a="b">monospace</span></tt></p>
<p><strong data-xwiki-translated-attribute-a="b" data-xwiki-parameter="value">something</strong></p>
<p><strong><span data-xwiki-translated-attribute-a="b" data-xwiki-parameter="value">something</span></strong></p>
<p>&nbsp;&tilde;&euro;</p><p data-xwiki-translated-attribute-param1="val&#252;e">&#160;&#732;&#8364;</p>
<p>&nbsp;˜€</p><p data-xwiki-translated-attribute-param1="valüe">&nbsp;˜€</p>
<div data-xwiki-translated-attribute-a="b" data-xwiki-parameter="value">something</div>
<div data-xwiki-translated-attribute-a="b" data-xwiki-parameter="value"><p>something</p></div>
<p><span data-xwiki-translated-attribute-a="b" class="monospace">monospace</span></p>
import java.util.Arrays;
import java.util.LinkedHashMap;
import org.xml.sax.helpers.AttributesImpl;
import org.xwiki.stability.Unstable;
import org.xwiki.xml.html.HTMLElementSanitizer;
    /**
     * Prefix that is used for invalid/disallowed attributes.
     *
     * @since 14.6RC1
     */
    @Unstable
    public static final String TRANSLATED_ATTRIBUTE_PREFIX = "data-xwiki-translated-attribute-";

    /**
     * The sanitizer used to restrict allowed elements and attributes, can be null (no restrictions).
     *
     * @since 14.6RC1
     */
    protected final HTMLElementSanitizer htmlElementSanitizer;

    {
        this(printer, null);
    }

    /**
     * @param printer the object to which to write the XHTML output to
     * @param htmlElementSanitizer the sanitizer to use for sanitizing elements and attributes
     */
    public XHTMLWikiPrinter(WikiPrinter printer, HTMLElementSanitizer htmlElementSanitizer)
        this.htmlElementSanitizer = htmlElementSanitizer;
     * Use it to specify that the current element to print is standalone. This value might be used to know if the first
     * space should be printed with a simple space or a {@code &nbsp;} entity. Note that the standalone value is
     * automatically reset after first printing of a space, or when a text is printed.
     *
        if (this.htmlElementSanitizer == null || this.htmlElementSanitizer.isElementAllowed(name)) {
            handleSpaceWhenStartElement();
            super.printXMLElement(name);
        }
        if (this.htmlElementSanitizer == null || this.htmlElementSanitizer.isElementAllowed(name)) {
            handleSpaceWhenStartElement();
            super.printXMLElement(name, cleanAttributes(name, attributes));
        }
        if (this.htmlElementSanitizer == null || this.htmlElementSanitizer.isElementAllowed(name)) {
            handleSpaceWhenStartElement();
            super.printXMLElement(name, cleanAttributes(name, attributes));
        }
        if (this.htmlElementSanitizer == null || this.htmlElementSanitizer.isElementAllowed(name)) {
            handleSpaceWhenStartElement();
            super.printXMLStartElement(name);
        }
        if (this.htmlElementSanitizer == null || this.htmlElementSanitizer.isElementAllowed(name)) {
            handleSpaceWhenStartElement();
            super.printXMLStartElement(name, cleanAttributes(name, attributes));
        }
        if (this.htmlElementSanitizer == null || this.htmlElementSanitizer.isElementAllowed(name)) {
            handleSpaceWhenStartElement();
            super.printXMLStartElement(name, cleanAttributes(name, attributes));
        }
        if (this.htmlElementSanitizer == null || this.htmlElementSanitizer.isElementAllowed(name)) {
            handleSpaceWhenStartElement();
            super.printXMLStartElement(name, cleanAttributes(name, attributes));
        }
        if (this.htmlElementSanitizer == null || this.htmlElementSanitizer.isElementAllowed(name)) {
            handleSpaceWhenEndlement();
            super.printXMLEndElement(name);
            this.elementEnded = true;
        }
    private Map<String, String> cleanAttributes(String elementName, Map<String, String> attributes)
    {
        Map<String, String> cleanAttributes;

        if (this.htmlElementSanitizer == null || attributes == null) {
            cleanAttributes = attributes;
        } else {
            cleanAttributes = new LinkedHashMap<>();
            for (Map.Entry<String, String> e : attributes.entrySet()) {
                if (this.htmlElementSanitizer.isAttributeAllowed(elementName, e.getKey(), e.getValue())) {
                    cleanAttributes.put(e.getKey(), e.getValue());
                } else {
                    cleanAttributes.put(TRANSLATED_ATTRIBUTE_PREFIX + e.getKey(), e.getValue());
                }
            }
        }

        return cleanAttributes;
    }

    private String[][] cleanAttributes(String elementName, String[][] attributes)
    {
        String[][] allowedAttributes;
        if (this.htmlElementSanitizer == null || attributes == null) {
            allowedAttributes = attributes;
        } else {
            allowedAttributes = Arrays.stream(attributes)
                .map(entry -> {
                    if (this.htmlElementSanitizer.isAttributeAllowed(elementName, entry[0], entry[1])) {
                        return entry;
                    } else {
                        return new String[] { TRANSLATED_ATTRIBUTE_PREFIX + entry[0], entry[1] };
                    }
                })
                .toArray(String[][]::new);
        }

        return allowedAttributes;
    }

    private Attributes cleanAttributes(String elementName, Attributes attributes)
    {
        Attributes allowedAttribute;

        if (this.htmlElementSanitizer == null || attributes == null) {
            allowedAttribute = attributes;
        } else {
            allowedAttribute = new AttributesImpl();

            for (int i = 0; i < attributes.getLength(); ++i) {
                if (this.htmlElementSanitizer.isAttributeAllowed(elementName, attributes.getQName(i),
                    attributes.getValue(i)))
                {
                    ((AttributesImpl) allowedAttribute).addAttribute(null, null, attributes.getQName(i),
                        null, attributes.getValue(i));
                } else {
                    ((AttributesImpl) allowedAttribute).addAttribute(null, null,
                        TRANSLATED_ATTRIBUTE_PREFIX + attributes.getQName(i), null, attributes.getValue(i));
                }
            }
        }

        return allowedAttribute;
    }