XML object V11.00

From PxPlus

Jump to: navigation, search

The *obj/xml object is designed to make the parsing and generation of XML easy for most applications.

Contents

Internal design

Internally when handling XML with the object, each XML tag is stored as an object with a tree structure linked from the root object (*obj/xml). Walking this tree structure can be done by referencing each node on the trees 'Node(nn) method, which returns the object for each subordinate node (which in turn themselves may have sub-ordinates). The 'Nodes property contains the number of immediately sub-ordinate nodes.

For each node there is also a 'TAG$ property that defines the XML tag and 'VALUE$ for the textual contents of each node.

There is also a single level list of attributes for each node representing the XML attributes for a tag. The number of attributes can be found in the property 'attrs, which each attribute itself being a node accessible via 'attr(nn) and have a 'TAG$ and 'VALUE$ attribute.

For example the XML of:

<company type="Corporation">
 <name>PVX Plus Technologies</name>
 <address>45B West Wilmot</address>
 <phone type="North American">1-888-975-7587</phone>
</company>

The first node would have a TAG$ of "company" with Attrs of 1. Its 'Attr(1)'Tag$ field would be "type" and its value would be "Corporation". The number of subordinate nodes ('Nodes) would be 3.

'Node(1)'Tag$ would be "name"
'Node(1)'Value$ would be "PVX Plus Technologies"
'Node(2)'Tag$ would be "address"
'Node(2)'Value$ would be "45B West Wilmot"
'Node(2)'Tag$ would be "Phone"
'Node(2)'Value$ would be "1-888-975-7587"
'Node(2)'Attrs would be 1
'Node(2)'Attr(1)'Tag$ would be "type"
'Node(2)'Attr(1)'Value$ would be "North American"

Methods/Properties

Method Description
set_xml(xml$) Load and create nodes given XML string in xml$. This creates a dummy top level node in which all top level XML structures are placed. This allows the input XML to contain multiple top level structures.
set_xml_1(xml$) This will load a single node from the XML string and will report an error 42 if it encounters multiples. This avoids the top-level node that may contain multiple nodes.
get_xml$() Return the XML string from the object and sub-ordinate nodes.
node(n) Return the sub node object 'n'
attr(n) Return the attribute object 'n'
add_node(n) Add a new sub-node and return its object id. 'n' defines where to insert the new node (0=Append).
add_node(n, object) Insert the supplied sub node into the node table. The inserted object will have its reference count incremented as there will now be an additional reference to it.
del_node(n) Drop the node specified
add_attr(n) Add a new attribute and return its object id. 'n' defines where to insert the new node (0=Append).
del_attr(n) Drop the attribute specified
Properties Description
nodes Number of sub-nodes (only direct sub-ordinate nodes)
attrs Number of attributes
tag$ Node tag (i.e. the <..> keyword)
value$ Text value of the node

Example for Parsing XML

Let assume you have received and need to parse the following XML and have it loaded into the string XML$.

NOTE: When exchanging XML between systems most XML has a header of <?xml...?> which becomes Node(1) of the object. The true XML to be parsed actually starts at Node(2).

<?xml version="1.0" encoding="UTF-8"?>
<response>
      <control>
            <status>success</status>
            <senderid>JohnDoe</senderid>
            <controlid>create_project_simple</controlid>
            <uniqueid>false</uniqueid>
            <dtdversion>2.1</dtdversion>
      </control>
      <operation>
            <authentication>
                  <status>success</status>
                        …more…

So to load the XML into the XML object you would use the 'Set_xml(string$) method.

-:a=new("*obj/xml")  ! Create the object
-:a'set_xml(XML$)  ! Pass the XML string

Once loaded you can parse through all the nodes looking for what you want:

-:?a'node(1)'tag$
?xml
-:?a'node(2)'tag$
response
-:?a'node(2)'node(1)'tag$
control
-:?a'node(2)'node(1)'node(1)'tag$
status
-:?a'node(2)'node(1)'node(1)'value$
success
-:?a'node(2)'node(1)'node(2)'tag$
senderid
-:?a'node(2)'node(1)'node(2)'value$
JohnDoe

Of course you can assign variables to hold the node pointers to make the coding a bit simpler

-:oResponse=a'node(2)
-:oCtrl=oResponse'node(1)
-:print oCtrl'node(1)'tag$
status

To make finding the nodes you could likely create a small routine to spin through a node looking for a specific tag. Remember though that XML would allow multiple occurrences of same tag within a node so your logic might have deal with this. In our next release we will providing a function to do this automatically for you.

Generating XML

So lets assume you wanted to generate the following XML:

<request>
 <login>
  <userid>JohnDoe</userid>
  <password>drowssap</password>
  <database>Sample Corp</database>
 </login>
 <command>
  <create_prod>
   <prodcode>000123</prodcode>
   <desc>Blue widget</desc>
   <price currency='CDN'>1.23</price>
   <qty>10</qty>
   <uom>ea</uom>
  </create_prod>
 </command>
</request>

The logic to create this might look like this:

0010 LET oXml=NEW("*obj/xml") ! XML Object
0020 LET oReq=oXml'Add_node("request")
0030 ! 
0040 LET oLogin=oReq'Add_node("login")
0050 ! 
0060 LET oLogin'Add_node("userid")'value$="JohnDoe"
0070 LET oLogin'Add_node("password")'value$="drowssap"
0080 LET oLogin'Add_node("database")'value$="Sample_Corp"
0090 ! 
0100 LET oCmnd=oReq'Add_node("command")
0110 ! 
0120 LET oCreate=oCmnd'Add_node("create_prod")
0130 ! 
0140 LET oCreate'Add_node("prodcode")'value$="000123"
0150 LET oCreate'Add_node("desc")'value$="Blue Widget"
0160 ! 
0170 LET oPrice=oCreate'Add_node("price")
0180 ! 
0190 LET oPrice'value$="1.23"
0200 ! -- Add currency
0210 LET oPrice'add_attr("currency")'value$="CDN"
0220 ! 
0230 LET oCreate'Add_node("qty")'value$="10"
0240 LET oCreate'Add_node("uom")'value$="ea"
0250 ! 
0260 LET x$=oXml'Get_xml$()
0270 PRINT x$
0280 ! 
0290 DROP OBJECT oXml

For additional information see our online manual at http://manual.pvxplus.com/page/utilities/obj_xml.htm

Personal tools