Topic Options
#56902 - 04/03/19 09:29 AM Help parsing xml name value pairs
Jim Dornbos Offline
OL Expert

Registered: 07/23/08
Posts: 151
Loc: Flint, Michigan
I'm trying to parse an existing xml file format that our customer uses for other purposes (so I don't have the option of adjusting what they send to us). It looks like:

<property>
<name>orderType</name>
<value>BULK</value>
</property>
<property>
<name>correlationId</name>
<value>9877414b-c4dc-4ebd-8732-ee094e1dc7b4</value>
</property>
<property>
<name>WIRE_O_BINDING</name>
<value>TRUE</value>
</property>

and so on, with many other name value pairs. My trouble is that I need to parse against the <name> and if I get a match, assign the <value> to the right global variable.

So if I need to know whether or not this is a wire-o-binding job, I need to keep looking through <names> until I find a match for wire_o_binding, then grab the value of TRUE. xmlget works for me if wire_o_binding is always the 3rd name/value pair - but there's no guarantee that will be the case. Any suggestions for how to attack this?

Thanks,
Jim

Top
#56904 - 04/03/19 10:51 AM Re: Help parsing xml name value pairs [Re: Jim Dornbos]
Jean-Cédric Offline
OL Expert

Registered: 10/03/16
Posts: 471
Loc: Québec, Canada
Not sure where you wan to go with this but here is what you could do:

  1. Add an XML Splitter that will split on the node Property
  2. Add a Text condition that will look at the field name and compare to WIRE_O_BINDING

On the true branch, setup your global variable with the content of the field value.

Top
#56906 - 04/03/19 01:27 PM Re: Help parsing xml name value pairs [Re: Jim Dornbos]
Philippe F. Offline
OL Expert

Registered: 09/06/00
Posts: 1928
Loc: Objectif Lune, Montreal, Qc
It would be easier - and MUCH faster - to use a script and specify the XPATH statement directly, as in this piece of JavaScript code:
Code:
var myXML = new ActiveXObject('Msxml2.DOMDocument.6.0');
myXML.load(Watch.GetJobFilename());

var valueNode = myXML.selectSingleNode("./root/property[name='WIRE_O_BINDING']/value");

Watch.log(valueNode ? valueNode.text : "nothing to show",2);

You'll have to adjust your XPATH statement according to the actual hierarchy of elements in the XML file. I just wrapped all your elements inside a <root> element for the sake of this example.
_________________________
Technical Product Manager
I don't want to achieve immortality through my work; I want to achieve immortality through not dying - Woody Allen

Top
#56907 - 04/03/19 01:58 PM Re: Help parsing xml name value pairs [Re: Jim Dornbos]
Jim Dornbos Offline
OL Expert

Registered: 07/23/08
Posts: 151
Loc: Flint, Michigan
Well - the first thing I'm trying to accomplish is to generate a work order derived from the XML. Second will be to retrieve pdfs from urls provided in the xml and send them to the appropriate printer here.

I realize this is more of an xml question than a PlanetPress question. I think ideally I'd like to apply an xslt that would change:

<property>
<name>WIRE_O_BINDING</name>
<value>TRUE</value>
</property>

into

<WIRE_O_BINDING>TRUE</WIRE_O_BINDING>

But due to my lack of xslt/xml expertise I need to find another way. Your suggestion is working and gives me a way to move forward.

Thanks for your help.
Jim

Top
#56908 - 04/03/19 02:07 PM Re: Help parsing xml name value pairs [Re: Philippe F.]
Jim Dornbos Offline
OL Expert

Registered: 07/23/08
Posts: 151
Loc: Flint, Michigan
Thanks, Philippe. I have probably 40 items to grab from this xml and will process about 5000 of these over the summer - so speed will matter for me.

I just prototyped 1 value using the splitter and text condition and that worked fine. But your suggestion looks like I could grab all 40 values in 1 swoop - which sounds good to me.

Thanks for adding that suggestion.

Jim


Edited by Jim Dornbos (04/03/19 04:08 PM)

Top
#56910 - 04/03/19 05:43 PM Re: Help parsing xml name value pairs [Re: Jim Dornbos]
Philippe F. Offline
OL Expert

Registered: 09/06/00
Posts: 1928
Loc: Objectif Lune, Montreal, Qc
The XSLT idea is a good one on paper... but it might not work with all files.

If the property name contains a value that is not an XML-compliant element name, the XSLT will fail.

For instance:
  • <name>WIRE O BINDING</name>
    or
  • <name>2PagePrinting</name>
cannot be converted to
  • <WIRE O BINDING>TRUE</WIRE O BINDING>
  • <2PagePrinting>TRUE</2PagePrinting>
because those are invalid XML element names.
_________________________
Technical Product Manager
I don't want to achieve immortality through my work; I want to achieve immortality through not dying - Woody Allen

Top
#56918 - 04/04/19 11:52 AM Re: Help parsing xml name value pairs [Re: Philippe F.]
Jim Dornbos Offline
OL Expert

Registered: 07/23/08
Posts: 151
Loc: Flint, Michigan
I'm not able to extract the simplest of values from the xml and I'm wondering if it's because I need to address (and how to address) the namespace that's defined in the xml. Actually - xmlget grabs this value for me just fine. I've stepped back from the the name:value pair problem of yesterday and now I'm just trying to return any value from the xml via the javascript solution you suggested yesterday.

The xml begins with:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<order xmlns="http://www.sfly.com/orderv3/order">
<version>3.0</version>
<orderNo>PRMR-SS-201903-84705</orderNo>
<orderDate>2019-03-26 12:16:40 PDT</orderDate>


Working backwards from the code you provided yesterday, I've simplified it just to try and nail down where I'm going wrong. In the code below I've tried calling orderNo in a variety of ways, and I keep getting nothing back. ./order/orderNo, /order/orderNo, order/orderNo, ./orderNo, /orderNo - and probably a couple more variations. In the log I'm getting:

ERROR: W3602 : Error 0 on line 4, column 1: Microsoft JScript runtime error: Type mismatch
ERROR: W3603 : Error running script.
ERROR: Run Script: W1603 : Plugin failed - 11:26:31 (elapsed time: 00:00:00:078)

If I hard code a value in for var valueNode1 = "testvalue";, that gets returned to me correctly, so it seems to be how I'm specifying myXML.selectSingleNode("orderNo"); that's the problem.

Code:
var myXML = new ActiveXObject('Msxml2.DOMDocument.6.0');
myXML.load(Watch.GetJobFilename());
var valueNode1 = myXML.selectSingleNode("orderNo");
Watch.SetVariable("global.sfly_packageName", valueNode1);


Any suggestions on where I'm going wrong with this?

Thanks,
Jim

Top
#56932 - 04/04/19 08:07 PM Re: Help parsing xml name value pairs [Re: Jim Dornbos]
Philippe F. Offline
OL Expert

Registered: 09/06/00
Posts: 1928
Loc: Objectif Lune, Montreal, Qc
Yep, the namespace is what's tripping you here: it is defined as a default namespace (i.e. no-prefix) which XPATH cannot handle natively.

In addition, whenever you do manage to retrieve a node, you must use node.text to get its content.

So to bypass the namespace issue, you have to specify that you are specifically looking for a node using its local name as opposed to its namespace name.

The following code should work:
Code:
var myXML = new ActiveXObject('Msxml2.DOMDocument.6.0');
myXML.load(Watch.GetJobFilename());
var valueNode1 = myXML.selectSingleNode("//*[local-name()='orderNo']");
Watch.Log(valueNode1.text,2);

Note that to make it even more explicit, you could also use:
Code:
var valueNode1 = myXML.selectSingleNode("./*[local-name()='order']/*[local-name()='orderNo']");


More information about default namespaces and XPATH is available on this Microsoft page: https://docs.microsoft.com/en-us/dotnet/standard/data/xml/xpath-queries-and-namespaces



Edited by Philippe F. (04/04/19 08:13 PM)
Edit Reason: Additional Info
_________________________
Technical Product Manager
I don't want to achieve immortality through my work; I want to achieve immortality through not dying - Woody Allen

Top