Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

How can I compare pages in different spaces?

Theresa Adams December 3, 2012

We are using confluence for documentation and followed the Atlassian documentation scheme.

But, when a tester is verifying the documentation, they would like to be able to compare a page from one version to the same page in another version. Each version is in its own space.

Has anyone done this kind of comparison?

6 answers

1 accepted

0 votes
Answer accepted
SarahA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 4, 2012

Hallo Theresa

One workaround would be to create a temporary space C, then use the Confluence CLI to do this:

  • Copy all the pages from Product A V1 to the temporary space C.
  • Copy all the pages from Product A V2 to the same temporary space C. This action will update any existing pages that have the same name as those being copied.

Then you can use the normal version comparison for each page, to see what's different between V1 and V2.

Here's the documentation for the Confluence CLI - see the "copyPage" action:

https://bobswift.atlassian.net/wiki/display/CSOAP/Documentation

And here is the introductory page:

https://marketplace.atlassian.com/plugins/org.swift.confluence.cli

Note that there's a Confluence plugin for the CLI too. Bob Swift is the expert. :)

I hope this helps.

Cheers, Sarah

0 votes
René Kjellerup June 6, 2017

you can accomplish this with python, if you are used to reading the output from the posix diff command:

#!/usr/bin/env python

import difflib
import sys try: from xmlrpc.client import ServerProxy from xmlrpc.client import Fault except: from xmlrpclib import ServerProxy from xmlrpclib import Fault def get_page(page_id, confluence_url='https://<confluence_domain>', confluence_login='<username>', confluence_password='<password>'): client = ServerProxy(confluence_url+"/rpc/xmlrpc", verbose=0) try: auth_token = client.confluence2.login(confluence_login, confluence_password) except: print("Can't login to confluence") return [] try: # getting confluence page page = client.confluence2.getPage(auth_token, page_id) except Fault as e: print(e.faultString) return [] return page['content'].split('\n') if len(sys.argv) < 3:
print("usage:" + sys.argv[0] + " page_id_1 page_id_2") for line in difflib.unified_diff(get_page(sys.argv[1]), get_page(sys.argv[2]), fromfile='pageID='+sys.argv[1], tofile='pageID='+sys.argv[2]): print(line[:-1])

this little script could help you

 

 

0 votes
Peter Kahn
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
June 14, 2016

I use Bob swifts API embedded in a groovy/gradle plugin.  You'd need to adapt this and at present it doesn't provide pretty unified diffs.  I figure I'll use Daisey Diff for that.  

 

Controller

class ConfluenceController extends TrustStoreService {
    def user
 def url
 def password
 ConfluenceSoapService service // soap service
 String authToken // login auth token

 public static logger = LogFactory.getLog(ConfluenceController)

    public static final String permissionsTypeView = "View"
 public static final String permissionsTypeEdit = "Edit"

 public ConfluenceController( String serverUrl, String username, String passwd) {
        url = serverUrl
        user = username
        password = passwd
}...
ConfluenceSoapService getService() {
    if (! service) {
        def serviceLocator = new ConfluenceSoapServiceServiceLocator()
        serviceLocator.setConfluenceserviceV2EndpointAddress(soapUrl())
        serviceLocator.setMaintainSession(true)

        service = (ConfluenceSoapService) serviceLocator.getConfluenceserviceV2()
    }
    return service
}

String getAuthToken() {
    if (! authToken) {
        checkTrustStore()
        logger.info("Login Attempt: ${user} @ ${url} :: ${password.size()}")
        authToken = getService().login(user, password)
    }
    return authToken
}
...
RemotePageSummary[] getPages(def space) {
    return getService().getPages(getAuthToken(),space)
}
..
RemotePage getPage(def space, def title) {
    return getService().getPage(getAuthToken(), space, title)
}

 

Compare Space Task

/**
 * Compares pages within two spaces, reporting on differences
 * Created by pkahn on 8/11/14.
 */

package com.attivio.releng.gradle.tasks.wiki

import com.attivio.releng.confluence.ConfluenceController
import com.attivio.releng.confluence.SpaceComparisonTool
import com.attivio.releng.gradle.tasks.AttivioTask
import com.attivio.releng.gradle.tasks.WikiTaskTrait
import org.gradle.api.GradleException
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.TaskAction

public class AttivioCompareConfluenceSpacesTask extends AttivioTask implements WikiTaskTrait {

    @Input
 String spaceKeyA
 @Input
 String spaceKeyB

 @TaskAction
 void compareSpaces() {
        boolean hasError = false
 ConfluenceController controller = getConfluenceController()
        SpaceComparisonTool comparisonTool = new SpaceComparisonTool(controller)

        logger.lifecycle("Comparing Spaces from ${spaceKeyA} to wiki(${spaceKeyB} : ${wikiUrl})")
        logger.info("${controller}")

        comparisonTool.compare(spaceKeyA, spaceKeyB)


        if (comparisonTool.onlySpaceA.size()) {
            hasError = true
 logger.error("Pages only in ${spaceKeyA}\n\t" + comparisonTool.onlySpaceA.join("\n\t"))
        }
        if (comparisonTool.onlySpaceB.size()) {
            hasError = true
 logger.error("Pages only in ${spaceKeyB}\n\t" + comparisonTool.onlySpaceB.join("\n\t"))
        }

        if (comparisonTool.differences.size()) {
            hasError = true
 logger.error("Difference Report ${spaceKeyA} :: ${spaceKeyB}")
            differences.each { entry -&gt;
                logger.error("---------------------------------\n${entry.key}\n${entry.value}\n")
            }
        }

        if (hasError) {
            throw new GradleException("Differences Found: ${spaceKeyA} ${spaceKeyB}")
        }
    }

}

 

Space Comparison tools

package com.attivio.releng.confluence

import org.apache.commons.logging.LogFactory
import org.swift.common.soap.confluence.RemotePageSummary
import org.apache.commons.lang.StringUtils

/**
 * compare two spaces providing details on missing pages and differences
 * Created by pkahn on 8/13/2014.
 */
class SpaceComparisonTool {
    public static logger = LogFactory.getLog(SpaceComparisonTool)
    ConfluenceController controller;
    def onlySpaceA = []
    def onlySpaceB = []
    def differences = [:]

    public SpaceComparisonTool(ConfluenceController controller) {
        this.controller = controller
    }


    /**
 * Compare two spaces and report differences
 * @param spaceA
 * @param spaceB
 * @return
 */
 @Override
 String toString() {
        return super.toString()
    }

    @Override
 boolean equals(Object obj) {
        return super.equals(obj)
    }

    /**
 * Execute comparison
 * @param spaceA
 * @param spaceB
 */
 public void compare(String spaceA, String spaceB) {


        // Page Lists
 logger.info("Loading Pages ${spaceA}")
        def pagesA = controller.getPages(spaceA)
        logger.info("Found: ${spaceA} ${pagesA.size()} pages")
        logger.info("Loading Pages ${spaceB}")
        def pagesB = controller.getPages(spaceB)
        logger.info("Found: ${spaceB} ${pagesB.size()} pages")

        // Ids
 def idsA = []
        def idsB = []
        pagesA.each { RemotePageSummary page -&gt;
            idsA &lt;&lt; page.getTitle()
        }
        pagesB.each { RemotePageSummary page -&gt;
            idsB &lt;&lt; page.getTitle()
        }

        // Missing Pages
 onlySpaceA = getListDifferences(idsA, idsB)
        onlySpaceB = getListDifferences(idsB, idsA)

        if (onlySpaceA.size() &gt; 0) {
            logger.error("Pages Only In ${spaceA}\n\t" + onlySpaceA.join("\n\t"))
        }
        if (onlySpaceB.size() &gt; 0) {
            logger.error("Pages Only In ${spaceB}\n\t" + onlySpaceB.join("\n\t"))
        }

        // Compare Common Pages


 idsA.each { def id -&gt;
            def pageA = controller.getPage(spaceA, id)
            def pageB = null
 try {
                pageB = controller.getPage(spaceB, id)
            } catch (Exception e) {
                // ignore as we already reported missing
 logger.debug("Missing Page. ${e.getMessage()}")
            }

            if ( pageB != null) {
                String contentA = pageA.content.toString()
                String contentb = pageB.content.toString()

                if (! contentA.equals(contentb)) {
                    def comparison = StringUtils.difference(contentA, contentb)
                    differences[id] = comparison.toString()
                }
            }
        }

        if (differences.size()) {
            logger.error("Difference Report ${spaceA} :: ${spaceB}")
            differences.each { entry -&gt;
                logger.error("---------------------------------\n${entry.key}\n${entry.value}")
            }
        }
    }

    private def getListDifferences(def listA, def listB) {
        def setA = listA.toSet()
        def setB = listB.toSet()
        setA.removeAll(setB)
        return setA
    }
}

 

class ConfluenceController extends TrustStoreService {
def user
 def url
 def password
 ConfluenceSoapService service // soap service
 String authToken // login auth token

 public static logger = LogFactory.getLog(ConfluenceController)

public static final String permissionsTypeView = "View"
 public static final String permissionsTypeEdit = "Edit"

 public ConfluenceController( String serverUrl, String username, String passwd) {
url = serverUrl
user = username
password = passwd

}
0 votes
Angela Yang January 5, 2016

Just want to check if any improvements have been done in Confluence since 2012? I'm after exactly the same thing as Theresa.

A bit of background for why such a feature is needed:

  • a document (confluence page) exists in different versions, living under different spaces
  • after a doc change is approved for the latest version, the changes sometimes need to be copied to a previous version
  • there is no simple way of copying doc (confluence page) changes from one page to another so manual doc change to an earlier version is required (this is tedious when there are many areas in the doc that changed) - this could be a good feature to add to Confluence
  • after the previous version doc is manually changed, I want to check how the 2 versions of docs compare and if I have correctly copied over all the required changes

Thanks

0 votes
AlysonA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 3, 2012

Theresa,

Thanks for clarifying. I'm afraid there isn't a functionality for this, you can perhaps open both pages in different tabs and compare them, but I'm aware this is not practical at all.

As for the script, this is something that would fit in a feature request that you can raise in https://jira.atlassian.com so we can consider including it in the future.

Those are my thoughts, let's see if someone else has more insights on this.

Cheers!

0 votes
AlysonA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 3, 2012

Hi Theresa,

Actually you can compare different page versions since Confluence tracks histories of changes to pages by maintaining a version of the page each time it is modified.

You just have to go to Tools > Page History and use the Compare with Current function.

Hope that's what you're looking for.

Cheers!

Theresa Adams December 3, 2012

Hi Alyson, no, unfortunately this isn't what I need.

We have a space for Product A V1 - with a page called "Log Format"

and a space for Product A V2 - with a page called "Log Format"

I want to compare those two.

Or better yet, a script that would compare every page in the hierarchy of Product A V1 with the same page in the hierarchy of Product A V2.

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events