March 05, 2021, 06:34:41 AM

Author Topic: [bmx] XML Parser & Saver by Pineapple [ 1+ years ago ]  (Read 591 times)

Offline BlitzBot

[bmx] XML Parser & Saver by Pineapple [ 1+ years ago ]
« on: June 29, 2017, 12:28:41 AM »
Title : XML Parser & Saver
Author : Pineapple
Posted : 1+ years ago

Description : The module pine.BinTree is required to run this code.

<a href="../Community/posts6a58.html?topic=97992" target="_blank">http://blitzbasic.com/Community/posts.php?topic=97992[/url]

Download it directly here:

<a href="http://dl.dropbox.com/u/10116881/blitz/pine.bintree/pine.bintree.mod.zip" target="_blank">http://dl.dropbox.com/u/10116881/blitz/pine.bintree/pine.bintree.mod.zip[/url]

My apologies for using BinTree instead of a native module, TList would cause huge slowdowns with larger lists of nodes or attributes, and TMap doesn't allow multiple entries for the same key.


Code :
Code: BlitzMax
  1. '       --+-----------------------------------------------------------------------------------------+--
  2. '         |   This code was originally written by Sophie Kirschner (sophiek@pineapplemachine.com)   |  
  3. '         | It is released as public domain. Please don't interpret that as liberty to claim credit |  
  4. '         |   that isn't yours, or to sell this code when it could otherwise be obtained for free   |  
  5. '         |                because that would be a really shitty thing of you to do.                |
  6. '       --+-----------------------------------------------------------------------------------------+--
  7.  
  8. SuperStrict
  9.  
  10. Import pine.BinTree
  11. Import brl.stream
  12.  
  13.  
  14. ' example program
  15. ' loads your xml file named 'example_input.xml', parses it, and then writes it as 'example_output.xml'
  16. Rem
  17. Local f:TStream=ReadFile("example_input.xml")
  18. Local n:xmlnode=xmlnode.read(f)
  19. CloseFile f
  20. f=WriteFile("example_output.xml")
  21. n.write f
  22. CloseFile f
  23. End
  24. EndRem
  25.  
  26.  
  27. Rem
  28. bbdoc: XML Node type
  29. about: children:BinTree and attributes:BinTree are two fields containing all the children nodes and the attributes, respectively.
  30. They can be iterated through using EachIn. (For a:xmlattribute=EachIn node.attributes; For n:xmlnode=EachIn node.children)
  31. TreeFind:Object(tree:BinTree,key$) will return the first value in the tree with the given key.
  32. TreeFindAll:TList(tree:BinTree,key$) will return a TList containing all the values in the tree with the given tree.
  33. See the BinTree documentation for more detailed info and how to iterate through keys, nodes containing key/value pairs, manipulation, etc.
  34. EndRem
  35. Type xmlnode
  36.         Field name$
  37.         Field children:BinTree=CreateTree()
  38.         Field attributes:BinTree=CreateTree()
  39.         Rem
  40.         bbdoc: Returns a new xmlnode.
  41.         EndRem
  42.         Function Create:xmlnode(name$)
  43.                 Local n:xmlnode=New xmlnode
  44.                 n.name=name
  45.                 Return n
  46.         End Function
  47.         Rem
  48.         bbdoc: Adds a new child.
  49.         EndRem
  50.         Method addchild(n:xmlnode)
  51.                 Assert n,"Cannot assign a nonexistent xmlnode as a child."
  52.                 children.insert n.name,n
  53.         End Method
  54.         Rem
  55.         bbdoc: Adds a new attribute.
  56.         returns: The created xmlattribute object.
  57.         EndRem
  58.         Method addattribute:xmlattribute(name$,value$)
  59.                 Local a:xmlattribute=New xmlattribute
  60.                 a.name=name
  61.                 a.value=value
  62.                 attributes.insert name,a
  63.                 Return a
  64.         End Method
  65.         Rem
  66.         bbdoc: Removes a child.
  67.         EndRem
  68.         Method removechild(n:xmlnode)
  69.                 Assert a,"Attempted to remove nonexistent XML node."
  70.                 children.removevalue(n,n.name)
  71.         End Method
  72.         Rem
  73.         bbdoc: Removes an attribute.
  74.         EndRem
  75.         Method removeattribute(a:xmlattribute)
  76.                 Assert a,"Attempted to remove nonexistent XML attribute."
  77.                 attributes.removevalue(a,a.name)
  78.         End Method
  79.         Rem
  80.         bbdoc: Returns the value assocated with some attribute name.
  81.         EndRem
  82.         Method getvalue$(name$)
  83.                 Local val:xmlattribute=xmlattribute(attributes.find(name))
  84.                 If Not val Return ""
  85.                 Return val.value
  86.         End Method
  87.         Rem
  88.         bbdoc: Returns the attribute assocated with the given name.
  89.         EndRem
  90.         Method getattribute:xmlattribute(name$)
  91.                 Return xmlattribute(attributes.find(name))
  92.         End Method
  93.         Rem
  94.         bbdoc: Returns the first encountered child node with the given name.
  95.         EndRem
  96.         Method getchild:xmlnode(name$)
  97.                 Return xmlnode(children.find(name))
  98.         End Method
  99.         Rem
  100.         bbdoc: Returns a list of all child nodes with the given name.
  101.         EndRem
  102.         Method getchildren:TList(name$)
  103.                 Return children.findall(name)
  104.         End Method
  105.         Rem
  106.         bbdoc: Read an XML Node (along with any children) from a stream.
  107.         EndRem
  108.         Function read:xmlnode(f:TStream)
  109.                 Local n:xmlnode=New xmlnode
  110.                 While ReadByte(f)<>opentag
  111.                         Assert Not Eof(f),"Encountered unexpected end-of-file."
  112.                 Wend
  113.                 Local nb%
  114.                 Local tag$=""
  115.                 Repeat
  116.                         nb=ReadByte(f)
  117.                         If nb=fintag Then Exit
  118.                         tag:+Chr(nb)
  119.                 Forever
  120.                 Assert Len(tag),"Encountered illegal tag: <>"
  121.                 If Asc(Right(tag,1))=closetag Then ' has no children
  122.                         tag=Left(tag,tag.length-1)
  123.                 ElseIf Asc(Left(tag,1))=closetag Then ' is a closing tag
  124.                         Return Null
  125.                 Else
  126.                         Local clist:TList=CreateList()
  127.                         Repeat
  128.                                 Local c:xmlnode=read(f)
  129.                                 If c Then
  130.                                         clist.addfirst c
  131.                                 Else
  132.                                         Exit
  133.                                 EndIf
  134.                         Forever
  135.                         For Local c:xmlnode=EachIn clist
  136.                                 n.children.insert c.name,c
  137.                         Next
  138.                 EndIf
  139.                 n.parsetag tag
  140.                 Assert n.name,"Encountered nameless tag."
  141.                
  142.                 Rem
  143.                 ?debug
  144.                 DebugLog "Read xmlnode: "+n.name
  145.                 Local attrstr$=""
  146.                 For Local a:xmlattribute=EachIn n.attributes
  147.                         attrstr:+a.name+" = ~q"+a.value+"~q; "
  148.                 Next
  149.                 Local chldstr$=""
  150.                 For Local c:xmlnode=EachIn n.children
  151.                         chldstr:+c.name+"; "
  152.                 Next
  153.                 DebugLog "Attributes: "+attrstr
  154.                 DebugLog "Children: "+chldstr
  155.                 ?
  156.                 EndRem
  157.                
  158.                 Return n
  159.         End Function
  160.         Rem
  161.         bbdoc: Write an XML Node (and all its children) to a stream.
  162.         EndRem
  163.         Method write(f:TStream,prefix$="")
  164.                 Assert f,"Stream does not exist."
  165.                 WriteString f,prefix
  166.                 WriteByte f,opentag
  167.                 WriteString f,name
  168.                 For Local a:xmlattribute=EachIn attributes
  169.                         WriteByte f,space
  170.                         WriteString f,a.name
  171.                         WriteByte f,equals
  172.                         WriteByte f,quote
  173.                         WriteString f,a.value
  174.                         WriteByte f,quote
  175.                 Next
  176.                 If children.isempty() Then
  177.                         WriteByte f,space
  178.                         WriteByte f,closetag
  179.                         WriteByte f,fintag
  180.                         WriteByte f,newl
  181.                 Else
  182.                         WriteByte f,fintag
  183.                         WriteByte f,newl
  184.                         For Local n:xmlnode=EachIn children
  185.                                 n.write f,prefix+Chr(tab)
  186.                         Next
  187.                         WriteString f,prefix
  188.                         WriteByte f,opentag
  189.                         WriteByte f,closetag
  190.                         WriteString f,name
  191.                         WriteByte f,fintag
  192.                         WriteByte f,newl
  193.                 EndIf
  194.         End Method
  195.        
  196.         ' private stuff that you shouldn't need to touch
  197.         Const opentag%=Asc("<")
  198.         Const closetag%=Asc("/")
  199.         Const fintag%=Asc(">")
  200.         Const space%=Asc(" ")
  201.         Const tab%=Asc("        ")
  202.         Const newl%=Asc("~n")
  203.         Const equals%=Asc("=")
  204.         Const quote%=Asc("~q")
  205.         Function iswhitespace%(c%)
  206.                 Return (c=space) Or (c=tab) Or (c=newl)
  207.         End Function
  208.         Method parsetag(str$)
  209.                 Local x%=0
  210.                 Local on$="",spaces%=0
  211.                 Local inquotes%=0
  212.                 Local lastwasspace%=1
  213.                 Local lasta:xmlattribute
  214.                 While x<str.length
  215.                         If inquotes=0 And iswhitespace(str[x]) Then
  216.                                 If Not lastwasspace
  217.                                         If spaces=0 Then
  218.                                                 name=on
  219.                                                 on=""
  220.                                                 spaces=1
  221.                                         EndIf
  222.                                         lastwasspace=1
  223.                                 EndIf
  224.                         ElseIf inquotes=0 And str[x]=equals
  225.                                 Local a:xmlattribute=New xmlattribute
  226.                                 a.name=on
  227.                                 attributes.insert a.name,a
  228.                                 lasta=a
  229.                                 on=""
  230.                                 lastwasspace=0
  231.                         ElseIf str[x]=quote
  232.                                 If inquotes
  233.                                         Assert lasta,"Encountered malformed tag."
  234.                                         lasta.value=on
  235.                                         on=""
  236.                                         lasta=Null
  237.                                 EndIf
  238.                                 inquotes=Not inquotes
  239.                                 lastwasspace=0
  240.                         ElseIf lasta And inquotes
  241.                                 on:+Chr(str[x])
  242.                                 lastwasspace=0
  243.                         ElseIf Not lasta
  244.                                 on:+Chr(str[x])
  245.                                 lastwasspace=0
  246.                         EndIf
  247.                         x:+1
  248.                 Wend
  249.                 If Not spaces Then
  250.                         name=on
  251.                 EndIf
  252.         End Method
  253.        
  254. End Type
  255.  
  256. Rem
  257. bbdoc: XML Node Attribute type
  258. EndRem
  259. Type xmlattribute
  260.         Field name$
  261.         Field value$
  262. End Type


Comments :


Bobysait(Posted 1+ years ago)

 
Code: [Select]
Method removechild(n:xmlnode)
Assert a,"Attempted to remove nonexistent XML node."
children.removevalue(n,n.name)
End Method
-> Assert nWhile it can't even compile this in SuperStrict, I'm wondering, did you tried your own code before posting it ? [/i]

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal