Dynamic XML Settings

Word Count: 719

I am working on a project and in this project there are many variables I want to store in an xml file. I could just stick them all in there as key/value pairs but I enjoy some type of structure in my application settings (as well as life). Typically I break my settings into logical groups such as the example settings.xml file below.

settings.xml
<?xml version="1.0" encoding="utf-8"?>
<settings>
<application>
   <name>mysite</name>
   <version>v 0.1 {alpha}</version>
   <url>http://www.mysite.com</url>
   <secure>https://mysite.com</secure>
</application>
<database>
   <dsn>mydsn</dsn>
   <dbtype>mssql</dbtype>
</database>
<email>
   <username>me</username>
   <password>pass</password>
   <server>mail.mysite.com</server>
</email>
</settings>

I am sure this is nothing to everyone but I came across something this problem today and could not find a quick solution. This example above would be very easy to parse int o some type of structure but what if I wanted to add a new section such as cart. I do not want to make changes to my Settings component so everything needs to be dynamic. For every grouping I want to create a separate structure. I whipped up this quick Setting component that will allow you read the XML file above with no regards of what it contains. I know I am re inventing the wheel here but hopefully this will help someone, on to the code.

Settings.cfc
<cfcomponent name="Settings">

   <cfset variables.settings = "">
   <cfset variables.configPath = "">
   
   <cffunction name="init" access="public" output="false" returntype="settings">
      <cfargument name="path" type="string" required="true" hint="Absolute Path to config file.">
      <cfset variables.settings = structNew()>
      <cfset variables.configpath = arguments.path>
      <cfreturn this>
   </cffunction>

   <cffunction name="read" access="public" output="true" returntype="struct"
            hint="I will return a structure containing all application seetings.">

      <cfset var xml = "">
      <cfset var xmldoc = "">
      <cftry>
         <cffile action="read" file="#variables.configPath#" variable="xml"/>
         <cfcatch type="any">
            <cfthrow message="Invalid path to settings file.">
         </cfcatch>
      </cftry>
      <cfset xmldoc = xmlParse(xml)>
      
      <cfloop collection="#xmldoc.settings#" item="parent">
         <!--- for each parent add a new item to our structure --->
         <cfset structInsert(variables.settings,parent,structNew())>
         <cfloop collection="#xmldoc.settings[parent]#" item="child">
            <cfset structInsert(variables.settings[parent],child,xmldoc.settings[parent][child].xmlText)>
         </cfloop>
      </cfloop>

      <cfreturn variables.settings>
   </cffunction>
   
   <cffunction name="set" access="public" output="false" returntype="void"
            hint="I will set a key/pair value ">

      <cfargument name="parent" type="string" required="true">
      <cfargument name="key" type="string" required="true">
   </cffunction>

   <cffunction name="get" access="public" output="false" returntype="void">
      <cfargument name="parent" type="string" required="true">
      <cfargument name="key" type="string" required="true">
   </cffunction>

</cfcomponent>

In a nutshell the read method is where the magic happens and here is what it does.

  1. Read in your xml settings file.
  2. Parse it
  3. Loop the settings node
  4. For each child of settings (grouping such as application & database) add a new key to our settings structure and initialize a new structure as its value
  5. Loop that key and insert a new key/value pair into your new structure that was just created.
You can see that there are some other methods that I am planning on implementing later. So you like what you see and you want to give it a test run? Just follow my test page below and both the settings.cfc and your testpage should be in the same directory. Once you get it working below you can store your settings in the application scope for easy to use settings in your app. Enjoy!

testpage.cfm
<cfset path = "C:\Program Files\Apache Group\Apache2\htdocs\****\config\settings.xml">
   <cfset settingsObj = createObject("component","settings").init(path)>
   <cfset settings = settingsObj.read()>

   <cfdump var="#settings#">

One more quick note about xml settings files. I tend to keep this out of the web root for security reasons. In my new application I am using the following structure.

  • /admin - admin area (admin.mysite.com)
  • /cfc - all components
  • /config - coldspring and settings xml
  • /www - public folder
  • Application.cfc

Comments



Post Your Comment

Leave this field empty







Show Captcha

If you subscribe, any new posts to this thread will be sent to your email address.

Copyright © 2007 Dan Vega | BlogCFC was created by Raymond Camden. This blog is running version 5.8.001.