Expand my Community achievements bar.

Submissions are now open for the 2026 Adobe Experience Maker Awards.
SOLVED

How to copy 100 tags to a new path?

Avatar

Level 2

On-prem AEM 6.5, SPA, Angular 9, Bootstrap 4

We have two groups of tags.  One group is used to populate a State dropdown in an Adaptive Form.  Another group is used to populate a Country dropdown in an Adaptive Form.  I would like to copy (not move) these two groups of tags to a different path.  I can't use a global taxonomy for these tags because administrators have locked down the ability to create globally available tags and there are too many tags to manually recreate for every new path.

What is the easiest method for accomplishing this task as a non-administrator?

dpkhmhs_0-1739387017240.png

 

Topics

Topics help categorize Community content and increase your ability to discover relevant content.

1 Accepted Solution

Avatar

Correct answer by
Level 6

Hi @dpkhmhs ,

 

You can create a simple Groovy script for this. Below is a sample code, though I haven’t tested it myself.

 

import org.apache.sling.api.resource.Resource
import org.apache.sling.api.resource.ResourceResolver
import org.apache.sling.api.scripting.SlingScriptHelper
import org.apache.sling.api.wrappers.ValueMapDecorator
import org.apache.sling.api.resource.ModifiableValueMap
import org.apache.sling.api.resource.ValueMap
import org.apache.sling.api.resource.Resource
import org.apache.sling.api.resource.ResourceUtil
import org.apache.sling.api.resource.ResourceMetadata
import org.apache.sling.api.resource.Resource
import org.apache.sling.api.resource.ResourceResolver

import com.day.cq.tagging.Tag
import com.day.cq.tagging.TagManager
import org.apache.sling.api.resource.Resource

// Input Parameters
String sourcePath = "/content/cq:tags/old-path"  // Source tag path
String targetPath = "/content/cq:tags/new-path"  // Target tag path

// Retrieve the source tag
TagManager tagManager = resourceResolver.adaptTo(com.day.cq.tagging.TagManager);
Tag sourceTag = tagManager.resolve(sourcePath)

// Function to copy a tag and its hierarchy
def copyTagHierarchy(Tag sourceTag, String targetPath, TagManager tagManager) {
    // Check if source tag exists
    if (sourceTag == null) {
        log.error("Source tag does not exist.")
        return
    }

    // Create a new tag in the target path
    String targetTagName = targetPath + "/" + sourceTag.getName()
    Tag targetTag = tagManager.createTag(targetTagName, targetTagName, targetTagName)

    // Copy properties (optional) from the source to the target tag
    copyTagProperties(sourceTag, targetTag)

    // Copy the child tags recursively
    sourceTag.listChildren().each { childTag ->
        // Recursively copy child tags
        copyTagHierarchy(childTag, targetTagName, tagManager)
    }
}

// Function to copy tag properties, excluding system properties
def copyTagProperties(Tag sourceTag, Tag targetTag) {
    // Get the properties of the source tag (as ValueMap)
    Resource sourceResource = resourceResolver.getResource(sourceTag.getPath())
    if (sourceResource == null) {
        log.error("Source resource does not exist for tag: " + sourceTag.getPath())
        return
    }

    ModifiableValueMap sourceProperties = sourceResource.adaptTo(ModifiableValueMap.class)
    
    // Get the target resource
    Resource targetResource = resourceResolver.getResource(targetTag.getPath())
    if (targetResource == null) {
        log.error("Target resource does not exist for tag: " + targetTag.getPath())
        return
    }
    
    ModifiableValueMap targetProperties = targetResource.adaptTo(ModifiableValueMap.class)
    
    // List of system properties to exclude from copy
    def excludedProperties = [
        "jcr:createdBy",
        "jcr:created",
        "jcr:lastModified",
        "jcr:lastModifiedBy"
    ]
    
    // Copy properties from source to target, excluding system properties
    if (sourceProperties != null && targetProperties != null) {
        sourceProperties.each { key, value ->
            // Exclude system properties
            if (!excludedProperties.contains(key)) {
                targetProperties.put(key, value)
            }
        }
        
        // Commit the changes
        resourceResolver.commit()
    }
}

// Start the copy process
copyTagHierarchy(sourceTag, targetPath, tagManager)

log.info("Tag hierarchy copied successfully from ${sourcePath} to ${targetPath}")

 

Regards,

Ayush

View solution in original post

4 Replies

Avatar

Community Advisor

@dpkhmhs You can create a simple groovy script to copy these tags under the new path. 

FYI, you will need JCR permissions to atleast create nodes to get this done. Check if there is a service user that you can use for this.

If you dont have grrovy console installed in your environment, you can create a managed controlled process (MCP) to do this.

Avatar

Level 2

Thanks for the reply @Harwinder-singh. I installed the groovy console (15.1.0) in my local instance and have admin access.  I opened a few of the sample scripts and it looks like gibberish to me.  The Groovy syntax is fine as I'm a Java developer.  However, I'm not an AEM developer and would appreciate some hints to create the "simple groovy script" you mentioned to accomplish my task.  Thanks!

Avatar

Community Advisor

Avatar

Correct answer by
Level 6

Hi @dpkhmhs ,

 

You can create a simple Groovy script for this. Below is a sample code, though I haven’t tested it myself.

 

import org.apache.sling.api.resource.Resource
import org.apache.sling.api.resource.ResourceResolver
import org.apache.sling.api.scripting.SlingScriptHelper
import org.apache.sling.api.wrappers.ValueMapDecorator
import org.apache.sling.api.resource.ModifiableValueMap
import org.apache.sling.api.resource.ValueMap
import org.apache.sling.api.resource.Resource
import org.apache.sling.api.resource.ResourceUtil
import org.apache.sling.api.resource.ResourceMetadata
import org.apache.sling.api.resource.Resource
import org.apache.sling.api.resource.ResourceResolver

import com.day.cq.tagging.Tag
import com.day.cq.tagging.TagManager
import org.apache.sling.api.resource.Resource

// Input Parameters
String sourcePath = "/content/cq:tags/old-path"  // Source tag path
String targetPath = "/content/cq:tags/new-path"  // Target tag path

// Retrieve the source tag
TagManager tagManager = resourceResolver.adaptTo(com.day.cq.tagging.TagManager);
Tag sourceTag = tagManager.resolve(sourcePath)

// Function to copy a tag and its hierarchy
def copyTagHierarchy(Tag sourceTag, String targetPath, TagManager tagManager) {
    // Check if source tag exists
    if (sourceTag == null) {
        log.error("Source tag does not exist.")
        return
    }

    // Create a new tag in the target path
    String targetTagName = targetPath + "/" + sourceTag.getName()
    Tag targetTag = tagManager.createTag(targetTagName, targetTagName, targetTagName)

    // Copy properties (optional) from the source to the target tag
    copyTagProperties(sourceTag, targetTag)

    // Copy the child tags recursively
    sourceTag.listChildren().each { childTag ->
        // Recursively copy child tags
        copyTagHierarchy(childTag, targetTagName, tagManager)
    }
}

// Function to copy tag properties, excluding system properties
def copyTagProperties(Tag sourceTag, Tag targetTag) {
    // Get the properties of the source tag (as ValueMap)
    Resource sourceResource = resourceResolver.getResource(sourceTag.getPath())
    if (sourceResource == null) {
        log.error("Source resource does not exist for tag: " + sourceTag.getPath())
        return
    }

    ModifiableValueMap sourceProperties = sourceResource.adaptTo(ModifiableValueMap.class)
    
    // Get the target resource
    Resource targetResource = resourceResolver.getResource(targetTag.getPath())
    if (targetResource == null) {
        log.error("Target resource does not exist for tag: " + targetTag.getPath())
        return
    }
    
    ModifiableValueMap targetProperties = targetResource.adaptTo(ModifiableValueMap.class)
    
    // List of system properties to exclude from copy
    def excludedProperties = [
        "jcr:createdBy",
        "jcr:created",
        "jcr:lastModified",
        "jcr:lastModifiedBy"
    ]
    
    // Copy properties from source to target, excluding system properties
    if (sourceProperties != null && targetProperties != null) {
        sourceProperties.each { key, value ->
            // Exclude system properties
            if (!excludedProperties.contains(key)) {
                targetProperties.put(key, value)
            }
        }
        
        // Commit the changes
        resourceResolver.commit()
    }
}

// Start the copy process
copyTagHierarchy(sourceTag, targetPath, tagManager)

log.info("Tag hierarchy copied successfully from ${sourcePath} to ${targetPath}")

 

Regards,

Ayush