I have started to play around a bit with classes and am building an XML data loader (yes, I could use XFiles or similar although not sure they actually support what I want to do?)
I want to load an XML file which has an unlimited set of child elements all of which are of the same type but form a hierarchy.
For example:
Etc.
So building a class but I am struggling how to do recursion in my class structure.
Item CLASS, TYPE
ItemName STRING(20)
Children QUEUE(Item) or QUEUE (&Item) don’t work
END
Also tried this but it doesn’t work as the QUEUE references an Item but it is bot declared yet and the item references the queue which is also not declared.
ChildrenQ QUEUE, TYPE
Child Item
END
Item CLASS,TYPE
ItemName String(20)
Children &ChildrenQ
END
Ironically I’m working on a new xFiles engine that does “tree parsing” (like the jFiles engine does) so yes, does what you would want it to do.
But as a learning exercise your approach is valuable to your learning curve.
When working with queues of NEW’d references
I find it extremely helpful to use my ctQueue class
to make it simple to ensure you are DISPOSEing everything correctly.
You just derive the .DEL() method, and take care of DISPOSE for ONE RECORD Everything else is just taken care of for you.
When you dispose the class, the PARENT.DESTRUCT calls SELF.FREE() which in turn loops over the queue calling .DEL()
note: you don’t even have to check IF NOT (SELF.Q.Children &= NULL)
before disposing it, as DISPOSE( MyNullRef ) is safe - it just does nothing.
INCLUDE('ctQueue.inc'),ONCE
gtItem GROUP,TYPE
ItemName STRING(42)
! whatever fields are of interest
END
gtItemTree GROUP,TYPE
Item LIKE(gtItem)
Children &ctQ_ItemTree
END
qtItemTree QUEUE(gtItemTree),TYPE
END
ctQ_ItemTree CLASS(ctQueue),TYPE,MODULE('ctQ_ItemTree.clw'),LINK('ctQ_ItemTree.clw')
Q &qtItemTree
!------------------------
CONSTRUCT PROCEDURE()
Del PROCEDURE(),DERIVED
AddItem PROCEDURE(*gtItem xItem)
AddChild PROCEDURE(*gtItem xItem)
END
!for the 'ctQ_ItemTree.clw'
MEMBER()
INCLUDE('ctQ_ItemTree.inc'),ONCE
MAP
END
!=======================================
ctQ_ItemTree.CONSTRUCT PROCEDURE()
CODE
SELF.Q &= NEW qtItemTree
CLEAR(SELF.Q)
SELF.BaseQ &= SELF.Q
!=======================================
ctQ_ItemTree.Del PROCEDURE()!,DERIVED
CODE
DISPOSE(SELF.Q.Children)
PARENT.Del()
!=======================================
ctQ_ItemTree.AddItem PROCEDURE(*gtItem xItem)
CODE
SELF.Q.Item = xItem
SELF.Q.Children &= NULL
ADD(SELF.Q)
!=======================================
ctQ_ItemTree.AddChild PROCEDURE(*gtItem xItem)
CODE
IF SELF.Q.Children &= NULL
SELF.Q.Children &= NEW ctQ_ItemTree
PUT(SELF.Q)
END
SELF.Q.Children.AddItem( xItem )