I am looking to perform a simple XML parse in Visual FoxPro and extract the XML node values and attributes into cursors. I have found this webpage: https://www.foxite.com/archives/this-is-an-example-of-parsing-xml-in-foxpro-0000089226.htm a helpful base for my code if you also want to take a look. Right now I am running into an issue regarding the variable type which is returned from loAttributeList.getNamedItem("node_name"). I am getting conflicting messages wether this variable is an Object or a Character? The code I have below is something which I think should accomplish the creation of a simple cursor which stores the node attribute values. However right now it will return type errors due to trying to input values into my cursors which seem to be Objects.
local lcXML as c
lcXML = "C:\status_flow.xml"
local lcAttrValue_stateValue as c, lcAttrValue_tranFrom as c, lcAttrValue_tranTo as c
lcAttrValue_stateValue = "value" && attribute names for which the value will be added to cursor
lcAttrValue_tranFrom = "from"
lcAttrValue_tranTo = "to"
create cursor Csrstatus ([Status] c)
create cursor Csrstatetransitions (Current c, [Next] c)
parseXML(lcXML, lcAttrValue_stateValue, lcAttrValue_tranFrom, lcAttrValue_tranTo)
*******************************************************
* this procedure will parse the xml in pcXMLFile and transform the XML into two cursors
*****************************
procedure parseXML(pcXMLFile, value_value, value_from, value_to)
*****************************
local loXml, loRootNode, lcParentName, lcNodeName, lcValue, lcName, lnType, lnNumNodes, ;
loNodeList, loNode, lbHasChild, lcTagName, loChildNodeList, lnChildLen, lnPass, loChildNode, ;
loAttributeList, lcAttrName, lcAttrValue, lc, lnNumAttr, loParentNodeList, lnNumParentNodes
loXml = createobject("MSXML2.DOMDocument.6.0") && create the xml parser object
loXml.async = .f. && wait for teh document to be parsed and loaded
loXml.load(pcXMLFile) && load the document into the object
loRootNode = loXml.documentElement && get the root element
loNodeList = loRootNode.getElementsByTagName("*") && get all nodes in document
lnNumNodes = loNodeList.length && number of nodes in document
*? lnNumNodes
for lnPos = 0 to (lnNumNodes -1) && go through all nodes in loNodeList (note, array starting point 0 for XML nodes)
loNode = loNodeList.item(lnPos)
lcNodeName = loNode.nodeName
? lcNodeName
loAttributeList = loNode.attributes
lcAttrValue = loAttributeList.getNamedItem("value")
*? lcAttrValue_value
lnType = loNode.nodeType
if lnType = 1
if lcNodeName = "State" && if node name is "State", then we want to extract the nodes attribute into cursor
if isnull(loAttributeList.getNamedItem(value_value)) = .f.
insert into Csrstatus values ;
(loAttributeList.getNamedItem(value_value)) && doesnt work because type mismatch...
endif
endif
if lcNodeName = "Transition"
if isnull(loAttributeList.getNamedItem(value_from)) = .f. ;
and isnull(loAttributeList.getNamedItem(value_to)) = .f.
&& special case if 'from' node is empty
if loAttributeList.getNamedItem(value_from) = ""
insert into Csrstatetransitions values ("<Initial>", ;
loAttributeList.getNamedItem(value_to))
else
insert into Csrstatetransitions values ;
(loAttributeList.getNamedItem(value_from), ;
loAttributeList.getNamedItem(value_to))
endif
endif
endif
endif
endfor
endproc
The very simple xml I am parsing looks something like:
I am new to XML and the DOM with FoxPro so hopefully someone can help me further understand how to parse XML and extract values and attributes to foxpro cursors. If you see a better way to accomplish this compared to the loop structure I have in my code, feel free to share that as well. Otherwise, there are hopefully only some small changes needed in my code to get this to work.
The output of the two cursors should look something like:
Status |
---|
1 |
2 |
3 |
4 |
Current | Next |
---|---|
Initial | 1 |
1 | 2 |
1 | 3 |
1 | 4 |
2 | 3 |
2 | 4 |
3 | 4 |
For the specified source you can just do:
oxml=CREATEOBJECT('msxml.domdocument')
oxml.load("D:\yoursource.xml")
XMLTOCURSOR(oxml.selectSingleNode('/Patients/States').xml,'States')
XMLTOCURSOR(oxml.selectSingleNode('/Patients/Transitions').xml,'Transitions')
for more complex xml you can use a xml parser -Check nfXml: https://github.com/vfpx/nfxml