PxPlus User Forum

Twitter Twitter Twitter

Author Topic: XML Parser - Find Node based on Attribute Value  (Read 2123 times)

Josh Fake

  • Member
  • **
  • Posts: 13
    • View Profile
    • Earnest & Associates
XML Parser - Find Node based on Attribute Value
« on: March 29, 2019, 10:19:05 AM »
To All:

I am in the process of moving away from the MS XML Parser MSXML2.DomDocument and replacing with the native XML object parser *obj/XML.  95% of the code is easily interpreted from using the MS COM Object to the Pvx Parser, but this last issue.

I have an incoming XML response from a webservice (this is just a "small snippet") with a list of a very large of Question Subnodes within the Question Node.

<Questions Level="Product">
    <Question Name="SpecialtyShape">
        <Answer>None</Answer>
    </Question>
    <Question Name="MV_ConfigIDListVisual">
        <Answer>1340</Answer>
        <Answer>1348</Answer>
    </Question>
    <Question Name="PricingGroup">
        <Answer>L06</Answer>
    </Question>
    <Question Name="Shape">
        <Answer>Rectangular</Answer>
    </Question>
    <Question Name="InsectScreen">
        <Answer>No</Answer>
    </Question>
    <Question Name="ConfigIDAccessoryGrid">
        <Answer>-29</Answer>
    </Question>
    <Question Name="NetPriceExtended">
        <Answer>2951.10</Answer>
    </Question>
    <Question Name="InsectScreenMaterial">
        <Answer>N/A</Answer>
    </Question>
</Questions>

Within the MSXML DOM Document I could easily find a Question based on the Name attributes value.
shape_node=xml'selectsinglenode("Questions/Question[@Name=""Shape""]")
shape$=shape_node'getelementsbytagname(""Answer"")'item(0)'text$

Is there any method within the PxPlus XML object to find a node based on an attributes' value as it can be achieved in the MS XML Object?
I could loop through all questions (almost 200) and create a memory file using the Name of the Question as the primary key, but that would involve more changes than I was hoping to make, I justed was hoping to replace the object so the code was not limited to a windows o/s.

Thanks for any and all help ahead of time

Allen Miglore

  • Silver Member
  • ***
  • Posts: 38
    • View Profile
    • UnForm
Re: XML Parser - Find Node based on Attribute Value
« Reply #1 on: March 29, 2019, 11:03:05 AM »
You can use the xml() function to loop through the xml nodes, and the attribute nodes as well.

 open (unt,isz=1)"test.xml"
 read record (lfo,siz=9999999)xml$
 close (lfo)
 let ofs=0
 let xml1$=xml(next from xml$,ind=ofs,key=tag$) ! get first level xml
 let ofs1=0
 while 1
 let xml2$=xml(next from xml1$,ind=ofs1,key=tag$,opt=prop$,err=*break) ! loop through tags 
 let propofs=0
 while 1
 let propval$=xml(property next from prop$,ind=propofs,key=propname$,err=*break) ! loop through attributes until Name="Shape"
 if propname$="Name" and propval$="Shape" then let found=1; break
 wend
 if found then break
 wend
 print xml2$

Josh Fake

  • Member
  • **
  • Posts: 13
    • View Profile
    • Earnest & Associates
Re: XML Parser - Find Node based on Attribute Value
« Reply #2 on: March 29, 2019, 11:57:20 AM »
Thank you Allen!

I will try this as I have never worked directly with the xml() function and see if this will work.  I have about 30 of these I have to navigate through so I will probably have to add a switch/case/end switch while transversing through all the question sub-nodes.  But I will definitely try this.

 I was just hoping there would be a way to handle this via the xml class find_node() method.  Most of the methods I use in the MS Com Object are easily converted to a method within the*obj/XML interface with the exception of this one. I'll add this as an "enhancement request".

Allen Miglore

  • Silver Member
  • ***
  • Posts: 38
    • View Profile
    • UnForm
Re: XML Parser - Find Node based on Attribute Value
« Reply #3 on: March 29, 2019, 12:06:50 PM »
We have a similar attribute search functionality in the UnForm xmlreader object, which internally is using the pxplus xml() function.  If the customer has UnForm, like a lot of yours do, you could write a simple job that uses that object.

Josh Fake

  • Member
  • **
  • Posts: 13
    • View Profile
    • Earnest & Associates
Re: XML Parser - Find Node based on Attribute Value
« Reply #4 on: March 29, 2019, 12:34:05 PM »
Thanks Allen, this client uses Unform extensively.   I might check it out as I could use your REST interfaces to post the Question Node and have it return a response back to FACTS as a new alternative.

Mike King

  • Diamond Member
  • *****
  • Posts: 3811
  • Mike King
    • View Profile
    • BBSysco Consulting
Re: XML Parser - Find Node based on Attribute Value
« Reply #5 on: March 29, 2019, 02:49:03 PM »
Actually the easiest solution might be to use the *obj/xml object we supply.

You can load it with the contents of the XML file then use Find_Node to find desired node/attribute.

Here is the code based on the XML you provided having been put in the file test.xml:

Code: [Select]
0010 LET oXml=NEW("*obj/xml" FOR PROGRAM) ! The FOR PROGRAM drops when done
0020 OPEN (1,ISZ=-1)"test.xml"
0030 READ RECORD (1,SIZ=1000000)R$ ! Read whole file into string
0040 CLOSE (1)
0050 oXml'set_xml(R$)
0060 LET oNode=0
0070 LET oQuestions=oXml'Find_node("Questions")
0080 WHILE 1
0090 LET oNode=oQuestions'Find_node("Question",oNode)
0100 IF oNode=0 THEN BREAK
0110 IF oNode'Find_Attr("Name")'Value$="Shape" THEN BREAK
0120 WEND
0130 IF oNode=0 THEN PRINT "not found" ELSE PRINT oNode'Find_node("Answer")'Value$

The steps were:
  • Create the XML object
  • Read the whole file into memory (used a dummy large SIZ= to assure whole file)
  • Passed file to Set_xml method
  • Found the Questions Node
  • Loop through each Question looking for any question with attribute of "Name" = "Shape"
  • Printed our the value of the 'Answer" node for that Question.


Mike King
President - BBSysco Consulting
eMail: mike.king@bbsysco.com

Peter.Higgins

  • Diamond Member
  • *****
  • Posts: 124
    • View Profile
Re: XML Parser - Find Node based on Attribute Value
« Reply #6 on: April 19, 2019, 09:21:35 AM »
Josh,
Since PVX has object inheritance, I would suggest a re-class of the xml object to add Mikes attribute search function so the code is reusable and not in the edited programs.   If the process does a large amount of searching in large files, adding an override of the *obj/xml parser routine to add a memory file with alternate keys on the attributes etc would be warranted.