XML for Data storage

XML

XML is a flexible, convenient, way of storing data, once you understand how.
Programs typically evolve thru several versions. This often results in different data items being stored. This has meant careful tracking of data version vs program versions, as programs could not correctly read data from the wrong data version.
XML is a flexible as names are stored with the data. Names which are understood can be read, while others are ignored. The downside is that missing variables may require defaults.
XML is a very convenient to use. The rules are quite simple.
XML consists of elements:

<name> text </name>

Every opening <name> is paired with a closing </name).
Names can be almost anything but are case sensitive.
Elements can be wholly contained within other elements. <Name1> <xyz> </xyz> </Name1>
Elements cannot overlap. <Name1> <xyz> </Name1> </xyz>

for more details visit: http://www.w3schools.com/xml/xml_syntax.asp

Saving Data

The following example shows only the code to open and write a file.
sub FileSaveAs
 filedialog "Save file", FilePath$+"*.Sudoku", FullName$
 call GetFileName$
 if FileName$="" then notice "No file chosen!": end
 call FileSave
end sub
 
sub FileSave
 open FullName$ for output as #File
 FileOpen = True
 #File "<XML>"
 #File "<!-- "; Date$();" "; Time$();" ";FullName$;" -->" 'XML comment
 #File " <Sudoku>"
 call SaveOptions
 call SaveCells
 #File " </Sudoku>"
 #File "</XML>"
 close #File
 FileOpen = False
 notice "Puzzle Saved ";chr$(13);_
 "File Name ";FileName$;chr$(13);_
 "at ";FilePath$
end sub
 
sub SaveCells
 for row = 1 to 9: for col = 1 to 9
 if CellValue(row,col) <> 0 then
 call SaveOneCell row, col, CellValue(row,col), CellStage(row,col)
 end if
 next col: next row
end sub
 
sub SaveOneCell row,col,value,stage
 #File " <Cell>";
 #File "<Row> ";row;
 #File " </Row>";
 #File "<Col> ";col;
 #File " </Col>";
 #File "<Value> ";value;
 #File " </Value>";
 if stage <> 1 then
 #File "<Stage> ";right$(" ";str$(stage),2);
 #File " </Stage>";
 else
 #File " ";
 end if
 #File "</Cell>"
end sub
 
sub SaveOptions
 #File " <Size> ";9;" </Size>"
 #File " <Diagonal>";
 if DiagActive then #File " On "; else #File " Off ";
 #File "</Diagonal>"
 #File " <Possible>";
 if PossibleShow then #File " On "; else #File " Off ";
 #File "</Possible>"
 #File " <Reduce> ";
 if ReduceActive then #File " On "; else #File " Off ";
 #File "</Reduce>"
end sub
 
sub GetFileName$
 for pos = len(FullName$) to 1 step -1
 if mid$(FullName$, pos, 1) = "\" then exit for
 next pos
 FileName$ = mid$(FullName$,pos+1)
 FilePath$ = left$(FullName$,pos)
end sub

XML for Data storage

XML

XML is a flexible, convenient, way of storing data, once you understand how.
Programs typically evolve thru several versions. This often results in different data items being stored. This has meant careful tracking of data version vs program versions, as programs could not correctly read data from the wrong data version.
XML is a flexible as names are stored with the data. Names which are understood can be read, while others are ignored. The downside is that missing variables may require defaults.
XML is a very convenient to use. The rules are quite simple.
XML consists of elements:

<name> text </name>

Every opening <name> is paired with a closing </name).
Names can be almost anything but are case sensitive.
Elements can be wholly contained within other elements: <Name1> <xyz> </xyz> </Name1>
Elements cannot overlap:<Name1> <xyz> </Name1> </xyz>

for more details visit: http://www.w3schools.com/xml/xml_syntax.asp

Saving Data


The following example shows only the code to open and write a file.
sub FileSaveAs
 filedialog "Save file", FilePath$+"*.Sudoku", FullName$
 call GetFileName$
 if FileName$="" then notice "No file chosen!": end
 call FileSave
end sub
 
sub FileSave
 open FullName$ for output as #File
 FileOpen = True
 #File "<XML>"
 #File "<!-- "; Date$();" "; Time$();" ";FullName$;" -->" 'XML comment
 #File " <Sudoku>"
 call SaveOptions
 call SaveCells
 #File " </Sudoku>"
 #File "</XML>"
 close #File
 FileOpen = False
 notice "Puzzle Saved ";chr$(13);_
 "File Name ";FileName$;chr$(13);_
 "at ";FilePath$
end sub
 
sub SaveCells
 for row = 1 to 9: for col = 1 to 9
 if CellValue(row,col) <> 0 then
 call SaveOneCell row, col, CellValue(row,col), CellStage(row,col)
 end if
 next col: next row
end sub
 
sub SaveOneCell row,col,value,stage
 #File " <Cell>";
 #File "<Row> ";row;
 #File " </Row>";
 #File "<Col> ";col;
 #File " </Col>";
 #File "<Value> ";value;
 #File " </Value>";
 if stage <> 1 then
 #File "<Stage> ";right$(" ";str$(stage),2);
 #File " </Stage>";
 else
 #File " ";
 end if
 #File "</Cell>"
end sub
 
sub SaveOptions
 #File " <Size> ";9;" </Size>"
 #File " <Diagonal>";
 if DiagActive then #File " On "; else #File " Off ";
 #File "</Diagonal>"
 #File " <Possible>";
 if PossibleShow then #File " On "; else #File " Off ";
 #File "</Possible>"
 #File " <Reduce> ";
 if ReduceActive then #File " On "; else #File " Off ";
 #File "</Reduce>"
end sub
 
sub GetFileName$
 for pos = len(FullName$) to 1 step -1
 if mid$(FullName$, pos, 1) = "\" then exit for
 next pos
 FileName$ = mid$(FullName$,pos+1)
 FilePath$ = left$(FullName$,pos)
end sub

Example data file:

<XML>
<!-- Mar 12, 2014 10:56:25 C:\Data\Sudoku\3.40.88.Sudoku -->
 <Sudoku>
 <Size> 9 </Size>
 <Diagonal> Off </Diagonal>
 <Possible> Off </Possible>
 <Reduce> Off </Reduce>
 <Cell><Row> 1 </Row><Col> 1 </Col><Value> 7 </Value> </Cell>
 <Cell><Row> 1 </Row><Col> 7 </Col><Value> 9 </Value> </Cell>
 <Cell><Row> 1 </Row><Col> 8 </Col><Value> 3 </Value> </Cell>
 <Cell><Row> 2 </Row><Col> 4 </Col><Value> 6 </Value> </Cell>
 <Cell><Row> 2 </Row><Col> 5 </Col><Value> 4 </Value> </Cell>
 <Cell><Row> 2 </Row><Col> 6 </Col><Value> 7 </Value><Stage> 2 </Stage></Cell>
 <Cell><Row> 3 </Row><Col> 1 </Col><Value> 1 </Value> </Cell>
 <Cell><Row> 3 </Row><Col> 9 </Col><Value> 7 </Value> </Cell>
 <Cell><Row> 4 </Row><Col> 2 </Col><Value> 6 </Value> </Cell>
 <Cell><Row> 4 </Row><Col> 3 </Col><Value> 8 </Value> </Cell>
 <Cell><Row> 4 </Row><Col> 4 </Col><Value> 5 </Value> </Cell>
 <Cell><Row> 4 </Row><Col> 7 </Col><Value> 7 </Value> </Cell>
 <Cell><Row> 5 </Row><Col> 4 </Col><Value> 3 </Value> </Cell>
 <Cell><Row> 5 </Row><Col> 5 </Col><Value> 8 </Value><Stage> 2 </Stage></Cell>
 <Cell><Row> 5 </Row><Col> 6 </Col><Value> 2 </Value> </Cell>
 <Cell><Row> 6 </Row><Col> 3 </Col><Value> 2 </Value> </Cell>
 <Cell><Row> 6 </Row><Col> 6 </Col><Value> 6 </Value> </Cell>
 <Cell><Row> 6 </Row><Col> 7 </Col><Value> 8 </Value> </Cell>
 <Cell><Row> 6 </Row><Col> 8 </Col><Value> 5 </Value> </Cell>
 <Cell><Row> 7 </Row><Col> 1 </Col><Value> 9 </Value> </Cell>
 <Cell><Row> 7 </Row><Col> 5 </Col><Value> 6 </Value><Stage> 2 </Stage></Cell>
 <Cell><Row> 7 </Row><Col> 9 </Col><Value> 1 </Value> </Cell>
 <Cell><Row> 8 </Row><Col> 4 </Col><Value> 1 </Value><Stage> 2 </Stage></Cell>
 <Cell><Row> 8 </Row><Col> 5 </Col><Value> 2 </Value> </Cell>
 <Cell><Row> 8 </Row><Col> 6 </Col><Value> 3 </Value> </Cell>
 <Cell><Row> 9 </Row><Col> 2 </Col><Value> 4 </Value> </Cell>
 <Cell><Row> 9 </Row><Col> 3 </Col><Value> 1 </Value> </Cell>
 </Sudoku>
</XML>

Reading XML

Reading XML data is a little more work than writting it, but still not dificult. Since you wrote the file, you only need to be able to read what you wrote.
For this example code segment, variable names with initial letters are assumed to have been declared global.
sub FileLoad
 filedialog "Load file...", FilePath$+"*.Sudoku", FullName$
 call GetFileName$
 if FileName$="" then notice "No file chosen!": end
 open FullName$ for input as #File
 FileOpen = True
 call ProcessFile
end sub
 
sub GetFileName$
 for pos = len(FullName$) to 1 step -1
 if mid$(FullName$, pos, 1) = "\" then exit for
 next pos
 FileName$ = mid$(FullName$,pos+1)
 FilePath$ = left$(FullName$,pos)
end sub
 
sub ProcessFile
 do
 call FindTag
 select case Tag$
 case "<XML>"
 case "<Sudoku>":call InitCellArrays :call LoadPuzzle
 case "</XML>" :close #File: FileOpen = False
 end select
 loop until FileOpen = False
end sub
 
sub LoadPuzzle
 do
 call FindTag
 select case Tag$
 case "<Cell>" :call LoadCell
 case "<Diagonal>" :DiagActive = FindContentLogic()
 case "</Diagonal>"
 case "<Possible>" :PossibleShow = FindContentLogic()
 case "</Possible>"
 case "<Reduce>" :ReduceActive = FindContentLogic()
 case "</Reduce>"
 case "<Size>" :call CheckSize
 case "</Size>"
 case "</Sudoku>" :call ShowRefresh: exit sub
 end select
 loop until FileOpen = False
end sub
 
sub LoadCell
 stage = 1
 do
 call FindTag
 select case Tag$
 case "<Row>" :row = FindContentValue()
 case "</Row>"
 case "<Col>" :col = FindContentValue()
 case "</Col>"
 case "<Value>" :val = FindContentValue()
 case "</Value>"
 case "<Stage>" :stage = FindContentValue()
 case "</Stage>"
 case "</Cell>" :CellValue(row,col) = val: CellStage(row,col) = stage
 exit sub
 end select
 loop until FileOpen = False
end sub
 
sub LoadInputBuffer
 if eof(#File) <> 0 then close #File: FileOpen = False: exit sub
 do until (len(InputBuffer$) > 0 ) or (eof(#File) <> 0 ) 'skip blank lines
 line input #File, InputBuffer$
 loop
end sub
 
sub FindTag
 if len(InputBuffer$) = 0 then call LoadInputBuffer
 for i = 1 to len(InputBuffer$)
 if mid$(InputBuffer$, i, 1) = "<" then exit for
 next
 for j=i+1 to len(InputBuffer$)
 if mid$(InputBuffer$, j, 1) = ">" then exit for
 next
 Tag$ = mid$(InputBuffer$, i, j-i+1)
 InputBuffer$ = mid$(InputBuffer$, j+1) 'remove tag
end sub
 
function FindContentString$()
 for i = 1 to len(InputBuffer$)
 if mid$(InputBuffer$, i, 1) = "<" then exit for
 next
 FindContentString$ = trim$(mid$(InputBuffer$, 1, i-1))
 InputBuffer$ = mid$(InputBuffer$, i) 'remove content
end function
 
function FindContentValue()
 for i = 1 to len(InputBuffer$)
 if mid$(InputBuffer$, i, 1) = "<" then exit for
 next
 FindContentValue = val(mid$(InputBuffer$, 1, i-1))
 InputBuffer$ = mid$(InputBuffer$, i) 'remove content
end function
 
function FindContentLogic()
 FindContentLogic = False
 if FindContentString$() = "on" then FindContentLogic = True
end function