Changing values in XML xpath

Post Reply
Dave23
Member
Posts: 41
Joined: Thu Oct 12, 2017 4:42 pm

Changing values in XML xpath

Post by Dave23 »

Morning all,

I have been trying to use xpath in order for me to get values from the xml below. Is it actually possible to target multiple attribute values using xpath and then change these values without scripting?

So the values that i need are:

Where "/Root/Order_Info/ProductType/Products[@Type='Manual']" and "/Root/Order_Info/ProductType/Products/Components[@Type='Inset']" then

Select all "/Root/Order_Info/ProductType/Products/Components/[@PageCount]" and then add 16 to each PageCount.

If scripting is the only way then that is fine, but due to me being somewhat of a beginner and still getting to grips with scripting could someone give me a starting point? I have done very basic scripts but nothing like this.

Any info would be great.

Cheers

Code: Select all

<?xml version="1.0"?>
<Root>
  <OrderInfo ID="11111">
    <ProductType ProductName="TEST1">
      <Products ProductType="BOOK" Name="A" Type="Throwout">
        <Components Filename="Test1_throwout.pdf" Type="Throwout" PageCount="4">
          <ComponentSpecs SpecClass="" />
        </Components>
        <ProductSpecs SpecClass="" />
      </Products>
      <Products ProductType="BOOK" Name="B" Type="Manual">
        <Components Filename="Test1_inset.pdf" Type="Inset" PageCount="200">
          <ComponentSpecs SpecClass="" />
        </Components>
        <Components Filename="Test1_cover.pdf" Type="Cover" PageCount="4">
          <ComponentSpecs SpecClass="" />
        </Components>
        <ProductSpecs SpecClass="" />
      </Products>
      <Products ProductType="BOOK" Name="C" Type="Folder">
        <Components Filename="Folder.pdf" Type="Folder" PageCount="4">
          <ComponentSpecs SpecClass="" />
        </Components>
        <ProductSpecs SpecClass="" />
      </Products>
      <CustomerProductSpecs SpecClass="" />
    </ProductType>
	<ProductType ProductName="TEST2">
      <Products ProductType="CD" Name="A" Type="CD">
        <Components Filename="CD.pdf" Type="CD" PageCount="">
          <ComponentSpecs SpecClass="" />
        </Components>
        <ProductSpecs SpecClass="" />
      </Products>
      <CustomerProductSpecs SpecClass="" />
    </ProductType>
	<ProductType ProductName="TEST3">
      <Products ProductType="BOOK" Name="A" Type="Throwout">
        <Components Filename="Test1_throwout.pdf" Type="Throwout" PageCount="4">
          <ComponentSpecs SpecClass="" />
        </Components>
        <ProductSpecs SpecClass="" />
      </Products>
      <Products ProductType="BOOK" Name="B" Type="Manual">
        <Components Filename="Test1_inset.pdf" Type="Inset" PageCount="200">
          <ComponentSpecs SpecClass="" />
        </Components>
        <Components Filename="Test1_cover.pdf" Type="Cover" PageCount="4">
          <ComponentSpecs SpecClass="" />
        </Components>
        <ProductSpecs SpecClass="" />
      </Products>
      <Products ProductType="BOOK" Name="C" Type="Folder">
        <Components Filename="Folder.pdf" Type="Folder" PageCount="4">
          <ComponentSpecs SpecClass="" />
        </Components>
        <ProductSpecs SpecClass="" />
      </Products>
      <OrderInfoSpecs SpecClass="" />
    </ProductType>
  </OrderInfo>
</Root>
cstevens
Member
Posts: 103
Joined: Tue Feb 12, 2013 8:42 pm

Re: Changing values in XML xpath

Post by cstevens »

Don't think this can be done outside of scripting, but here's how you could do it in scripting (assuming the XML is a file coming into the script element):

Code: Select all

function jobArrived( s : Switch, job : Job )
{
	var ADD_PAGES = 16;
	//Open the incoming file as an XML document		
	var xmlDoc = new Document(job.getPath());
	
	//Get the Products nodes	
	var products = xmlDoc.evalToNodes("//Root/OrderInfo/ProductType/Products", null);
	var productType = "";
	s.log(1, "There are " + products.length + " products in this order.");
	//Go through each Products element to find out if it has a Components element with @Type="Inset"	
	for(var i=0; i<products.length; i++){
		productType = products.at(i).evalToString("@Type");
		s.log(1, "Product Type for product at index " + i + " is " + productType); 
		//If the ProductType is Manual go through the Components to see if one has a Type of "Inset"		
		if(productType == "Manual") {
			var components = products.at(i).evalToNodes("./Components", null);
			s.log(1, "For this product there are " + components.length + " Components.");
			var componentType = "";
			var increasePageCounts = false;
			for (var j=0; j<components.length; j++){
				componentType = components.at(j).evalToString("@Type", null);
				s.log(1, "Components element at index " + j + " has a Type of: " + componentType);
				if (componentType == "Inset"){
					s.log(1, "Components Type of Inset found.  Incrementing PageCount values by " + ADD_PAGES);
					increasePageCounts = true;
					break;
				}
			}
			//if a Components Type value was Inset increase each PageCount attribute for the Components in this Product
			if(increasePageCounts){
				var pageCount = 0;
				for (var j=0; j<components.length; j++){
					pageCount = components.at(j).evalToNumber("@PageCount", null);
					components.at(j).addAttribute("PageCount", null, pageCount + ADD_PAGES);
				}
			}
		}
	}
	//Save the changes to the XML file
	xmlDoc.save(job.getPath());
	//Send the modified file to the outgoing connection
	job.sendToSingle(job.getPath());
}
Dave23
Member
Posts: 41
Joined: Thu Oct 12, 2017 4:42 pm

Re: Changing values in XML xpath

Post by Dave23 »

This is great thanks cstevens a good foundation for me. When i tested this script I did notice that this updates both Cover and Inset types by adding 16 to the page count. How do i get it so that it only updates the Inset only?
jan_suhr
Advanced member
Posts: 592
Joined: Fri Nov 04, 2011 1:12 pm
Location: Nyköping, Sweden

Re: Changing values in XML xpath

Post by jan_suhr »

If you only have one ProductType per XML-file you can solve this with the Make XML app.

You can split the XML with Saxon to one XML-file per ProductType.

You could also have the value you add in a Submit point if you need it to be anything other than 16
Jan Suhr
Color Consult AB
Sweden
=============
Check out my apps
cstevens
Member
Posts: 103
Joined: Tue Feb 12, 2013 8:42 pm

Re: Changing values in XML xpath

Post by cstevens »

Sorry, I thought that's what you wanted based on your description. That actually makes the script a bit easier:

Code: Select all

function jobArrived( s : Switch, job : Job )
{
	var ADD_PAGES = 16;
	//Open the incoming file as an XML document		
	var xmlDoc = new Document(job.getPath());
	
	//Get the Products nodes	
	var products = xmlDoc.evalToNodes("//Root/OrderInfo/ProductType/Products", null);
	var productType = "";
	s.log(1, "There are " + products.length + " products in this order.");
	//Go through each Products element to find out if it has a Components element with @Type="Inset"	
	for(var i=0; i<products.length; i++){
		productType = products.at(i).evalToString("@Type");
		s.log(1, "Product Type for product at index " + i + " is " + productType); 
		//If the ProductType is Manual go through the Components to see if one has a Type of "Inset"		
		if(productType == "Manual") {
			var components = products.at(i).evalToNodes("./Components", null);
			s.log(1, "For this product there are " + components.length + " Components.");
			var componentType = "";
			var increasePageCounts = false;
			for (var j=0; j<components.length; j++){
				componentType = components.at(j).evalToString("@Type", null);
				s.log(1, "Components element at index " + j + " has a Type of: " + componentType);
				if (componentType == "Inset"){
					s.log(1, "Components Type of Inset found.  Incrementing PageCount values by " + ADD_PAGES);
					//Get the current PageCount value in this element and add 16 to it
					var currentPageCount = components.at(j).evalToNumber("@PageCount", null);
					components.at(j).addAttribute("PageCount", null, currentPageCount + ADD_PAGES);
					break;
				}
			}
		}
	}
	//Save the changes to the XML file
	xmlDoc.save(job.getPath());
	//Send the modified file to the outgoing connection
	job.sendToSingle(job.getPath());
}
Dave23
Member
Posts: 41
Joined: Thu Oct 12, 2017 4:42 pm

Re: Changing values in XML xpath

Post by Dave23 »

Thanks for updating the script cstevens, appreciate it.

jan_suhr I had originally thought about doing it that way. I have used xslt to split other xml, the issue i found with this was merging the xml's back together as i needed 1 xml as the result. I found merging them in xslt difficult and couldn't get it to work.
Post Reply