Page 1 of 1

XML Sample Program

Posted: Sat Jun 02, 2007 2:46 pm
by akj
To learn about the new PureBasic XML library I wrote a small program to analyse an XML file that is based on the one shown at http://en.wikipedia.org/wiki/XML

I called the file XML Sample.txt and it contains:

Code: Select all

<book title="Mecanique" authors="Landau, Lifshitz">
  <chapter title="equations du mouvement">
     <section title="coordonnees generalisees">
        Une des notions fondamentales de la Mecanique est celle de point materiel. ....
     </section>
     <section title="Le principe de moindre action">
        La formule la plus generale de la loi du mouvement des systemes mecaniques est
        fournie par le principe dit de moindre action (ou principe de Hamilton). ....
     </section>
     [Chapter 1 text]
   </chapter>
   <chapter title = "lois de conservation">
     [Chapter 2 text]
   </chapter>
   [Book text]
</book>
My program which analyses this file is:

Code: Select all

file$ = "XML Sample.txt"

Procedure ShowNode(label$, *node)
; Display node attributes and text
Protected tab$ = Space(4), text$
If *node
  Debug label$+":"
  Debug tab$+"Node name = "+GetXMLNodeName(*node)
  ExamineXMLAttributes(*node)
  While NextXMLAttribute(*node)
    Debug tab$+XMLAttributeName(*node)+" = "+XMLAttributeValue(*node)
  Wend
  text$ = GetXMLNodeText(*node)
  text$ = Trim(ReplaceString(text$, #CRLF$, " "))
  Debug tab$+"Node text = "+text$
  Debug tab$+"Child nodes = "+Str(XMLChildCount(*node))
EndIf
EndProcedure

tree = LoadXML(#PB_Any, file$)
Debug "Tree = "+Str(tree)
status = XMLStatus(tree)
Debug "Status = "+Str(status)
If status=0
  *node = MainXMLNode(tree)
  While *node
    ShowNode("Parent", *node)
    For child = 1 To XMLChildCount(*node)
      *child = ChildXMLNode(*node, child)
      ShowNode("Child "+Str(child), *child)
      For grandchild = 1 To XMLChildCount(*child)
        *grandchild = ChildXMLNode(*child, grandchild)
        ShowNode("Grandchild "+Str(grandchild), *grandchild)
      Next grandchild
    Next child
    *node = NextXMLNode(*node)
  Wend
  FreeXML(tree)  
EndIf
End
As it helped me, I am sharing my code in the hope it will also help other people.
I realise it can be improved by recursively traversing the XML tree, but at least it's a start.

Posted: Sat Jun 02, 2007 3:11 pm
by ts-soft
thx for this, i am also testing the xml stuff :wink:

I'm missing something

Posted: Sat Jun 02, 2007 3:51 pm
by exjoburger
When I try to compile the code I get the compiler message: "Line 8: GetXMLNodeName() is not a function, array, macro or linked list".
As a newbie to PureBasic I must be missing something?

Re: I'm missing something

Posted: Sat Jun 02, 2007 3:53 pm
by thefool
exjoburger wrote:When I try to compile the code I get the compiler message "GetXMLNodeName() is not a function, array, macro pr linked list".
As a newbie to PureBasic I must be missing something?
You miss the latest beta version, available from your personal account :)
http://www.purebasic.fr/english/viewtopic.php?t=27343

Posted: Sat Jun 02, 2007 3:53 pm
by exjoburger
Ah, thank you :oops:

Posted: Sat Jun 02, 2007 8:08 pm
by Comtois
here is my try to learn about xml.

file "plan.xml" (using OgreXMLConverter.exe)

Code: Select all

<mesh>
    <submeshes>
        <submesh material="plan/system" usesharedvertices="false" use32bitindexes="false" operationtype="triangle_list">
            <faces count="2">
                <face v1="2" v2="1" v3="0" />
                <face v1="0" v2="3" v3="2" />
            </faces>
            <geometry vertexcount="4">
                <vertexbuffer positions="true" normals="true" texture_coord_dimensions_0="2" texture_coords="1">
                    <vertex>
                        <position x="0" y="0" z="0" />
                        <normal x="0" y="1" z="0" />
                        <texcoord u="-2" v="-2" />
                    </vertex>
                    <vertex>
                        <position x="1" y="0" z="0" />
                        <normal x="0" y="1" z="0" />
                        <texcoord u="2" v="-2" />
                    </vertex>
                    <vertex>
                        <position x="1" y="0" z="1" />
                        <normal x="0" y="1" z="0" />
                        <texcoord u="2" v="2" />
                    </vertex>
                    <vertex>
                        <position x="0" y="0" z="1" />
                        <normal x="0" y="1" z="0" />
                        <texcoord u="-2" v="2" />
                    </vertex>
                </vertexbuffer>
            </geometry>
        </submesh>
    </submeshes>
</mesh>

Code: Select all

file$ = "plan.xml"

Procedure AddNode(*Node, Position)
  AddGadgetItem (0, -1, GetXMLNodeName(*Node), 0, position) 
  For child = 1 To XMLChildCount(*Node)
    *child = ChildXMLNode(*Node, child)
    AddNode(*child, position+1)
  Next  
EndProcedure

OpenWindow(0, 0, 0, 355, 280, "TreeGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CreateGadgetList(WindowID(0))
TreeGadget(0, 10, 10, 260, 260)                                         
tree = LoadXML(#PB_Any, file$)
status = XMLStatus(tree)
If status=0
  AddNode(MainXMLNode(tree), 0)
EndIf

Repeat

Until WaitWindowEvent() = #PB_Event_CloseWindow

Posted: Sat Jun 02, 2007 8:32 pm
by akj
@Contois:
I like your efficient method of showing the tree structure.

I have modified my original program given at the start of this topic to recurse through all node levels and it seems to work correctly on your plan.xml file. The new code is:

Code: Select all

; XML Tree Parse  AKJ  02-Jun-07

EnableExplicit
Define file$ = "plan.xml"

Procedure ShowNode(label$, *node)
; Display node attributes and text
Protected tab$ = Space(4), text$
If *node
  Debug label$+":"
  text$ = GetXMLNodeText(*node)
  text$ = Trim(ReplaceString(text$, #CRLF$, " "))
  Select XMLNodeType(*node)
  Case #PB_XML_Root
    Debug tab$+"Child nodes = "+Str(XMLChildCount(*node))
  Case #PB_XML_Comment
    Debug tab$+"Comment = "+text$
  Case #PB_XML_CData
    Debug tab$+"CDATA text = "+text$
    Debug tab$+"CDATA offset = "+Str(GetXMLNodeOffset(*Node))+" bytes"
  Default
    Debug tab$+"Node name = "+GetXMLNodeName(*node)
    ExamineXMLAttributes(*node)
    While NextXMLAttribute(*node)
      Debug tab$+XMLAttributeName(*node)+" = "+XMLAttributeValue(*node)
    Wend
    Debug tab$+"Node text = "+text$
    Debug tab$+"Child nodes = "+Str(XMLChildCount(*node))
  EndSelect
EndIf
EndProcedure

Procedure Traverse(*node)
; Call ShowNode() for each descendant node
Static level = 0 ; Recursion level
Protected children, child, *child
level + 1
children = XMLChildCount(*node)
For child = 1 To children
  *child = ChildXMLNode(*node, child)
  ShowNode("Level "+Str(level)+"    Node "+Str(child)+" of "+Str(children), *child)
  Traverse(*child)
Next child
level - 1
EndProcedure

; Main program
Define tree, error, *node
tree = LoadXML(#PB_Any, file$)
Debug "Tree = "+Str(tree)
error = XMLStatus(tree)
If error
  Debug "Error "+Str(error)+" at line "+Str(XMLErrorLine(tree))+": "+XMLError(tree)
Else ; If OK
  *node = RootXMLNode(tree)
  ShowNode("Level 0    Root Node", *node)
  Traverse(*node)
  FreeXML(tree)
EndIf
End
The above code utilises some of the XML error routines.
It also shows a typical usage of a static variable.

Posted: Wed Jun 06, 2007 2:47 am
by kenmo
Is it just me, or does GetXMLAttribute() not seem to work?

Code: Select all

If CreateXML(0)
	*Node.l = CreateXMLNode(RootXMLNode(0), 0)
	SetXMLNodeName(*Node, "main")
	SetXMLAttribute(*Node, "att", "val")
	Debug GetXMLAttribute(*Node, "att")
EndIf
*edit: Ah, its already in the Bug Reports...

Posted: Sun Jul 15, 2007 8:15 pm
by akj
A useful free XML editor/viewer is at http://symbolclick.com