Seamless Media Migration to XM Cloud: A Step-by-Step Guide from Sitecore XP 10.4 and Content Hub Integration - Part 3

In part 1 of the article, we saw how to connect Sitecore XP with Sitecore ContentHub, and in part 2, we saw how to import all the assets to Sitecore Content Hub.

In this article, we will explore how to export the content from Sitecore Content Hub along with the assets public link, and update all the media items in Sitecore with the relevant asset's public link based on the identifier (SitecoreItemIdentifier) that we have exported from Sitecore XP and added in Sitecore Content Hub.

We will export all the assets from Sitecore Content Hub based on the search condition, like SitecoreItemIdentifier not empty.

To set this Filter condition, go to the Assets page and select the Search Component, and the Query Builder 




  • Select the Assets with SitecoreItemidentifier, as these are the new assets imported from the Excel upload.
  • Once we retrieved the assets, then exported them to Excel for updating the reference in Sitecore XP like below.



After getting all the results, export the data from Sitecore Content Hub in Excel / CSV format with all the information like
  • Id
  • Identifier
  • SitecoreItemIdentifier
  • Title
  • Description
  • FileName
  • Asset Public Links
  • Final lifecycle status
  • Content repositories
In order to export the asset details from Content Hub, it is necessary to add an Export Profile. Without Export Profile also we can also import the default output, but here we have added all the necessary fields that are needed in the Excel output.

Steps to Create the Export Profile:
  • Go to Manage -- Export Profiles and click Export Profile
  • Add Name and Definition (M.Asset) 
  • Check Is Default
  • In the Settings box, select the Text option and add the snippet below to extract the required information from the assets and their relations.


     {
      "properties": [
        "Title",
        "Description",
        "FileName",
        "SitecoreItemIdentifier"
      ],
      "relations": {
        "FinalLifeCycleStatusToAsset": {
          "exportRelatedEntities": true
        },
        "ContentRepositoryToAsset": {
          "exportRelatedEntities": false
        }
      },
      "includeSystemProperties": true,
      "publicLinks": {
        "asset": true,
        "masterfile": true
      },
      "version": "1.1"
    }
  • After configuring the Export Profiles, we need to assign this Export Profile to download the assets.
    Go to Pages and search for the Assets page. Click on the Selection Component to assign the Export Profile created 





  • If we downloaded the file as xslx file, then change the file type to CSV format, which will be easy to import into Sitecore XP using PowerShell.
    $uploadPath = "C:\\nelson\\export.csv"
    # Import the CSV file from the local path downloaded from Content Hub
    $csvData = Import-Csv -Path $uploadPath
    $normalizedItemID = $null
    if ($csvData) {
       
       
            New-UsingBlock (New-Object Sitecore.SecurityModel.SecurityDisabler) {
            New-UsingBlock (New-Object Sitecore.Data.DatabaseCacheDisabler) {
                New-UsingBlock (New-Object Sitecore.Data.BulkUpdateContext) {
                    New-UsingBlock (New-Object Sitecore.Data.Events.EventDisabler) {
                        foreach ( $row in $csvData ) {
                            #Get the Sitecore item ID from the CSV file for the media item to be be replaced with asset
                            #public in RTE field
                            #Example of image refereed in RTE <img src="-/media/1DBE221862714A419253611C0DE450D2.ashx" />
                            # 1DBE221862714A419253611C0DE450D2 is the ID of the media item in Sitecore
                            $normalizedItemID = $row.SitecoreItemIdentifier.replace("{", "").replace("}", "").replace("-", "").ToLower();  
                           
                            $mediaItem = Get-Item -Path "master:" -ID $row.SitecoreItemIdentifier;                
                            if ($null -eq $mediaItem) { continue; }
                           
                            #get the public link of the asset in the CSV file from Content Hub, if more than one link is available, take the first one
                            #then get the first link from the list of links
                            $src = $row.AssetPublicLinks;
                            if($src -ne $null -or $src -ne "")
                            {
                                if ($src.IndexOf("|") -gt 0) {
                                    $src = ([String]$src).split("|")[0]
                                }
                            }
                            $Title = [System.Net.WebUtility]::HtmlEncode($row.Title);                      
                            # Find all items, referring the original media item
                            #-ItemLink will find all the item reference and its field name
                            $referrers = $mediaItem | Get-ItemReferrer -ItemLink;

                            if ($referrers.Count -gt 0) {
                                $referrers | ForEach-Object {
                                   
                                    $sourceItem = Get-Item -Path "master:" -ID $_.SourceItemID;                            
                                    $sourceVersion = $sourceItem.Version.ToString();
                                    $referenceItemVersion = $_.SourceItemVersion.ToString();
                                   
                                    if ($sourceVersion -eq $referenceItemVersion) {
                                        $sourceField = Get-Item -Path "master:" -ID $_.SourceFieldID;
                                        $itemField = $sourceItem | Get-ItemField -ReturnType TemplateField -Name $sourceField.Name;
                               
                                        # Update RTE Field's Sitecore media library image with the Conten Hub Asset public link
                                        if ($itemField.type -eq "Rich Text") {
                                            $richTextValue = $sourceItem.Fields[$sourceField.Name].Value;
                                            if ($richTextValue) {
                                                $htmlDoc = New-Object HtmlAgilityPack.HtmlDocument;
                                                $htmlDoc.LoadHtml($richTextValue);
                                                $imgNodes = $htmlDoc.DocumentNode.SelectNodes("//img");
                                               
                                                if ($imgNodes) {
                                                    foreach ($img in $imgNodes) {
                                                        $oldSrc = $img.GetAttributeValue("src", "");
                                                        if ($oldSrc -like '*' + $normalizedItemID + '*') {
                                                            $img.SetAttributeValue("src", $src);
                                                        }
                                                    }
                                                    $sourceItem.Editing.BeginEdit();
                                                    $sourceItem.Fields[$sourceField.Name].Value = $htmlDoc.DocumentNode.OuterHtml;
                                                    $sourceItem.Editing.EndEdit();
                                                 
                                                }                                                        
                                               
                                            }
                                        }
                                        #Update the General link field's image with the Content Hub Asset public link
                                        elseif ($itemField.type -eq "General Link") {
                                            $sourceItem.Editing.BeginEdit();    
                                            [Sitecore.Data.Fields.LinkField]$fieldValueLink = $sourceItem.Fields[$sourceField.Name];    
                                            $fieldValueLink.Clear();
                                            $fieldValueLink.Text = "Link";
                                            $fieldValueLink.Title = $Title;
                                            $fieldValueLink.LinkType = "external";
                                            $fieldValueLink.Url = $src;
                                            $sourceItem.Editing.EndEdit();
                                        }
                                        #Update the image field with the Content Hub Asset public link
                                        elseif ($itemField.type -eq "Image") {                                        
                                             
                                            $sourceItem.Editing.BeginEdit();
                                            $sourceItem.Fields[$sourceField.Name].Value = [string]::Format("<image src='{0}' dam-content-type='Image' dam-id='{1}' alt='{2}' />", $src, $row.identifier,$Title)
                                            $sourceItem.Editing.EndEdit();                                      
       
                                        }
                                    }
                                   
                                }  
                            }
                                   
                        }          
       
                    }
                }
            }
        }
    }    

    Once we run the script, all the media references in Sitecore will be updated with the asset's public link.
  • We will take one asset from the content hub, export to Excel, and then change the file extension to  CSV, and let's see the reference in Sitecore updated with these public links

    Sample exported file from Content Hub:


    RTE / Image / General Link:





Let's learn and grow together, happy programming 😊

Comments

Popular posts from this blog

Sitecore Upgrade from 8.1 XP to 10.4 XM Scaled - Part 1

Custom Item Url and resolving the item in Sitecore - Buckets

Fixing Sitecore Buckets folder path - Items created after 12 AM server time zone