Wiki Home

Menu To Xml


Namespace: VB
This is my first contribution to the Wiki world.
I hope I don't blow it ;-)

This function converts a VFP menu from MNX table to XML file.


*---------------------------------------------------------------------
* Test MenuToXml()
*---------------------------------------------------------------------
source = "yourMenu.mnx"
target = "yourMenu.xml"
MenuToXml(source,target)
oShell = NewObject("WScript.Shell")
oShell.Run(target)
Return

*---------------------------------------------------------------------
* MenuToXml: pass source MenuName.mnx and target FileName.xml
*---------------------------------------------------------------------
Function MenuToXml(mnxFileName,xmlFileName)
*-- Let's get the party started
    menuAlias = "foxmenu"
    If Lower(Right(Alltrim(mnxFileName),3))<>"mnx" ;
    Or Not File(mnxFileName) Then
        mnxFileName = Getfile("Menu File (*.mnx):MNX","Menu File","Open",0,"Menu To Xml")
        If Empty(mnxFileName) Then
            Return ""
        Endif
    Endif

    oldSelect = Select()
    Use In Select(menuAlias)
    Use (mnxFileName) In 0 Again Alias (menuAlias)

*-- Some dirty job is done here, close your eyes
    Local newNode As MSXML2.IXMLDOMElement

    oXml = NewObject("MSXML2.DOMDocument")
    oXml.Async = .T.
    oXml.PreserveWhiteSpace = .F.


    Select (menuAlias)
    Locate
*-- 1st Record has menu info
    Skip
*-- 2nd Record has menu name
    menuName = foxmenu.Name
    oRoot = oXml.createElement("Menu")
    oRoot.setAttribute("name",menuName)

*-- Loop through pads and items
    Do While Not Eof(menuAlias)

        Skip
        If Eof(menuAlias) Then
            Exit
        Endif
        If foxmenu.objType = 2 Then && is Submenu
            ParseItems(@newNode,foxmenu.levelName)
        Else
            NewPad(@newNode)
        Endif
        oRoot.AppendChild(newNode)
    Enddo

    oXml.documentElement = oRoot
    xmlStream = oXml.XML

*-- Save the xml file, we don't wanna lose our hard work
    If Vartype(xmlFileName)=="C" And Not Empty(xmlFileName) Then
        oXml.Save(xmlFileName)
    Endif

*-- Clean up the mess and fly like a butterfly
    Use In Select(menuAlias)
    Select (oldSelect)
    Release oXml, oNode

    Return xmlStream
Endfunc
*---------------------------------------------------------------------
Function ParseItems(oNode,thisLevel)
    Do While Not Eof(menuAlias)
        Skip
        If foxmenu.levelName <> thisLevel Then && break level
            If foxmenu.objType = 2 Then && is Submenu
                ParseItems(@newNode,foxmenu.levelName)
            Else
                Skip -1
                Exit
            Endif
        Else
            newNode = Null
            If foxmenu.Prompt == "\-" Then && separator
                NewSeparator(@newNode)
            Else
                NewItem(@newNode)
            Endif
        Endif
        oNode.AppendChild(newNode)
    Enddo
EndFunc
*---------------------------------------------------------------------
Function NewPad(newNode)
    newNode = oXml.createElement("Pad")
    newNode.setAttribute("id",Alltrim(foxmenu.itemNum))
    newNode.setAttribute("name",foxmenu.Name)
    newNode.setAttribute("prompt",foxmenu.Prompt)
    If Not Empty(foxmenu.SkipFor) Then
        newNode.setAttribute("skipFor",foxmenu.SkipFor)
    Endif
    If Not Empty(foxmenu.Message) Then
        newNode.setAttribute("message",foxmenu.Message)
    Endif
EndFunc
*---------------------------------------------------------------------
Function NewItem(newNode)
    newNode = oXml.createElement("Item")
    newNode.setAttribute("id",Alltrim(foxmenu.itemNum))
    newNode.setAttribute("prompt",foxmenu.Prompt)
    If Not Empty(foxmenu.KeyName) Then
        newNode.setAttribute("keyName",foxmenu.KeyName)
    Endif
    If Not Empty(foxmenu.KeyLabel) Then
        newNode.setAttribute("keyLabel",foxmenu.KeyLabel)
    Endif
    If foxmenu.Mark<>Chr(0) Then
        newNode.setAttribute("mark","Yes")
    Endif
    If Not Empty(foxmenu.SkipFor) Then
        newNode.setAttribute("skipFor",foxmenu.SkipFor)
    Endif
    If Not Empty(foxmenu.ResName) Then
        newNode.setAttribute("image",foxmenu.ResName)
    Endif
    If Not Empty(foxmenu.Message) Then
        newNode.setAttribute("message",foxmenu.Message)
    Endif
    If Not Empty(foxmenu.Command) Then
        newNode.setAttribute("command",foxmenu.Command)
    Endif
EndFunc
*---------------------------------------------------------------------
Function NewSeparator(newNode)
    newNode = oXml.createElement("Item")
    newNode.setAttribute("id",foxmenu.itemNum)
    newNode.setAttribute("type","Separator")
EndFunc
*---------------------------------------------------------------------
* End of MenuToXml.prg
*---------------------------------------------------------------------


Hmm, I wonder how to make the PRE tag color coded for VFP.
Is there a css class definition somewhere?
Ok, ok, I recognize I didn't RTFM.
I'll find out...

Ok, now we have a menufile in XML. Great job! But for what do I need this? Where's the benefit? Why did you do it? ?wOOdy

Hey!
That's a good question.
Hmm, perhaps to show how useless xml is ?
Yep, that's a good one.

~~ George Nava

If this were to be used with vfpx's oop menu project and a builder were to be created that stores menu configuration to an xml file, xml that will be parsed at runtime to create the oop menu .. now that would be nice :) -- ?edyshor

---

For menu files older than VFP7, you need to test for the number of fields being only 23 as follows:
Set a global variable for the number of fields at the top of the file

LOCAL vMenu

vmenu = 0

Get the number of fields in the MNX file using AFIELDS()

Use (mnxFileName) In 0 Again Alias (menuAlias)
vMenu = AFIELDS(&menuAlias)

and test for this being greater than 23 before using the "ResName" field in an node in Function NewItem(newNode)

IF vMenu > 23
If Not Empty(foxmenu.ResName) Then
newNode.setAttribute("image",foxmenu.ResName)
ENDIF
ENDIF

Then it will work with older MNX files as well


Right now i'm interested in replacing the standard vfp menu system with the OOP menu project from VFPX and a builder that creates xml like source that should be parsed and loaded by a wrapper. Does anyone have any ideea (on the builder particulary) -- ?edyshor

Category Code Samples
( Topic last updated: 2010.07.30 11:42:57 AM )