XML parser

Coding and general discussion relating to user created compiler modules

Moderators: David Barker, Jerry Messina

Post Reply
SHughes_Fusion
Posts: 219
Joined: Wed Sep 11, 2013 1:27 pm
Location: Chesterfield

XML parser

Post by SHughes_Fusion » Thu Feb 27, 2014 1:48 pm

I'm working on a project which will communicate with an Android app via Bluetooth. We are looking at the options of using an XML-based system for data as this opens things up nicely for future expansion.

Does anyone know of an XML parser for Swordfish or can point me in the resources which will help me develop one?

User avatar
David Barker
Swordfish Developer
Posts: 1194
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Re: XML parser

Post by David Barker » Thu Feb 27, 2014 4:27 pm

I don't know of any xml parsers personally - however, I'm assuming you are just looking to pull simple <tag>..</tag> fields? Something like that would be easy to implement, assuming the data is reasonably well formed.

User avatar
RangerBob
Posts: 152
Joined: Thu May 31, 2007 8:52 am
Location: Beds, UK

Re: XML parser

Post by RangerBob » Mon Mar 03, 2014 1:40 pm

I created a "QuasiXML" parser for use in my Reverse Geocache.

It was quick, dirty and nasty but it works a treat for reading and writing parameters off an SD card. At least it may be a useful jumping off point.

Code: Select all

{
*****************************************************************************
*  Name    : FileWriter.BAS                                                 *
*  Author  : Rangerbob                                                      *
*  Notice  : Copyright (c) 2011 							                *
*          : All Rights Reserved                                            *
*  Date    : 02/09/2011                                                     *
*  Version : 1.0                                                            *
*  Notes   : SD card must  *
*          : be mounted first before calling functions.                     *
*		   : Reads and writes a simplied XML structure and debug
*****************************************************************************
}
Module File

Include "String.bas"
Include "Convert.bas"
Include "SDFileSystem.bas"

Dim XMLString As String(200) 
Dim Header As String(15) 

Const Tab = $09	' Tab



{
********************************************************************************
* Name    : XMLWriteParam	                                                   *
* Purpose : Writes the given string to the parameter in the declared file.     *
* Note	  : "XML" is used here as a loose term!								   *
********************************************************************************
}
Public Function XMLWriteParam(pFileName As String, pParam As String, pPayload As String) As Byte
	
	// Note:
	// Due to limitations of the PIC/SD system, the easiest way for this to work is to
	// create a new file to work on, stream across the old file line by line until reaching paramter to be adjusted. 
	// If not found, append to end. Then rename old file to backup and name new file to current.
	// Also prevents corruption of the original file if the proceedure is interrupted for any reason.

	Dim index As Byte
	Dim i As Byte
    Dim TestByte As Byte
    Dim InString As Boolean
    Dim FoundTarget As Boolean
    Dim Source As TSDName

	result = null
	FoundTarget = False

   	index = SD.OpenFile(0,pFileName)
	// Found Source file ok, no problem, otherwise will return error
	If index = errOK Then
	    
		// Create the new file to modify
		Repeat 
			index = SD.NewFile(1,"modify.bak")
			If index = errExists Then			// if there is already a file, it blocks - can happen due to crash/interruption
				SD.DeleteFile("modify.bak")
			EndIf
		Until index = errOK
		
		If index = errOK Then
			Repeat
				// Put line from file into memory
				index = 0
				Repeat 
		        	TestByte = SD.ReadByte(0) 	
		        	If index < SizeOf(XMLString) Then
		        		XMLString(index) = TestByte
		        		Inc(index)
	        		EndIf
				Until SD.EOF(0) Or TestByte = 10
				XMLString(index) = null
				
				// Search line for header, extract into Header string
				index = 0
				i = 0				
                InString = false
				Repeat
					If XMLString(index) = "<" Then           		// Find start of header string
						InString = true
					EndIf
					If InString = true Then
						If i < SizeOf(Header) Then					// Stop buffer overflow
							Header(i) = XMLString(index)
            				Inc(i)
						EndIf
					EndIf
					Inc(index)
				Until XMLString(index -1)= null Or XMLString(index -1) = ">"
				Header(i) = null
				Header = Uppercase(Header)

				// Check if target header
				If Compare(Header,Uppercase(pParam)) = 0 Then
					//It is our target: lazy, memory efficient way, recreate entire line rather than modify existing
					SD.Write(1, pParam)
					SD.Write(1, pPayload)
					Insert("/", pParam, 1)
					SD.Write(1, pParam)
					SD.Write(1,13)
					SD.Write(1,10)
					FoundTarget = true
				Else
					// Write out line as is	
					index = 0
					While XMLString(index) <> null 
						SD.Write(1, XMLString(index))
						Inc(index)
					Wend
				EndIf
										
			Until SD.EOF(0)

			// Parameter does not exist in file, append to end 
			If foundtarget = false Then
				SD.Write(1,13)
				SD.Write(1,10)
				SD.Write(1,pParam)          // Write param name
				SD.Write(1,pPayload)        // write payload
				
				Insert("/", pParam, 1) 		// insert param closing slash
				SD.Write(1,pParam)          // write param close
				SD.Write(1,13)
				SD.Write(1,10)
			EndIf
			SD.CloseFile(0)
        	SD.CloseFile(1)

			// Rename and replace
			// Using TSD structure to work around bug in rename
			If result = errOK Then
				SD.DeleteFile(pFileName)
				Source.Name = "MODIFY"
				Source.extension = "BAK"
				result = SD.Rename(Source, pFileName, sdFile) 
			EndIf
			
		EndIf
		
	SD.CloseFile(0)
	EndIf	

End Function
{
********************************************************************************
* Name    : XMLReadParam                                                       *
* Purpose : Writes the given string to the parameter in the declared file.     *
********************************************************************************
}
Public Function XMLReadParam(pFileNumber As ShortInt, pFileName As String, pString As String) As String
    Dim XMLString As String(15)
    Dim Payload As String(20)
    Dim index As Byte 
    Dim InString As Boolean
    Dim FoundTarget As Boolean

	result = null
	FoundTarget = False
   	
   	// Open the file
 	index = SD.OpenFile(pFileNumber,pFileName)
	
	// Found file ok, no problem, otherwise will return error
	If index = errOK Then
	    Repeat
			// Find XML Header
			InString = false
			index = 0
	
			Repeat 
				XMLString(index) = SD.ReadByte(pFileNumber)
				If XMLString(index) = "<" Then           		// Find start of param string header
					InString = true
				EndIf
				If InString = true Then
					If index < SizeOf(XMLString) Then			// Stop buffer overflow
						Inc(index)
					Else
						XMLString(index - 1) = ">"
					EndIf
				EndIf
			Until SD.EOF(pFileNumber) Or XMLString(index - 1) = ">"
			
			// Pull out data
			If SD.EOF(pFileNumber) = false Then
				XMLString(index) = NULL		// terminate string
				XMLString = Uppercase(XMLString)
				
				// Is it our target?
				pString = Uppercase(pString)
				
				// Pull out payload
				If Compare(XMLString,pString) = 0 Then
					index = 0 
			  		Repeat
	         	    	Payload(index) = SD.ReadByte(pFileNumber)
	         	    	Inc(index)
	         	    Until SD.EOF(pFileNumber) Or Payload(index - 1) = "<"
	         	    	
	         	    Payload(index - 1) = null
	         	    result = Payload
				    FoundTarget = true	
  	    		EndIf
    		
			EndIf
									
		Until SD.EOF(pFileNumber) Or FoundTarget = true
		SD.CloseFile(pFileNumber)
	EndIf
	
End Function

{
********************************************************************************
* Name    : PrintDebug                                                         *
* Purpose : Writes a debug string to file "Debug.log"						   *
* Note	  : Cannot call during a file 1 read / write operation!                *
********************************************************************************
} 
Public Function PrintDebug(pFileNumber As ShortInt, pDebugString As String) As Byte
	// Open File for Writing
	result = SD.AppendFile(pFileNumber,"Debug.log")
	
	If result = errNotFound Then
		result = SD.NewFile(pFileNumber,"Debug.log")		
		SD.Write(pFileNumber, "> No debug log found, starting new file", 13, 10)
 	EndIf
 	
	If result = errOK Then
		SD.Write(pFileNumber, "> ", pDebugString, 13, 10)
		SD.CloseFile(pFileNumber)
	EndIf
	
End Function

{
********************************************************************************
* Name    : CreateSettings                                                     *
* Purpose : Creates a default settings.xml file 							   *
* Note	  :                 												   *
********************************************************************************
} 
Public Function CreateSettings(pFileNumber As ShortInt,pFileName As String) As Byte
	
	result = SD.NewFile(pFileNumber,pFileName)		

	If result = errOK Then													// Write out header
		SD.Write(pFileNumber, "// Reverse Geocache Settings.xml file", 13, 10)
		SD.Write(pFileNumber, "// Edit me to make changes! Do not touch comments or headings (<heading>)", 13, 10)
		SD.Write(pFileNumber, 13, 10)
		SD.Write(pFileNumber, "// This is the name the box will use to greet the player", 13, 10)
		SD.Write(pFileNumber, "<Greetname>Player</Greetname>", 13, 10)
		SD.Write(pFileNumber, 13, 10)
		SD.Write(pFileNumber, "// Number of Attempts to open the box remaining to the player", 13, 10)
		SD.Write(pFileNumber, "<Attempts>50</Attempts>", 13, 10)
		SD.Write(pFileNumber, 13, 10)
		SD.Write(pFileNumber, "// Targets must be entered in order, last (Target0) to first (TargetN)", 13, 10)
		SD.Write(pFileNumber, "// Co-ordinates should be entered in Decimal degrees (dd.dddd and ddd.dddd)", 13, 10)
		SD.Write(pFileNumber, "<Target0>01.1234,567.8910</Target>", 13, 10)
		SD.Write(pFileNumber, "<Target1>01.1234,567.8910</Target>", 13, 10)
		SD.Write(pFileNumber, "<Target2>01.1234,567.8910</Target>", 13, 10)
		SD.Write(pFileNumber, 13, 10)
		SD.Write(pFileNumber, "// Current Target to find", 13, 10)
		SD.Write(pFileNumber, "<Current>2</Current>", 13, 10)
		SD.Write(pFileNumber, 13, 10)
		SD.Write(pFileNumber, "// Precision needed to call a target solved", 13, 10)
		SD.Write(pFileNumber, "// Default 500. Do not set to less than 500!", 13, 10)
		SD.Write(pFileNumber, "<Precision>500</Precision>", 13, 10)
		SD.Write(pFileNumber, 13, 10)
		SD.Write(pFileNumber, "// Set this parameter to true on first running to box to ensure", 13, 10)
		SD.Write(pFileNumber, "// first line from taunts file is used. Usually an introduction for user.", 13, 10)
		SD.Write(pFileNumber, "// Will automatically be set to false once the first message has been displayed.", 13, 10)
		SD.Write(pFileNumber, "<Firstrun>true</Firstrun>", 13, 10)
		SD.Write(pFileNumber, 13, 10)
		SD.Write(pFileNumber, "// User Password. Set this to something memorable so you can", 13, 10)
		SD.Write(pFileNumber, "// Override the box via USB if necessary!", 13, 10)
		SD.Write(pFileNumber, "<Password>TEST</Password>", 13, 10)
		SD.Write(pFileNumber, 13, 10)
		SD.Write(pFileNumber, "// Unlock the Box? Set to true if the box is solved", 13, 10)
		SD.Write(pFileNumber, "// Delete me or set to false to lock box and start puzzle", 13, 10)
		SD.Write(pFileNumber, "<Unlock>true</Unlock>", 13, 10)
		
		SD.CloseFile(pFileNumber)		
		result = errOK	
 	EndIf
	
End Function


User avatar
David Barker
Swordfish Developer
Posts: 1194
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Re: XML parser

Post by David Barker » Mon Mar 03, 2014 5:52 pm

Very useful! Thanks for posting...

Post Reply