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

Show last authors
1 {{warning}}
2 This document probably needs to be split into several documents, and also some of it probably needs to be moved to the [[dev documentation>>doc:documentation.extensions.dev.confluence.WebHome]].
3 {{/warning}}
4
5 {{toc/}}
6
7 == Introduction ==
8
9 XWiki and Confluence reference documents quite differently. XWiki references document using their full names, whereas Confluence have several ways of doing this:
10
11 * from its space key and its page title, in a case insensitive way
12 * from its (stable) page id
13 * using special ##@## keywords like ##@home##, ##@self##, ##@parent##.
14
15 Spaces can also be referenced, through their space key or through special keywords like ##currentSpace()## (and actually, since we migrated Confluence space home pages to the target XWiki space's WebHome page, ##@home## requires exactly the same resolution as ##currentSpace()##)
16
17 Attachments are occasionally referenced through their id as well (which we mostly don't currently handle).
18
19 This makes things difficult to handle at import time as well as when displaying the imported content, that may reference documents and spaces in macro parameters (including inside [[CQL queries>>extensions:Extension.CQL.WebHome]]) and links we failed to convert.
20
21 In this document, we describe how we handle Confluence references and what are our strategies for tackling the difficulties
22
23 {{info}}
24 We can sometime see the use of ##@global## or ##@all## in Confluence macro parameters. They respectively refer to "the wiki globally", or "all the spaces". We don't have an equivalent in XWiki. We don't currently have a feature to list all the migrated spaces (although it should not be impossible to do), and it's not even sure it would be the right thing to do (maybe the related feature ought to take other XWiki content in account as well). As for using the main wiki, it would only work if nothing is imported into subwikis.
25 {{/info}}
26
27 == Confluence references ==
28
29 === Overview ===
30
31 Sometimes, Confluence XML can't convert a Confluence reference to a proper XWiki reference. Usually, that's because we lack the information needed to build the correct reference. This information is:
32
33 * where the space in which the referenced page lives is migrated (it is not necessarily at the root of the main wiki, because of the [[root parameter>>documentation.extensions.admin.confluence.input-parameters.WebHome]]).
34 * the hierarchy between the root of the space and the page (all its ancestor pages)
35
36 This information can be missing when, for instance, a link references a page in a space that has not been imported yet.
37
38 In this case, Confluence XML issues references. There are currently 3 kinds of Confluence references:
39
40 * ##confluenceSpace##: a reference to a confluence space, to be converted to the XWiki space reference where the Confluence space was imported
41 * ##confluencePage##: a reference to a confluence page, to be converted to the corresponding XWiki document reference
42 ** ##confluencePage:page:SPACE.PAGETITLE## for a page with the given space key and page title
43 ** ##confluencePage:id:ID@FILENAME## for a page with the given page id
44 * ##confluenceAttach##: a reference to a Confluence attachment
45 ** ##confluenceAttach:spaceHome:SPACE@FILENAME## for an attachment on the home page of the given space
46 ** ##confluenceAttach:page:SPACE.PAGETITLE@FILENAME## for an attachment on a page with the given space key and page title
47 ** ##confluenceAttach:id:ID@FILENAME## for an attachment on a page with the given page id
48
49 ==== Current implementation ====
50
51 Confluence references are currently implemented in the [[##confluence-resource-reference-type-parsers## module>>url:https://github.com/xwiki-contrib/confluence/blob/master/confluence-resource-reference-type-parsers/]] as resource reference type parsers, which means that they are transparently converted to XWiki reference whenever possible when parsing a XWiki document. This has a few implications:
52
53 * successfully converted Confluence references do not show up in the the document's XDOM, it's like if the corresponding XWiki references were always there and not the Confluence references.
54 * parsing a XWiki document with Confluence references is potentially costly, because confluence resolvers are called and Solr queries are fired by the default confluence resolvers
55 * when saving a document containing successfully converted Confluence references, the conversions will happen automatically (documents are somehow automatically "fixed"), and the conversions will appear in the diff.
56
57 ==== Alternative implementation ====
58
59 It would be possible to handle Confluence references differently and have it work anyway. For instance, instead of implementing resource reference type parsers, we could have implemented [[##XHTMLLinkRenderer##>>https://github.com/xwiki/xwiki-rendering/tree/master/xwiki-rendering-syntaxes/xwiki-rendering-syntax-xhtml/src/main/java/org/xwiki/rendering/internal/renderer/xhtml/link/XHTMLLinkRenderer.java]], which converts links when rendering to HTML, not when not parsing the XDOM. This has a few (blocking) drawbacks:
60
61 * ##XHTMLLinkRenderer## is internal and should not be relied upon has since it's internal, it could disappear
62 * The pages won't self heal when edited and saved, the confluence references are staying (although it can be seen as an advantage too)
63 * The handling is specific to the HTML output, you would need to implement something similar and specific for each output format
64
65 Should you want to go ahead and implement such a HTML link renderer, you could take inspiration from [[this untested implementation>>attach:ConfluencePageXHTMLLinkTypeRenderer.java]]. You will also need to provide a minimal, alternative implementation for them [[with a higher priority to override>>extensions:Extension.Component Module||anchor="HOverrides"]] the standard ones (which you can also make sure not to install), such as:
66
67 {{code language="java"}}
68 @Component
69 @Named("confluenceAttach")
70 @Singleton
71 public class CustomConfluenceAttachResourceReferenceTypeParser implements ResourceReferenceTypeParser
72 {
73 private static final ResourceType CONFLUENCE_ATTACH = new ResourceType("confluenceAttach");
74
75 @Override
76 public ResourceType getType()
77 {
78 return CONFLUENCE_ATTACH;
79 }
80
81 @Override
82 public ResourceReference parse(String reference)
83 {
84 return new ResourceReference(reference, CONFLUENCE_ATTACH);
85 }
86 }
87 {{/code}}
88
89 This would need to be done for each of the three Confluence reference types.
90
91 ==== Getting rid of Confluence references ====
92
93 It's not nice to have Confluence references in XWiki content. They do mostly work, but they are costly, are not handled by a lot of stuff and are simply not idiomatic. We also do issue Confluence references at places where they are not supported, like in the reference parameter of the display macro.
94
95 We advise getting rid of Confluence when possible. No tool exists for this in standard XWiki or in a contrib extension, but the rough idea on how to do it is:
96
97 * Browse your documents and parse them as XDOM
98 * In each document, look for references beginning with confluencePage:, confluenceSpace: or confluenceAttach: inside references or macro parameters
99 * Parse them, following the description detailed in the overview section
100 * Call the confluence resolvers
101 * Update the document
102
103 {{info}}
104 If you have the Confluence resource reference type parsers installed, there is no need to browse references, because the ones that can be fixed are fixed at parse time. You only need to look inside macro parameters. To know whether you need to save documents, you can compare the number of occurrence of "confluence" in the source, and then in the serialized XDOM.
105 {{/info}}
106
107 {{info}}
108 You may also want to find Confluence absolute URLs and to try converting them as well
109 {{/info}}
110
111 (% class="wikigeneratedid" %)
112 You can take inspiration from [[this implementation>>https://github.com/xwikisas/application-confluence-migrator-pro/blob/main/application-confluence-migrator-pro-reference-fixer/application-confluence-migrator-pro-reference-fixer-api/src/main/java/com/xwiki/confluencepro/referencefixer/internal/ConfluenceReferenceFixer.java]].
113
114 == Confluence resolvers ==
115
116 We do our best not to rely on the way Confluence references documents and spaces after importing the content, but that's not completely avoidable:
117
118 * often, it is not possible to convert links at import times.
119 * Some macros and bridges reference Confluence stuff the Confluence way (space key + page title, or id, or special keywords). Including macros using [[CQL>>https://github.com/xwikisas/application-confluence-migrator-pro/blob/main/application-confluence-migrator-pro-reference-fixer/application-confluence-migrator-pro-reference-fixer-api/src/main/java/com/xwiki/confluencepro/referencefixer/internal/ConfluenceReferenceFixer.java]], which has such properties as "ancestor", "space", "parent", "title".
120 * we have a [[strategy to handle old Confluence links>>extensions:Extension.Confluence.URL Mapping.WebHome]] that could be hanging out in people's emails, chat history and bookmarks.
121
122 At import time, links to other spaces also often exist, and resolving links we can resolve at import time is useful too.
123
124 We therefore provide [[interfaces>>https://github.com/xwiki-contrib/confluence/tree/master/confluence-resolvers/src/main/java/org/xwiki/contrib/confluence/resolvers]] to query the wiki for Confluence things. Best is to have a look at the Javadoc, but in short:
125
126 * ##ConfluencePageIdResolver## defines a ##getDocumentById(long id)## method to find a document using its Confluence id
127 * ##ConfluencePageTitleResolver## defines a ##getDocumentByTitle(String spaceKey, String title)## method to find a document using its Confluence space key and Confluence page title
128 * ##ConfluenceSpaceKeyResolver## defines a ##getSpaceByKey(String spaceKey)## method to find where a Confluence space was imported and returns a reference of type ##EntityType.SPACE##
129 * ##ConfluenceSpaceResolver## defines two methods:
130 ** ##getSpace(EntityReference reference)## return the root of the Confluence space which the given document belongs to
131 ** ##getSpaceKey(EntityReference reference)## returns the Confluence space key of the space in which the given document lives
132
133 The [[default implementation of each of these interfaces>>https://github.com/xwiki-contrib/confluence/tree/master/confluence-resolvers/src/main/java/org/xwiki/contrib/confluence/resolvers/internal]] loops over the all the available implementations and stops as soon as one finds a result.
134
135 An [[implementation for all these interfaces relying on ##Confluence.Code.ConfluencePageClass##>>https://github.com/xwiki-contrib/confluence/blob/master/confluence-resolvers/src/main/java/org/xwiki/contrib/confluence/resolvers/internal/PageClassConfluenceResolver.java]] is provided. These objects are, by default, available for each document imported using Confluence XML (but this can be disabled). They store important information like the page id, the space key and the title of documents coming from Confluence.
136
137 This means that by default, you should be fully able to inject these interfaces as components in your own components and query the wiki and expect this to work.
138
139 {{warning}}
140 This won't work with content imported with the "Store confluence details" parameter of Confluence XML set to false.
141 \\This was notably the case for all contents imported before mid-2024, except for content imported using the [[unmaintained application-confluence-migrator>>https://github.com/xwikisas/application-confluence-migrator]] starting from version 1.0-rc-2 released in November 2021.
142 {{/warning}}
143
144 {{info}}
145 Confluence resolvers are designed to be extended and to welcome alternative implementations, as well as to support multiple implementations at the same time. This means that you can provide your custom way of resolving things. For instance, you can write an implementation that uses data from extracted from the Confluence database. You might be able to bring support for content imported a while ago for instance.
146
147 Since Confluence XML calls Confluence resolvers at import time too, you can also help Confluence XML convert links at import time for spaces that have not been imported yet this way, if you know in advance where each space is going to be imported.
148 {{/info}}
149
150 {{warning}}
151 Confluence is generally case insensitive, but the default implementation of the Confluence resolvers [[is case sensitive>>https://jira.xwiki.org/browse/CONFLUENCE-481]]. This is a big limitation that should be easy to lift as soon as we start [[indexing string properties case insensitively in Solr>>https://forum.xwiki.org/t/add-the-ability-to-do-case-insensitive-solr-search-for-stringproperty-and-listproperty/16955]].
152
153 Confluence resolvers formerly used HQL which does have a ##lower## function, but:
154
155 * this doesn't work well in a multi wiki setting (we would have to loop over all the wikis)
156 * ##lower## ruins performance anyway, because it invalidates the use of indexes
157 {{/warning}}
158
159 === Confluence URL conversion ===
160
161 At import time, Confluence XML goes out of it way to convert Confluence absolute URLs to proper XWiki references.
162
163 Like confluence resolvers, this is extensible and outside code can provide URL converters by implementing [[ConfluenceURLConverter>>https://github.com/xwiki-contrib/confluence/tree/master/confluence-syntax-xhtml/src/main/java/org/xwiki/contrib/confluence/parser/xhtml/ConfluenceURLConverter.java]]. Confluence XML provides a convenient base class for doing this, [[AbstractConfluenceURLConverter>>https://github.com/xwiki-contrib/confluence/blob/master/confluence-xml/src/main/java/org/xwiki/contrib/confluence/filter/url/AbstractConfluenceURLConverter.java]].
164
165 A URL converter implements the convertURL method that takes a strings, and return the corresponding resource reference, or null if the converter does not know how to convert this URL. The [[default implement>>https://github.com/xwiki-contrib/confluence/blob/master/confluence-xml/src/main/java/org/xwiki/contrib/confluence/filter/url/internal/DefaultConfluenceURLConverter.java]] loops over all the available converters and stops as soon as one can convert the URL. Confluence XML comes with [[a converter that converts the widespread standard Confluence URLs>>https://github.com/xwiki-contrib/confluence/blob/master/confluence-xml/src/main/java/org/xwiki/contrib/confluence/filter/url/internal/BaseConfluenceURLConverter.java]].
166
167 Macro converters can use ConfluenceURLConverter to convert URL. They need to make sure to handle the null case when the URL could not be converted, so as to not fortuitously drop the URL.

Get Connected