Search code examples
xmlvisual-foxpro

parsing XML and inserting node data into cursors


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: enter image description here

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

Solution

  • 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