Home > Software design >  parsing XML and inserting node data into cursors
parsing XML and inserting node data into cursors

Time:01-11

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: 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

CodePudding user response:

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

CodePudding user response:

(I wouldn't use this at all, just replying because you asked where you made a mistake. I would definitely suggest Marco's code, or simply use Strextract() plus XMLToCursor())

In your code you are trying to insert a complete object but you need its 'value'.

Never ever create a data structure with just c, specify a length, ie:c(10)

Instead of using if someThing = .F. you could simply use if !someThing

Local lcXML As c

lcXML = "C:\temp\myxml.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(10))
Create Cursor Csrstatetransitions (Current c(10), [Next] c(10))

parseXML(lcXML, lcAttrValue_stateValue, lcAttrValue_tranFrom, lcAttrValue_tranTo)

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
        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).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 Empty(loAttributeList.getNamedItem(value_from).Value)
                        Insert Into Csrstatetransitions Values ("<Initial>", ;
                            loAttributeList.getNamedItem(value_to).Value)

                    Else
                        Insert Into Csrstatetransitions Values ;
                            (loAttributeList.getNamedItem(value_from).Value, ;
                            loAttributeList.getNamedItem(value_to).Value)

                    Endif
                Endif
            Endif
        Endif
    Endfor
Endproc

CodePudding user response:

For more complex XML, take a look at the XMLAdapter class. It's designed to keep you from having to deal directly with the DOM.

Tamar

  • Related