Confluence XHTML Syntax Documentation

Last modified by Raphaël Jakse on 2026/03/23 13:12

Content

Reference

The Confluence XHTML Syntax is what Confluence currently uses to store the content of its pages. It is what you can see:

  • when using the "View Storage Format" feature of Confluence
  • in BodyContent objects with a bodyType equal to 2.

The Confluence XHTML Syntax is basically XHTML (the XML variant of HTML), with a few additional, Confluence-specific tags and attributes, and a few oddities.

Warning

The Confluence XHTML Syntax is an XML dialect that can contain CDATA sections. When stored in a CDATA section in the content property of BodyContent objects, a space is added to CDATA end tag. ]]> becomes ]] >. You will have to pre-process this before parsing the Confluence XML syntax.

Information

We've not seen this syntax ever indented in Confluence exports. If you see indented example, they were either indented by ourselves for readability, or taken from the Confluence "View Storage Format" feature.

Warning

Sometimes, block macros are put inside their own <p> element. But not always. This can surprising, and this need to be carefully handled while parsing or converting the Confluence XHTML syntax.

Warning

Conversely, we have seen inline macros defined by Confluence plugins that are put inside their own #<p># element. We don't know how to handle this and they will appear on their own line (after import) in XWiki.

Confluence-specific tags

ac:caption

<ac:image ac:align="left" ac:layout="align-start" ac:original-height="1200" ac:original-width="1200"
  ac:custom-width="true" ac:alt="some alt text" ac:width="50">
  <ri:attachment ri:filename="rock.jpg" ri:version-at-save="1" />
  <ac:caption>
    <p>sos<em>asdas</em>ame ca<strong>sasd</strong>ion</p>
  </ac:caption>
  <ac:adf-mark key="border" size="2" color="#091e4224" />
</ac:image>

The caption of an image, in the node's body.

ac:default-parameter

<ac:macro ac:name="anchor">
  <ac:default-parameter>value1</ac:default-parameter>
</ac:macro>

Gives the value of the parameter of a macro that doesn't have a name, in its body. Sometimes, <ac:parameter name=""> is used instead, likely with ac:structured-macro. We haven't seen it used several times per macro, rather, at most once.

ac:emoticon

<p>My emoticon: <ac:emoticon ac:name="smile" ac:emoji-shortname=":slight_smile:" ac:emoji-id="1f642" ac:emoji-fallback="(here an emoji, but xwiki.org cannot handle them in documents)" /></p>
<p>New Confluence Cloud emoticon: <ac:emoticon ac:name="cross" ac:emoji-shortname=":cross_mark:" ac:emoji-id="atlassian-cross_mark" ac:emoji-fallback=":cross_mark:" /></p>

An emoticon, that hopefully but doesn't necessarily map well to an emoji. Formerly, Confluence emoticons where a bit like MSN smileys, ancestors of the emojis that are widespread now.

The tag is self-closing. The tag's attributes seem to have changed quite a bit over time, we can't rely on any attribute to be there. Here is an attempt to explain the parameters anyway.

AttributeMeaning
ac:nameThe name of the emoticon
ac:emoji-short-namethe name of the emoji on which one would fallback to render this emoticon
ac:emoji-idthe hexadecimal code of the corresponding emoji character, OR some Confluence-specific name
ac:emoji-fallbackThe emoji itself, OR the emoji short name
Warning

Formerly, emoticons were given with an img tag like in the following:

<img class="emoticon emoticon-warning" title="(warning)" src="http://confluence.atlatian.net/s/en_US/7901/4635873c8e185dc5df37b4e2487dfbef570b5e2c/_/images/icons/emoticons/warning.svg" alt="(warning)" border="0" />

Or with an ac:image tag like in the following:

<ac:image ac:class="emoticon emoticon-smile" ac:title="(L&auml;cheln)" ac:alt="(L&auml;cheln)"><ri:url ri:value="http://confluence.atlatian.net/s/de_DE/7901/4635873c8e185dc5df37b4e2487dfbef570b5e2c/_/images/icons/emoticons/smile.svg" /></ac:image>

ac:image

<p>
<ac:image ac:align="left" ac:layout="align-start" ac:original-height="1200" ac:original-width="1200"
  ac:custom-width="true" ac:alt="some alt text" ac:width="50">
  <ri:attachment ri:filename="rock.jpg" ri:version-at-save="1" />
  <ac:caption>
    <p>sos<em>asdas</em>ame ca<strong>sasd</strong>ion</p>
  </ac:caption>
  <ac:adf-mark key="border" size="2" color="#091e4224" />
</ac:image>

<ac:image ac:border="true" ac:height="217" ac:width="524">
  <ri:attachment ri:filename="image.png">
    <ri:page ri:content-title="pagetovalidate" ri:space-key="spacetovalidate"/>
  </ri:attachment>
</ac:image>
</p>

An image. If the image displays an attachment, it is given using a ri:url tag, possibly with a relative value, or a ri:attachment tag. A caption can be given with the ac:caption tag. Some styling can be given with an ac:adf-mark key.

AttributeMeaning
ac:alignHow the image is aligned (we know about these values: "left", "right", "center")
ac:layoutHow the image is organised (we know about these values: "align-start", "align-end", "center", "wrap-left", "wrap-right")
ac:original-widthThe original width of the image
ac:original-heightThe original height of the image
ac:custom-widthWhether a custom width is applied to the image. Note: supposedly, an ac:custom-height attribute exists but we've not seen it yet.
ac:widthThe custom width (optional)
ac:heightThe custom height (optional)
ac:altThe alternative text (same as the standard HTML alt attribute of the standard HTML img element)
ac:borderWhether the image has a border (but also note the ac:adf-mark key="border" element present in the first example which doesn't have an ac:border attribute)

ac:inline-comment-marker

<p>before<ac:inline-comment-marker ac:ref="21641e47-9393-4d3c-890f-0994b2181443">annotation</ac:inline-comment-marker>after</p>

Surrounds a text commented in an inline comment.

ac:layout

<ac:layout>
  <ac:layout-section ac:type="two_equal" ac:breakout-mode="default">
    <ac:layout-cell><p>Test1</p></ac:layout-cell>
    <ac:layout-cell><p>Test2</p></ac:layout-cell>
  </ac:layout-section>
  <ac:layout-section ac:type="fixed-width" ac:breakout-mode="default">
    <ac:layout-cell><p /></ac:layout-cell>
  </ac:layout-section>
</ac:layout>

Defines a layout.

ac:layout-cell

Defines a cell in a layout. See ac:layout.

ac:layout-section

Defines a section in a layout. See ac:layout.

<p><ac:link ac:card-appearance="inline"><ri:page ri:content-title="Under Page A" ri:version-at-save="2" /><ac:link-body>Under Page A</ac:link-body></ac:link></p>
<p><ac:link><ri:user ri:username="UserName" /></ac:link></p>
<p><ac:link><ri:user ri:userkey="ff80808156e241950156e468e9510003" /></ac:link></p>
<p><ac:link ac:anchor="myanchor"><ac:plain-text-link-body><![CDATA[correctly migrated label]] ></ac:plain-text-link-body></ac:link></p>
<p><ac:link ac:tooltip="an empty link"><ac:plain-text-link-body><![CDATA[this page]] ></ac:plain-text-link-body></ac:link></p>
<ac:structured-macro ac:name="pagetree" ac:schema-version="1" ac:local-id="7725dd30-f42e-4a74-babd-e3ce084d7398" ac:macro-id="67ee8bead41558eb6e8678e51d4d95665af4b328f23ae8d4b567c27a480b59a6">
  <ac:parameter ac:name="root">
    <ac:link><ri:page ri:content-title="@self" /></ac:link>
  </ac:parameter>
  <ac:parameter ac:name="startDepth">1</ac:parameter>
</ac:structured-macro>

Defines a link to a page or to a user. Appears directly in a paragraph or in a macro parameter.

AttributeMeaning
ac:card-appearanceHow the link is rendered in Confluence
ac:anchorThe target anchor
ac:tooltipThe link's tooltip
  • The target of the link (anchor excluded: it is defined as an attribute) is defined in a child ri:* element (ri:url, ri:page, ri:blog-post, ri:space, ri:user).
  • The body is defined using either:
    • an ac:plain-text-link-body element, which defines a plain text body
    • an ac:link-body element, which defines a (potentially rich) text body

If no child element defines any target, the target is by default the current page. It is also possible that a link doesn't have a body. Thus, <ac:link /> is a link to the current page.

An element which content defines the body of the surrounding ac:link element. See ac:link.

ac:macro

<ac:macro ac:name="anchor"><ac:default-parameter>anchorintitle</ac:default-parameter></ac:macro>
<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[code block text]]></ac:plain-text-body></ac:macro>

An element that marks the usage of a macro. Probably an older way of doing this, see also ac:structured-macro.

AttributeMeaning
ac:nameThe name of the macro

The macro parameters are given as child elements (ac:default-parameter [a nameless parameter], and ac:parameter). The body of the macro is given using an ac:plain-text-body or an ac:rich-text-body element.

ac:parameter

<ac:structured-macro ac:name="panel" ac:schema-version="1" ac:macro-id="bc82cb0f-6564-4928-a24c-f325fc29da0f">
  <ac:parameter ac:name="bgColor">#E3FCEF</ac:parameter>
  <ac:rich-text-body>
    <h2><strong>Welcome to your new space!</strong></h2>
    <p>Spaces help your team structure, organize, and share work, so every team member has visibility into institutional knowledge and access to the information they need to do their best work.</p>
  </ac:rich-text-body>
</ac:structured-macro>

Specifies the value of the parameter of the given name for the macro in which the node is. The value is in the body of the node.

AttributeMeaning 
ac:nameThe name of the parameter

ac:placeholder

<h2>Discussion items</h2><table><tbody><tr><th>Item</th><th>Notes</th></tr><tr><td><ac:placeholder>Agenda item</ac:placeholder></td><td><ul><li><ac:placeholder>Notes for this agenda item</ac:placeholder></li></ul></td></tr><tr><td>&nbsp;</td><td>&nbsp;</td></tr></tbody></table><h2>Action items</h2><ac:task-list>
<ac:task>
<ac:task-id>1</ac:task-id>
<ac:task-status>incomplete</ac:task-status>
<ac:task-body><ac:placeholder ac:type="mention">Type your task here. Use &quot;@&quot; to assign a user and &quot;//&quot; to select a due date.</ac:placeholder><p>&nbsp;</p></ac:task-body>
</ac:task>
</ac:task-list>

Defines a placeholder in a space template. Its content is intended for a user to be replaced in when creating a page from a template, and describes what it should be replaced with.

AttributeMeaning
ac:typeWe don't really know.

ac:plain-text-body

The plain text body of a macro. From what we have seen, the content is inside a CDATA section.

An element which content defines the plain text body of the surrounding ac:link element. See ac:link.

ac:rich-text-body

The rich-text body of a macro. From what we have seen, the content is not inside a CDATA section.

ac:structured-macro

<p>
  <ac:structured-macro ac:name="livesearch" ac:schema-version="1" ac:local-id="1b06a399-a2ea-4e7f-8605-644926a58266" ac:macro-id="6b3a5eca5933839827ef50a69a6723f4acac920ca178daa759820b3c376858c2">
    <ac:parameter ac:name="spaceKey">
      <ri:space ri:space-key="currentSpace()" />
    </ac:parameter>
    <ac:parameter ac:name="size">large</ac:parameter>
    <ac:parameter ac:name="additional">none</ac:parameter>
  </ac:structured-macro>
</p>

An element that marks the usage of a macro. Formerly help ac:macro.

AttributeMeaning
ac:nameThe name of the macro
ac:local-idAn id for the macro. Not always there.
ac:macro-idAn id for the macro. From what we have seen, it is always present, and unique per Confluence site
ac:schema-version

We are not sure, we have seen "1" or "2" as values for this attribute

data-layoutWe are not sure. it's not always there but we've always ever seen "default" for this attribute

ac:task

<ac:task-list>
<ac:task>
<ac:task-id>1</ac:task-id>
<ac:task-status>incomplete</ac:task-status>
<ac:task-body><ac:placeholder ac:type="mention">Type your task here. Use &quot;@&quot; to assign a user and &quot;//&quot; to select a due date.</ac:placeholder><p>&nbsp;</p></ac:task-body>
</ac:task>
</ac:task-list>

A task inside a task list, which has an id, a status and a body defined as child elements.

ac:task-body

The rich text body of a task, not inside a CDATA section. Can contain block elements like paragraphs.

ac:task-id

The identifier of a task, defined as an integer given as a child text node.

ac:task-list

A list of tasks containing ac:task elements.

ac:task-status

The status of a task, defined as a child text node. We've seen complete and incomplete.

at:declarations

<at:declarations>
  <at:string at:name="currentDateLozenge" />
</at:declarations>

A template declaration block, inside which space template variables are defined. Variables are fields that are filled by the user when creating a page from a template. Uses of these variables with the at:var element will be replaced with the filled values.

at:string

Defines a string template parameter. This is a self-closing tag.

AttributeMeaning
at:nameThe name of the template variable

at:var

<at:declarations> <at:string at:name="currentDateLozenge" /> </at:declarations> <h2>Date</h2> <p> <at:var at:name="currentDateLozenge" at:rawxhtml="true" /> </p>
 

AttributeMeaning
at:nameThe name of the template variable
at:rawxhtmlWe don't know what this boolean does

ri:* elements

ri:* elements define targets. They appear in the content of ac:link elements, ac:image elements or macro parameters (sometimes inside an ac:link element which is inside an ac:parameter element, we've not found a definitive, consistent rule about this).

They are usually self-closing tags, from what we've seen.

ri:attachment

<ac:image><ri:attachment ri:filename="image.png"><ri:page ri:content-title="page" ri:space-key="SPACE" /></ri:attachment></ac:image>
<ri:attachment ri:filename="[email protected]" ri:version-at-save="1" />

Targets an attachment. This one is *not* a self-closing tag. Its content further refines where to find the attachment, with an ri:page or ri:space element. If absent, the attachment is on the current page. If the ri:space element is used, the attachment is to be found in the home page.

AttributeMeaning
ri:filenameThe filename of the attachment
ri:version-at-saveNot always there, supposedly the version of the attachment when the content was edited (an integer corresponding to the version parameter of the Attachment object)
Warning

On XWiki, @ typically separate the page name and the attachment filename, but it is a valid character in attachment filename and we've seen this in the wild. See https://jira.xwiki.org/browse/CONFLUENCE-378

ri:url

<ri:url ri:value="image.png" />
<ri:url ri:value="https://twitter.com/XWiki/status/1808056434883502509"/>

Defines a relative URL (usually to an attachment), or an absolute URL

AttributeMeaning
ri:valuethe relative or absolute URL

ri:page

<ri:attachment ri:filename="file.png">
  <ri:page ri:content-title="My Page" ri:space-key="SPACE" />
</ri:attachment>
AttributeMeaning
ri:content-titleThe content title of the targeted page. Can be a special "@" value like @self (the current page) or @home (the home page of the given space)
ri:space-keyThe space in which to find the content type. If not present, the current space is to be used, unless the space is given separately (e.g. in another macro parameter - for example, the view-file macro is like this)
ri:version-at-saveNot always there, supposedly the version of the page when the link was added (an integer corresponding to the version parameter of the Page object)

ri:blog-post

<ac:link><ri:blog-post ri:content-title="Blog post" ri:posting-day="2023/09/27" /></ac:link>

Targets a blog post. Otherwise similar to ri:page.

AttributeMeaning
ri:content-title

The content title of the targeted page. Supposedly, can be a special "@" value like @self (the current page)

ri:posting-dayAn YYYY/MM/DD date of when the target blog post was posted
ri:space-keySupposedly possibly present. The space in which to find the content type. If not present, the current space is to be used, unless the space is given separately (e.g. in another macro parameter - for example, the view-file macro is like this)
ri:version-at-saveSupposedly possibly present. Supposedly the version of the page when the link was added (an integer corresponding to the version parameter of the BlogPost object)

ri:space

<ri:space ri:space-key="DEMO" />

<ac:structured-macro ac:name="livesearch" ac:schema-version="1" ac:local-id="1b06a399-a2ea-4e7f-8605-644926a58266" ac:macro-id="6b3a5eca5933839827ef50a69a6723f4acac920ca178daa759820b3c376858c2">
    <ac:parameter ac:name="spaceKey">
        <ri:space ri:space-key="currentSpace()" />
    </ac:parameter>
    <ac:parameter ac:name="size">large</ac:parameter>
    <ac:parameter ac:name="additional">none</ac:parameter>
</ac:structured-macro>

Targets a space.

AttributeMeaning
ri:space-keyThe space in which to find the content type. Can be a special value like currentSpace()

ri:user

<ac:link><ri:user ri:username="UserName" /></ac:link>
<ac:link><ri:user ri:account-id="ff80808156e241950156e468e9510003" /></ac:link>
<ac:link><ri:user ri:userkey="ff80808156e241950156e468e9510003" /></ac:link>

Targets a user. We describe three parameters we've seen to specify the users and only one is present at a time from what we've seen.

AttributeMeaning
ri:usernameThe username of the target user
ri:account-idThe account id of the target user
ri:userkeyThe user key of the target user

ac:adf-extension

<ac:adf-extension>
  <ac:adf-node type="panel">
    <ac:adf-attribute key="panel-type">note</ac:adf-attribute>
    <ac:adf-content>
      <p>This is a note (woaw)</p>
    </ac:adf-content>
  </ac:adf-node>
  <ac:adf-fallback>
    <div class="panel conf-macro output-block" style="background-color: rgb(234,230,255);border-color: rgb(153,141,217);border-width: 1.0px;">
      <div class="panelContent" style="background-color: rgb(234,230,255);">
        <p>This is a note (woaw)</p>
      </div>
    </div>
  </ac:adf-fallback>
</ac:adf-extension>

Some sort of macro (which we will call ADF macro) with a fallback.

ac:adf-fallback

The XHML fallback to use (given in the content of the node) if the macro is not supported.

ac:adf-node

The non-fallback definition of the ADF macro.

AttributeMeaning
ri:typeThe name of the ADF macro

ac:adf-attribute

An ADF macro parameter. The value is given in the content of the node.

AttributeMeaning
keythe name of the parameter

ac:adf-content

The content of the macro, given in the content of the node.

ac:adf-mark

<ac:image ac:align="left" ac:layout="align-start" ac:original-height="1200" ac:original-width="1200" ac:custom-width="true" ac:alt="some alt text" ac:width="50">
  <ri:attachment ri:filename="rock.jpg" ri:version-at-save="1" />
  <ac:caption>
    <p>sos<em>asdas</em>ame ca<strong>sasd</strong>ion</p>
  </ac:caption>
  <ac:adf-mark key="border" size="2" color="#091e4224" />
</ac:image>

Seems to define styling. Seen as a direct child of the ac:image macro. The possible parameters might depend the value of the key attribute

AttributeMeaning
keyThe type of mark. We know about "border"
size (for key="border")The size of the border
color (for key="border")The color of the border

Standard HTML tags with specific considerations

img

<img class="emoticon emoticon-warning" title="(warning)" src="http://confluence.atlatian.net/s/en_US/7901/4635873c8e185dc5df37b4e2487dfbef570b5e2c/_/images/icons/emoticons/warning.svg" alt="(warning)" border="0" />

Formerly used to represent emoticons. See ac:emoticon. And possibly regular images.

a

Defines a link in some text, or in a macro parameter. Works like the usual XHTML element of the same name. See also ac:link.

Quirks

Remains of the WYSIWYG editor's cursor

Confluence XHTML documents are full of <p class="auto-cursor-target"><br /></p> elements. They need to be cleaned up because they are artifacts of the wysiwyg edition and they don't do anything in Confluence. However, they would cause new lines in XWiki if not handled carefully. 

See:

Some inline macros are outside the paragraph inside which they are supposed to be

And instead, we have a paragraph (p tag), then this inline macro outside any paragraph, and then a new p tag.

We believe this is caused by some third party extensions, that this also creates issues in Confluence (including in edit mode), but some hack probably make it so that these inline macros seem like this whole paragraph -inline macro - paragraph chain is a unique paragraph.

We don't currently handle this at all because it seems complicated to do given how the XHTML parsing is done.

Get Connected