Changing metadata of an image object using DocumentObj 2.5 SetMetaData

I'm wring a PowerShell script to change objects metadata at once. My script woks properly for topic objects. However, it does not work for image objects. I wrote the following code to change metadata using DocumentObj 2.5.

function DocumentObj-SetMetaData()
{
  $functionName = "DocumentObj-SetMetaData"
  $documentObjUrl = $infosharewsurl + "DocumentObj25.asmx?WSDL"
  $documentObjWebService = new-webServiceProxy -uri $documentObjUrl -UseDefaultCredential
  try
  {
    $psXMLMetadata = "<ishfields>"
    $psXMLMetadata += "<ishfield name='FTITLE' level='logical'>" + $ftitle + "</ishfield>"
    $psXMLMetadata += "<ishfield name='FKUBOTAMODELCLASSIFICATION' level='version'>" + $classification + "</ishfield>"
    $psXMLMetadata += "<ishfield name='FKUBOTAMODELSERIES' level='version'>" + $modelseries + "</ishfield>"
    $psXMLMetadata += "<ishfield name='FKUBOTAMODEL' level='version'>" + $model + "</ishfield>"
    $psXMLMetadata += "<ishfield name='FKUBOTAREGION' level='version'>" + $region + "</ishfield>"
    $psXMLMetadata += "<ishfield name='FKUBOTACOUNTRY' level='version'>" + $country + "</ishfield>"
    $psXMLMetadata += "<ishfield name='FKUBOTAKEYWORD' level='version'>" + $keywords + "</ishfield>"
    $psXMLMetadata += "</ishfields>"
  
    $psXMLRequiredCurrentMetadata = "<ishfields/>"
  
    # Write-Host($psXMLMetadata)
    Write-Host($id)
    $result = $documentObjWebService.SetMetaData([REF]$context, $id, [REF]$version, $language, $resolution, $psXMLMetadata, $psXMLRequiredCurrentMetadata)
  }
  catch [System.Web.Services.Protocols.SOAPException]
  {
    ("error at " + $functionName)
      Return-Result $Error[0].Exception.InnerException.Message
  }

  $result #returning the function value by simply outputting it
}
When this function is called, following ishfields are given via $psXMLMetadata variable.
<ishfields>
  <ishfield name='FTITLE' level='logical'>OM-GUIDE-0001</ishfield>
  <ishfield name='FKUBOTAMODELCLASSIFICATION' level='version'></ishfield>
  <ishfield name='FKUBOTAMODELSERIES' level='version'></ishfield>
  <ishfield name='FKUBOTAMODEL' level='version'></ishfield>
  <ishfield name='FKUBOTAREGION' level='version'></ishfield>
  <ishfield name='FKUBOTACOUNTRY' level='version'></ishfield>
  <ishfield name='FKUBOTAKEYWORD' level='version'>guide</ishfield>
  <ishfield name='FRESOLUTION' level='lng'>Thumbnail</ishfield>
</ishfields>
An exception occurs when the $documentObjWebService.SetMetaData is executed and it returns '-102003' as the error code. I looked into the error code explanation in the following page. But I cannot figure out the reason of the error.
Please give me advises to resolve this issue.
Kind regards,
Naoki
  • Hi Naoki,

    Nice to see you write PowerShell scripts on the (deprecated) ASMX-SOAP API functions using INTERNAL authentication. Where INTERNAL refers to that the Docs CMS user profile holds the password.

    The number '-102003' uses the following error description "The {objecttype} "{object}" cannot be returned, because it is not initialized." where the two parameter mentioned (so {...}) are filled in in your runtime.
    I will guess that you did not offer a value for "$resolution" - like Low, High, Default,... - so in turn you didn't specify an exact object that the system can work on.

    I cannot really derive which Tridion Docs version (like 14SP3/14.0.3) you are using? I do wonder why you decide not to use ISHRemote, see https://github.com/sdl/ISHRemote
    [...]
    New-IshSession -WsBaseUrl "">https://example.com/ISHWS/" -PSCredential "Admin"
    $ishTopicMetadata = Set-IshMetadataField -Name "FTITLE" -Level Logical -Value "Topic $timestamp" |
    Set-IshMetadataField -Name "FAUTHOR" -Level Lng -ValueType Element -Value $ishUserAuthor |
    Set-IshMetadataField -Name "FSTATUS" -Level Lng -ValueType Element -Value $ishStatusDraft
    $ishObject = Add-IshDocumentObj -FolderId $ishFolderTopic.IshFolderRef -IshType ISHModule -Lng $ishLng -Metadata
    $ishTopicMetadata -FileContent $ditaTopicFileContent
    $ishObject = Set-IshDocumentObj -IshObject $ishObject -Metadata (Set-IshMetadataField -IshSession $ishSession -Name
    "FSTATUS" -Level Lng -ValueType Element -Value $ishStatusReleased)[...]

  • Hi Dave,

    This PowerShell code was given by a SDL support engineer and had been working well for map/topic objects. This is reason why I'm using the deprecated ASMX-SOAP API functions. Regarding ISHRemote, there isn't enough information and I didn't realize it works as the alternative of the ASMX-SOAP API functions.

    We are using TD14 SP1 so that ISHRemote works on it. I'll try ISHRemote by referring your suggested code.

    Thank you for good suggestion.

    Kind regards,

    Naoki

  • Umm, it's difficult.

    I'm trying to get/set object's metadata based on object id (i.e. GUID) and its version. Therefore, I created a CSV file that contains GUID and its version of objects as shown below.

    GUID-CA754C5A-A4FC-44E4-9BA9-7A7EC19215E3,1
    GUID-806E1FE4-083A-4B45-A9F1-6177A987EBB7,1
    GUID-DDF07E67-29C7-49DF-8676-90C1AD9A311E,1

    In the PowerShell script, I want to process each object by finding the object using Find-IshDocumentObj. However, it seems specifying GUID for Set-IshMetadataFilterField is not possible. How do I process each document object base on the GUID?

    Following is part of my PowerShell code:
    # Read CSV file that contains GUID and its version list
    $input_csv = Get-Content $obj_list_csv | ConvertFrom-Csv -Header @('GUID''version')

    # Get matadata for each object
    $input_csv | ForEach-Object {
      $cur_GUID = $_."GUID"
      $cur_version = $_."version"
      # Write-Host ($cur_GUID,"`t",$cur_version)
      $obj_filer = Set-IshMetadataFilterField -IshSession $ishSession -Level logical -Name IshRef -FilterOperator Equal -Value $cur_GUID |
                   Set-IshMetadataFilterField -Level version -Name VERSION -FilterOperator Equal -Value $cur_version | 
                   Set-IshMetadataFilterField -Level lng -Name DOC-LANGUAGE -FilterOperator Equal -Value $lang
      $ishObject = Find-IshDocumentObj -IshSession $ishSession -MetadataFilter $obj_filer
      $documentDescription = "$($ishObject.IshRef)=$($ishObject.version_version_value)=$($ishObject.doclanguage)"
      Write-Host "$documentDescription"
    }
  • In essence the ASMX-SOAP and WCF-SOAP are equal regarding business calls, but differ in the security paradigm they respect. So I'm not forcing you into ISHRemote. Some background on the API and its future is available here: https://community.sdl.com/product-groups/sdl-tridion/tridion-docs/m/videos/4533 

    As I developed on ISHRemote I think it does its best to wrap WCF-SOAP in a PowerShell pipeline object friendly way. The ASMX-SOAP will force you more in raw xml structures.

    On the essence, finding one object by GUID. That is actually the main difference between a Find-* and Get-* cmdlet, with Find-* you do not know the identifier, with Get-* you do (as in your scenario). So regarding the last piece of code, what about:

    $metadataFilter = Set-IshMetadataFilterField -Level Version -Name VERSION -FilterOperator Equal -Value $cur_version |
                    Set-IshMetadataFilterField -Level Lng -Name DOC-LANGUAGE -FilterOperator Equal -Value $lang
    Get-IshDocumentObj -LogicalId $cur_GUID -MetadataFilter $metadataFilter
    # and ISHRemote already takes care of the returned object in pretty-print for you and retrieves a bunch of nice descriptive fields for you

    And on https://github.com/sdl/ISHRemote are some extra links, also ISHRemote repects the Get-Help some-cmdlet principle with examples.

  • I'm getting familiar with ISHRemote and PowerShell. I succeeded to obtain objects metadata based on object's GUID and version. This could be achieved with your kind assistance. Thanks a lot, Dave!

    Now, it's possible to add or modify metadata using Excel. My next task is writing a PowerShell script that overwrite objects metadata. As the result, we'll be able to add or modify metadata for a publication at once.

    # Get objects metadata from TD14 UAT server
    # [Command syntax]
    # > GetMetaFromUAT.ps1 <obj_list_csv> <out_meta_tsv> <lang>

    # Get command line arguments and check them
    Param($obj_list_csv, $out_meta_tsv, $lang)
    if ([string]::IsNullOrEmpty($obj_list_csv) -or [string]::IsNullOrEmpty($out_meta_tsv) -or [string]::IsNullOrEmpty($lang)) {
      Write-Error("Error: Three arguments (obj_list_csv, out_meta_tsv, lang) must be specified.")
      break
    }

    #Provide Web Services URL
    $url = 'https://xxxxxxx/ISHWS/'

    #Provide Domain and your username
    $username = 'xxxxx'
    $password = 'xxxxx'

    # Check for file existence
    if (-not(Test-Path $obj_list_csv)) {
      Write-Error("Error: Specified CSV file does not exist.")
      break
    }

    # login to Content Manager
    try {
      $ishSession = New-IshSession -WsBaseUrl $url -IshUserName $username -IshPassword $password
    catch {
      Write-Host "Cannot connect ...."
      exit
    }

    # Read CSV file that contains GUID and its version list
    $input_csv = Get-Content $obj_list_csv | ConvertFrom-Csv -Header @('GUID''version')

    # Create output file and write header line in it
    $outputFile = New-Object System.IO.StreamWriter($out_meta_tsv, $false, [Text.Encoding]::GetEncoding("UTF-16"))
    $outputFile.WriteLine("GUID`tVersion`tTitle`tModel classification`tModel series`tModel`tRegion`tCountry`tKeywords`tResolution")

    # Get matadata for each object
    $input_csv | ForEach-Object {
      $cur_GUID = $_."GUID"
      $cur_version = $_."version"
      Write-Host ($cur_GUID)
      $metadataFilter = Set-IshMetadataFilterField -IshSession $ishSession -Level version -Name "VERSION" -FilterOperator Equal -Value $cur_version | Set-IshMetadataFilterField -IshSession $ishSession -Level lng -Name "DOC-LANGUAGE" -FilterOperator Equal -Value $lang  | Set-IshMetadataFilterField -IshSession $ishSession -Level lng -Name "FRESOLUTION" -FilterOperator Equal -Value "Thumbnail"
      $target_obj = Get-IshDocumentObj -IshSession $ishSession -LogicalId $cur_GUID -MetadataFilter $metadataFilter
      $title = ($target_obj.IshField | where Name -eq FTITLE).value
      $modelClassification = ($target_obj.IshField | where Name -eq KUBOTAMODELCLASSIFICATION).value
      $modelSeries = ($target_obj.IshField | where Name -eq FKUBOTAMODELSERIES).value
      $model = ($target_obj.IshField | where Name -eq FKUBOTAMODEL).value
      $region = ($target_obj.IshField | where Name -eq FKUBOTAREGION).value
      $country = ($target_obj.IshField | where Name -eq FKUBOTACOUNTRY).value
      $keyword = ($target_obj.IshField | where Name -eq FKUBOTAKEYWORD).value
      $resolution = ($target_obj.IshField | where Name -eq FRESOLUTION).value
      # Write to file as tab separated values
      $outputFile.WriteLine($cur_GUID,"`t",$cur_version,"`t",$title,"`t",$modelClassification,"`t",$modelSeries,"`t",$model,"`t",$region,"`t",$country,"`t",$keyword,"`t",$resolution)
    }