Frustrated with XML

skywola

Member
Joined
Jan 5, 2012
Messages
12
Location
Mesa, AZ, USA
Programming Experience
10+
I am working on an application that works with foreign languages and also uses colors. The original program persisted all of its data to a text file, and worked very well, but used unmanaged code, that is, API functions. When I did research on how to persisted application settings with managed code, I found that XML files are used in managed code. XML files do not work good for what I am doing though, because the do not save characters like "[", "]", and will not even allow you to save a tag with a space character in it! I suspect that it might be possible to save the data in an XML correctly if I use binary, but I am not sure on that, and I do not prefer it. I would prefer to keep the format in text form if possible though, because in that form, you can open up the file in notepad and see exactly how things are stored, and even edit it in notepad if you want. If I use text format though, I need a way to store and retreive attributes like color and utf-8 style text. So my question is: Are there any alternatives to XML that use text files under managed code and allow you to store and retrieve attributes?
 
Last edited:
Don't know how you're doing things, but generally I haven't had any problems with .Net and Xml, also not with those chars you mention.
 
The biggest problem I am having at the moment is, I have a XML file like this:
HTML:
<?xml version="1.0" encoding="utf-8"?>
<root>
    <Searches>
          <search0>BlankBlackoutList</search0>
    </Searches>
    <BlankList>
         <Color0>Color [Black]</Color0>
         <Color1>Color [Black]</Color1>
         <Color2>Color [Black]</Color2>
    </BlankList>
  </root>

I know how to get to the root:
root = XElement.Load(path) 

but everything I try to read <Color0>, which should give me back "Color [Black]" fails and throws an error.
 
Last edited by a moderator:
root...<Color0>.Value will return the string value "Color [Black]". Btw, that value is produced by Color.ToString and will not give you a suitable string for converting back to a Color value. For example use ToArgb/FromArgb or the ColorTranslator class, or if you're only using named colors the Name property along with FromName method.
 
Yea, the ToArgb/FromArgb thing is something I dealt with when I wrote the API functions, I had to write a procedure to handle non-custom colors . . . I remember it being lots of fun :fatigue:

Is there are reason for the "..." between root and <Color0>? Is it like a directory level signification?
 
Last edited:
Yea, the ToArgb/FromArgb thing is something I dealt with when I wrote the API functions, I had to write a procedure to handle non-custom colors . . . I remember it being lots of fun
Those are shared methods of the Color structure.
Is there are reason for the "..." between root and <Color0>? Is it like a directory level signification?
...<> is the Xml descendants property.
 
I am posting this for anyone that runs into a similar issue. This is the whole procedure I created. Keep in mind that this was custom-created to replace the
WIN API function that read a text file, so it may not look like normal XML usage, I may not be a perfect coder, but I am an effective coder, I
get the job done. Note that this allows for a default value to be assigned, something you see often with the WIN API functions.
In the first line of code in the function, Tachufind is the application directory.

Public Function readElement(ByVal path As String, ByVal parentTag As String, ByVal childTag As String, Optional ByVal defaultValue As String = "")
Dim programDataDirectory As String = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) & "\Tachufind"
Dim attrValue As String = ""
Try
checkForDirAndFile(path, programDataDirectory) ' check for the directory and file, create it if it does not exist.
Dim root = XElement.Load(path)
' if no file given, use defaultValue defalts
If parentTag = "" Or root.Element(parentTag) Is Nothing Then
attrValue = defaultValue
Return attrValue
Exit Function
End If
Dim tag As XElement = root.Element(parentTag)
' attrValue = tag.Element(attrName).Value
If tag.Element(childTag) Is Nothing Then
attrValue = defaultValue
Return attrValue
Exit Function
End If
Dim attr As XElement = tag.Element(childTag)
attrValue = tag.Element(childTag).Value

Catch ex As Exception
reportError("Error in " & moduleName & ", readElement : " & Err.Description)
End Try
Return attrValue
End Function



Public Function checkForDirAndFile(ByVal path As String, ByVal programDataDirectory As String)
If Not System.IO.Directory.Exists(programDataDirectory) Then
Directory.CreateDirectory(programDataDirectory)
End If
'Create Element fileName node
If Not File.Exists(path) Then
Dim writer As New XmlTextWriter(path, System.Text.Encoding.UTF8)
writer.WriteStartDocument(True)
writer.Formatting = Formatting.Indented
writer.Indentation = 3
writer.WriteStartElement("root")
writer.WriteEndElement()
writer.WriteEndDocument()
writer.Close()
End If
Return 0
End Function


I also used a replace procedure when I saved any tagNames to make sure that the user could not
enter any characters that would be illegal for the tags: (this is not acomprehensive list, just a few as an example)
pNameOfSearchTable = pNameOfSearchTable.Replace("&", "-")
pNameOfSearchTable = pNameOfSearchTable.Replace("<", "")
pNameOfSearchTable = pNameOfSearchTable.Replace(">", "")


reportError is a module level function I created to display an error, at the beginning of each
module or .vb file I just create a variable like this:

Dim moduleName As String = "ApplicationSettings"

then in the catch statement, I place this code, "readElement" is the name of the function:

reportError("Error in " & moduleName & ", readElement : " & Err.Description)

Function reportError(ByVal text As String)
FrmError.rtbErr.Text = text
FrmError.ShowDialog()
Return 0
End Function


I suppose making it a sub might be a good idea, no need for a return.
 
Last edited:
Back
Top