The CreatorCon Call for Content is officially open! Get started here.

Please help me with the XML Import issue.

Ereshkigal
Tera Contributor

I want to import Incident records from a remote environment to a local environment.

I created a DataSource based on the following document and ran the import.

https://docs.servicenow.com/bundle/rome-platform-administration/page/administer/import-sets/concept/...

I was able to import it, but there are some problems.

  1. If the Group information is different between remote and local, the business rule "Abort changes on group" will be executed and it will not be possible to import.(If the group information does not match, I want to empty Assignment Group and Assigned to)
  2. I created a Transform Script in the above document, but because of that Script, it is the same as the remote sys_id when importing, so I can not import the record once imported. (I want to import the updated part as well)
  3. Newly added related records such as Incident Task should not be imported.

How can I solve these problems with Transform Script?

Thank you!

Business Rule:Abort changes on group(Incident)

(function executeRule(current, previous /*null when async*/) {

	// Add your code here
	var assigned_to = current.assigned_to;
	var assignment_group = current.assignment_group;

	var grp = new GlideRecord('sys_user_grmember');
	grp.addQuery('group.sys_id', assignment_group);
	grp.addQuery('user', assigned_to);
	grp.query();

	if(!grp.hasNext())
	{
		gs.addErrorMessage(gs.getMessage("Assigned to user {0} must be member of Assignment group {1} ",[assigned_to.getDisplayValue(),assignment_group.getDisplayValue()]));
		current.setAbortAction(true);
	}

})(current, previous);

Transform Script:OnBefore

(function runTransformScript(source, map, log, target /*undefined onStart*/ ) {

	// Add your code here
	if(action == "insert"){
		target.setNewGuidValue(source.u_sys_id);
	}

})(source, map, log, target);

 

find_real_file.png

1 ACCEPTED SOLUTION

@Ereshkigal 

Got it. There is a concept known as "Coalesce" which means below:

The coalesce option allows you to update existing target table records when transforming import data.

The coalesce option on a field map allows you to specify if the selected Target field should be used to coalesce on when import set records are transformed. If the field map Coalesce checkbox is selected, when the import set row is transformed the instance checks for an existing record in the target table that has the same value in the Target field as the import set row Source field.

If an existing record with a matching value in the target table is found, that record is updated. If no matching record is found, then a new record is created in the target table.
 
Please refer to below doc for more info on this:
 
https://docs.servicenow.com/bundle/quebec-platform-administration/page/administer/import-sets/concept/c_ImportSetCoalesce.html
 
So based on your Transform Map configuration, decide a field which can act as a Coalesce here, I believe Number can be one attribute which you can use here and you just need to make the Number Field Map Coalesce as True which should solve your issue and will update existing record and not create new record as shown below:
 
Like for example, I have shown below for Category field, similarly you can do it for Number field:
 
find_real_file.png
Hope this helps. Please mark the answer as correct/helpful based on impact.

Regards,
Shloke
Hope this helps. Please mark the answer as correct/helpful based on impact.

Regards,
Shloke

View solution in original post

9 REPLIES 9

Tony Chatfield1
Kilo Patron

Hi, your onbefore() transform script is used to set the sys_id of you source record as a valid 'record' in your target table IE 'incident'

But as per the documentation, you still a second onBefore() script containing lookup\data matching for every reference field based on referenced 'name' so that the correct matching sys_id can be set as the target record.

https://docs.servicenow.com/bundle/rome-platform-administration/page/administer/import-sets/task/t_AddOnBeforeScriptToTransformMap.html

The example script at item 8 is a good example, you will need a version of this for each reference field.

 

Thank you for answering!!

The above method is currently undergoing trial and error.

I would like to borrow some knowledge about scripts below.

Based on the above document, the process of issuing a draft locally with the same Sys ID at the time of import is described.

However, once you have created a draft, you will not be able to import it locally for updates that have been made remotely.

For the remote updates, I want to update the local ones as well after importing.

However, due to lack of knowledge about scripting, I cannot solve it by myself.

Help me!

Thank you!

(function runTransformScript(source, map, log, target /*undefined onStart*/ ) {

	// Add your code here
	if(action == "insert"){
		target.setNewGuidValue(source.u_sys_id);
	}

})(source, map, log, target);

 

Hi, based on your last post I would recommend that you look at alternative solutions as importing xml files referencing sys_id's is going to take quite a bit of development.
- _ you might be able to map your source sys_id's to a correlation_id field or custom field to identify external ID's

If you want to use a manual file upload, then rather than export and import xml
I would suggest that you export\import csv\plain text files so that you can process through a transform map identifying your target record and reference data via the field mapping coalesce functionality and\or scripted lookups.

You could also utilize a REST integration.

But you have mentioned 'incident' and both of these solutions are likely to result in duplication of values like task number, and you might want to review replication options as replication may resolve potential issues with duplicate numbering of records.

shloke04
Kilo Patron

Hi @Ereshkigal 

What you can do here is create two field Maps one for Assignment Group and one for Assigned to field and then instead of using direct field mapping use script within the field Map as shown below:

I have assumed that source field contains Name of your Assignment group from Remote environment and hence I have used Name in addQuery in script below, but in case it contains some other attribute then change the query accordingly.

answer = (function transformEntry(source) {

	// Add your code here
	var getSource = source.FieldName; // Replace "FieldName" with Source Assignent group filed in your Import table
	var gr = new GlideRecord('sys_user_group');
	gr.addQuery('name',getSource);
	gr.query();
	if(gr.next()){
		return gr.sys_id;
	}else{
		return '';
	}
	

})(source);

Screenshot for reference:

find_real_file.png

Similarly, you can do this for Assigned to field as well.

Hope this helps. Please mark the answer as correct/helpful based on impact.

Regards,
Shloke

Hope this helps. Please mark the answer as correct/helpful based on impact.

Regards,
Shloke