Add Attribute to XML, with a twist.

Post Reply
actionHero
Member
Posts: 37
Joined: Thu May 18, 2017 12:06 am

Add Attribute to XML, with a twist.

Post by actionHero »

Hello,
I have an XML that I need to add an attribute to based on another XML in a folder.

Original XML (this may have one ISBN to look up or 100).
<details>
<detail ID="1" isbn="987654321000" title="" qty="10" />
<detail ID="2" isbn="987654321001" title="" qty="11" />
<detail ID="3" isbn="987654321002" title="" qty="12" />
</details>

I have a folder of XMl's, each named an ISBN. Inside the xml is a node with a job number. I need to be able to take the ISBN in the original XML, search the folder, find the XML with same ISBN name, grab the node for jobnumber, add attribute to Original XML. I own XML Magic App, not sure if this is something that can be done with that?

Final XML

<details>
<detail ID="1" isbn="987654321000" title="" qty="10" jobnumber="123456" />
<detail ID="2" isbn="987654321001" title="" qty="11" jobnumber="123457" />
<detail ID="3" isbn="987654321002" title="" qty="12" jobnumber="123458" />
</details>
Last edited by actionHero on Tue Sep 17, 2019 8:06 pm, edited 1 time in total.
cstevens
Member
Posts: 103
Joined: Tue Feb 12, 2013 8:42 pm

Re: Add Attribute to XML, with a twist.

Post by cstevens »

Edit. I misread your post originally, this is updated to reflect more what you wanted.

Something like this maybe? I don't know what the structure of the XML file you're searching for the job number is, or which if the xml files is triggering the script. I'm assuming (probably incorrectly) that the file with the jobnumber is coming into the script.

Code: Select all

	//open the original XML as an XML DOM	
	var origXML = new Document(origXMLPath);
	
	//get the folder and list of XML files contained in it (assuming this folder is coming into this script as a job input)
	var inFolder = new Dir(job.getPath());
	var fileList = inFolder.entryList("*.xml", Dir.Files, Dir.Name);
	
	//get the list of detail nodes from original XML file
	var detailList = origXML.evalToNodes("//details/detail", null);
	var isbn = "";
	var xmlFileName= "";
	var jobNumber = "";
	//for each node get the isbn number then search the folder of XML files for a node that matches that ISBN
	for (var i=0; i<detailList.length; i++){
		detailList.at(i).getAttribute("isbn");
		s.log(1, "Checking input XML files for matching isbn number of: " + isbn);
		for(var j=0; j<fileList.length; j++){
			if(fileList[i].indexOf(isbn) != -1){
				xmlFileName = fileList[i];
				break
			}
			//open one of the folder XML files as DOM
			folderXML = new Document(inFolder.path + "\\" + xmlFileName);
			jobNumber = folderXML.evalToString("//XPath/to/jobnumber", null);
			if(jobNumber != ""){
				s.log(1, "Found matching detail node with jobnumber value of: " + jobNumber);
				//add the jobnumber attribute to the original XML file
				detailList.at(i).addAttribute("jobnumber", null, jobNumber);
				jobNumber = "";
			}
		}
	}
	//save changes to original XML file
	origXML.save(orgXMLPath);
actionHero
Member
Posts: 37
Joined: Thu May 18, 2017 12:06 am

Re: Add Attribute to XML, with a twist.

Post by actionHero »

Thanks for the response. The folder of XML's with job numbers will be a repository. I wont know what XML's exist, just need to search for the ISBN via the tag in original XML. The original XML will trigger the search of the repository.

Thanks,
Adam
cstevens
Member
Posts: 103
Joined: Tue Feb 12, 2013 8:42 pm

Re: Add Attribute to XML, with a twist.

Post by cstevens »

So is the original XML file coming into the script? This should still be valid, you just need to change the paths to the original xml file (job.getPath()), the xml folder repository location, and the XPath where the jobnumber is located within the xml file(s) in the repository.

Is the ISBN number in the xml file name inside the repository, or do you have to actually open each XML file and look for the isbn number inside the file?
actionHero
Member
Posts: 37
Joined: Thu May 18, 2017 12:06 am

Re: Add Attribute to XML, with a twist.

Post by actionHero »

Hello,
Yes the Original XML comes in to the script, it is an Order xml. Orders are received and they need to grab book spec data from our MIS... however I can only search my MIS by job number to grab the book spec data. I'm creating the repository of XML's that are named the ISBN, then inside the XML will be the MIS job number. The order XML comes in, needs to find the ISBN XML in repository, then open it and grab the MIS job number, and add that to the Order attribute.

Thanks!
actionHero
Member
Posts: 37
Joined: Thu May 18, 2017 12:06 am

Re: Add Attribute to XML, with a twist.

Post by actionHero »

I'm getting an error saying, "Error in line 30 of script : TypeError. 'getAttribute' undefined or not a function". Must be a different way I need to write, detailList.at(i).getAttribute("isbn");
mkayyyy
Member
Posts: 75
Joined: Mon Nov 21, 2016 6:31 pm
Location: UK

Re: Add Attribute to XML, with a twist.

Post by mkayyyy »

actionHero wrote: Mon Sep 16, 2019 9:07 pm I'm getting an error saying, "Error in line 30 of script : TypeError. 'getAttribute' undefined or not a function". Must be a different way I need to write, detailList.at(i).getAttribute("isbn");
The function needs to be getAttributeValue. Also the value returned from that function needs to be assigned to the variable isbn:

Code: Select all

isbn = detailList.at(i).getAttributeValue("isbn", null);
actionHero
Member
Posts: 37
Joined: Thu May 18, 2017 12:06 am

Re: Add Attribute to XML, with a twist.

Post by actionHero »

Thank you for the replay. I have it working in a perfect scenario but not every scenario.

First I need it to fail to traffic light connector if an ISBN can't be found. An incoming XML could have many ISBN's in the order. Currently if all the ISBN's exist in the folder, it works fine. But if one of the line item ISBN's doesn't exist, the scripts places the last known job number in the field as opposed to failing to traffic light connector. I realize i'm not telling it to fail at the moment but that's why i'm asking... I'm not totally sure how to get to fail the whole file even even one of the ISBN's cant be found.

Code: Select all

// Is invoked each time a new job arrives in one of the input folders for the flow element.
// The newly arrived job is passed as the second parameter.
function jobArrived( s : Switch, job : Job )
{
//open the original XML as an XML DOM
var doc = job.getPath();
var origXML = new Document(doc);
//get the folder and list of XML files contained in it input)
var inFolder = new Dir("C:/Users/Enfocus.KY-SW1/Documents/FM_Parts");
var fileList = inFolder.entryList("*.xml", Dir.Files, Dir.Name);
s.log(1,fileList);

//get the list of detail nodes from original XML file
var detailList = origXML.evalToNodes("//metadata/orders/order/details/detail", null);
var isbn = "";
var xmlFileName= "";
var jobNumber = "";
s.log(2, "Made it here - 1");
var test= detailList.length;
s.log(2, test);

  //for each node get the isbn number then search the folder of XML files for a node that matches that ISBN
for (var i=0; i<detailList.length; i++){
var thenode = detailList.getItem(i);
var id = thenode.getAttributeValue("isbn",null);
s.log(3, id);
s.log(1, "Checking input XML files for matching isbn number of: " + id);

for(var j=0; j<fileList.length; j++)
	if(fileList[j].indexOf(id) != -1){
       xmlFileName = fileList[j]
					 break;
   } 


s.log(2, "Made it here - 2");
//open one of the folder XML files as DOM

folderXML = new Document(inFolder.path + "/" + xmlFileName);

jobNumber = folderXML.evalToString("//csv/field[1]", null);
s.log(2, jobNumber);
if(jobNumber != ""){
s.log(2, "Found matching detail node with jobnumber value of: " + jobNumber);
//add the jobnumber attribute to the original XML file
detailList.at(i).addAttribute("jobnumber", null, jobNumber);
jobNumber = "";}

}
//save changes to original XML file
origXML.save(job.getPath() );
job.sendToData(1, job.getPath() );
}
mkayyyy
Member
Posts: 75
Joined: Mon Nov 21, 2016 6:31 pm
Location: UK

Re: Add Attribute to XML, with a twist.

Post by mkayyyy »

To get the script to fail the whole file if one of the ISBNs don't exist I went with this which seems to work:

Code: Select all

// Is invoked each time a new job arrives in one of the input folders for the flow element.
// The newly arrived job is passed as the second parameter.
function jobArrived( s : Switch, job : Job ) {
	//open the original XML as an XML DOM
	var doc = job.getPath();
	var origXML = new Document(doc);
	//get the folder and list of XML files contained in it input
	var inFolder = new Dir("C:/Users/Enfocus.KY-SW1/Documents/FM_Parts");
	
	//get the list of detail nodes from original XML file
	var detailList = origXML.evalToNodes("//detail", null);
	var allFilesExist = true;
	var allJobNames = true;
	
	for (var i = 0; i < detailList.length; i += 1) {
		var currentNode = detailList.getItem(i);
		var isbnAttr = currentNode.getAttributeValue("isbn", null);
		
		var isbnFile = inFolder.entryList(isbnAttr + ".xml", Dir.Files, Dir.Name);
		
		if (isbnFile.length !== 0) {
			folderXML = new Document(inFolder.path + "/" + isbnFile);
			
			jobNumber = folderXML.evalToString("//csv/field[2]", null);
			
			if (jobNumber !== "") {
				s.log(2, "Found matching detail node with jobnumber value of: " + jobNumber);
				//add the jobnumber attribute to the original XML file
				detailList.at(i).addAttribute("jobnumber", null, jobNumber);
			} else {
				allJobNames = false;
				break;
			}
		} else {
			allFilesExist = false;
			break;
		}
	}
	
	if (allFilesExist && allJobNames) {
		//save changes to original XML file
		origXML.save(job.getPath());
		job.sendToData(1, job.getPath());
	} else {
		//send to error connection
		job.log(3, "Missing isbn XML file/Missing jobnumber");
		job.sendToData(3, job.getPath());
	}
}
I ended up creating two variables allFilesExist and allJobNames and setting them both to true. Then whilst the for loop is running if the ISBN file doesn't exist then change that variable to false and break from the loop, same with the check that jobnumber (//csv/field[2]) isn't an empty string.

Then once the loop has finished check that both allFilesExist and allJobNames are true otherwise send to the error connection.
cstevens
Member
Posts: 103
Joined: Tue Feb 12, 2013 8:42 pm

Re: Add Attribute to XML, with a twist.

Post by cstevens »

Sorry, I must have accidentally unsubscribed to this thread. Sorry to leave you hanging like that. Looks like you got it working though.
actionHero
Member
Posts: 37
Joined: Thu May 18, 2017 12:06 am

Re: Add Attribute to XML, with a twist.

Post by actionHero »

Thank you for all the help, it works just as expected now. This is very helpful!
actionHero
Member
Posts: 37
Joined: Thu May 18, 2017 12:06 am

Re: Add Attribute to XML, with a twist.

Post by actionHero »

Thank you for all the help, it works just as expected now. This is very helpful!
mkayyyy
Member
Posts: 75
Joined: Mon Nov 21, 2016 6:31 pm
Location: UK

Re: Add Attribute to XML, with a twist.

Post by mkayyyy »

actionHero wrote: Thu Sep 26, 2019 7:49 pm Thank you for all the help, it works just as expected now. This is very helpful!
No problem! Glad I could help :)
Post Reply