Load XML into List Collection

I needed the ability to load a XML file into a selectable list. The problem was really two fold, I had a collection of DAT files (like a single column CSV file) that I needed to first convert to XML (I had another existing collection of XML files, yea I know "consistency, consistency, consistency") as well.ScreenShot014

So I can up with a simple couple of utility methods to convert a single column CSV file (herein referred to as a DAT file) to an XML and then another method to take a XML file and return a list collection. This allows me to first convert the DAT and then load the collection into a ComboBox. 

At first I was worried about performance of reading from the XML files, but then I realized we are talking about a collection of strings around the order of 100. This loads using the XMLTextReader class in about 2/10 of a second. I think that is performance I can live with.

This method takes a plurized DAT file (much like the RoR MVC style) and creates a simple XML (that includes the root attributes that the partner XML read method expects). An example would be using a DAT file name ‘colors.dat’ it would make a XML file with ‘colors’ root node and then a collection of ‘color’ nodes with a single element named ‘name’ that contains the value of each DAT file.

Example DAT file (just for clarity):

red
yellow
orange
pink
blue

Method to convert the DAT to a XML file:

        public void DATToXML(string DATFile, string XMLFile, bool SortList, bool IncludeEmpty, string IncludeAllCaption)
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.IndentChars = ("    ");
            settings.Encoding = System.Text.Encoding.UTF8;
            
 
            FileInfo datFileInfo = new FileInfo(DATFile);
            string rootNode = datFileInfo.Name.Replace(datFileInfo.Extension.ToString(), "");
            string childNode = rootNode.Substring(0, rootNode.Length - 1);
 
            using (StreamReader sr = new StreamReader(DATFile))
            {
                string line = string.Empty;
 
                using (XmlWriter writer = XmlWriter.Create(XMLFile, settings))
                {
                        writer.WriteStartElement(rootNode);
                        writer.WriteAttributeString("displaymember", "name");
                        writer.WriteAttributeString("sortlist", SortList.ToString());
                        writer.WriteAttributeString("includeempty", IncludeEmpty.ToString());
                        writer.WriteAttributeString("includeall", IncludeAllCaption);
 
                        while ((line = sr.ReadLine()) != null)
                        {
                            if (!string.IsNullOrEmpty(line))
                            {
                                writer.WriteStartElement(childNode);
                                writer.WriteElementString("name", line);
                                writer.WriteEndElement();
                            }
                        }
                        writer.WriteEndElement();
                        writer.Flush();
                }
            }
        }

 

Now the method to take the newly created XML file and load it into a List<string> collection:

        public List<string> XMLToList(string XMLFile)
        {
            List<string> list = new List<string>();
 
            XmlTextReader xml = new XmlTextReader(XMLFile);
 
            string displayMember = string.Empty;
            bool sortList = false;
            string includeall = string.Empty;
            bool includeempty = false;
 
            while (xml.Read())
            {
                switch (xml.NodeType)
                {
                    case XmlNodeType.Element:
                        while (xml.MoveToNextAttribute())
                        {
                            if (xml.Name == "displaymember")
                                displayMember = xml.Value.ToString();
 
                            if (xml.Name == "sortlist")
                                sortList = bool.Parse(xml.Value.ToString());
 
                            if (xml.Name == "includeall")
                                includeall = xml.Value.ToString();
 
                            if (xml.Name == "includeempty")
                                includeempty = bool.Parse(xml.Value.ToString());
 
                        }
                        while (xml.Read())
                        {
                            if (xml.Name.ToString() == displayMember)
                            {
                                // read next node, the textnode to get value
                                xml.Read();
 
                                if (xml.NodeType != XmlNodeType.Whitespace)
                                    list.Add(xml.Value.ToString());
                            }
                        }
                        break;
                }
            }
 
 
            // If includeall is set then put it at the first of the list
            if (!string.IsNullOrEmpty(includeall))
                list.Insert(0, includeall);
 
            // If sort is set then sort the list before returning it from the method
            if (sortList)
                list.Sort(delegate(string s1, string s2) { return s1.CompareTo(s2); });
 
            // if includeempty is true then put a empty string at the first of the list
            if(includeempty)
                list.Insert(0,string.Empty);
 
            return list;
 
        }

Bit of info on the options:

  • The "displayMember" is the value of the element name to use for the string value (defaults to "name").
  • The "sortList" option is a bool that indicates if the list should be sorted before it is returned.
  • The "includeAll" option is a string value that will be put at the top of the list. Like "- All" or "* Select All *".
  • The "includeEmpty" option is a bool that (if set "true") sets the option to include empty DAT file entries in the string collection.

So put together like this:

        private void Form1_Load(object sender, EventArgs e)
        {
            string DATFile = @"C:\work\zipcodes.csv";
            string XMLFile = @"C:\work\zipcodes.xml";
            
            DATToXML(DATFile, XMLFile, true, false, string.Empty);
 
            Stopwatch sw = new Stopwatch();
 
            sw.Start();
 
            List<string> zipcodes = XMLToList(XMLFile);
 
            sw.Stop();
 
            TimeSpan ts = sw.Elapsed;
 
            this.labelXMLLoadTime.Text = "XML Load Time: " + 
                                         String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds);
 
            sw.Start();
 
            this.comboBox1.DataSource = zipcodes;
 
            sw.Stop();
 
            ts = sw.Elapsed;
 
            this.labelComboboxLoadTime.Text = "Combobox Load Time: " + 
            String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds);
 
            this.labelCount.Text = "Number Of Items Loaded: " + this.comboBox1.Items.Count.ToString("g");
            
        }

Awesome stuff. Super simple and very fast. I loaded up the entire US Zipcode collection in .223 seconds and then put that into a ComboBox in 2.9 seconds. I realize most people are not going to have 40,000 entries in a selectable ComboBox, my point is that it is zooming fast.

Enjoy!

Linux Mint, AMD 3850 and 1680×1050 Working!

About a month ago I picked up the ATI 3850 video card thinking it would be significant performance upgrade from my Nvidia 7950GT – it was. However, I was seriously dismayed to see the state of video drivers from ATI – in particular in comparison to the Nvidia driver. My LinuxMint Desktop glory!

Anyhow, so I started the fight. The fight to get my ATI 3850 card to drive my Viewsonic VG2230wm at 1680×1050@60. I tried several of the binary ATI drivers but finally got the 8.01 (the kernel version is 8.45.4, the driver is labeled 8.01 and the ATI website says it’s version 8.1 !? -man is that confusing) driver to work. Simple to install; Download the binary, then from a command line just execute the file as root.

Here is my relevant xorg.conf sections:

Section "Module"
        Load            "GLcore"
        Load            "glx"
        Load            "dbe"
        Load            "v4l"
EndSection
 
Section "Device"
        Identifier      "ATI3850"
        Busid           "PCI:1:0:0"
        Driver          "fglrx"
EndSection 
 
Section "Monitor"
        Identifier   "Monitor"
        VendorName   "ViewSonic"
        ModelName    "VG2230wm"
        DisplaySize  470 300
        HorizSync    24.0 - 84.0
        VertRefresh  50.0 - 85.0
        ModeLine     "1680x1050@60" 154.20 1680 1712 2296 2328 1050 1071 1081 1103 +hsync +vsync
        Option       "dpms"
EndSection 

Enjoy!

Google Chart C# API

I was playing around with the excellent Google Chart API and I wanted to illustrate just how crazy simple it is to ScreenShot013implement this, even on a WinForm app (see nifty screen capture ->).

First grab the Google C# API Wrapper source code. Then take and unzip that and open that project in Visual Studio and compile the DLL. Then add a new Windows Application Project to the solution, drag a new PictureBox on the form, and then paste this into Form1.cs:

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.ComponentModel;
   4:  using System.Data;
   5:  using System.Drawing;
   6:  using System.Text;
   7:  using System.Windows.Forms;
   8:  using GoogleChartSharp;
   9:   
  10:  namespace Tester
  11:  {
  12:      public partial class Form1 : Form
  13:      {
  14:          public Form1()
  15:          {
  16:              InitializeComponent();
  17:          }
  18:   
  19:          private void Form1_Load(object sender, EventArgs e)
  20:          {
  21:              // Set the image to be directly loaded from the FQDN of the chart
  22:              this.pictureBox1.ImageLocation = SimpleGrid();            
  23:          }
  24:   
  25:          public static string SimpleGrid()
  26:          {
  27:              // Instantiate the chart object
  28:              LineChart lineChart = new LineChart(250, 150);
  29:   
  30:              // Values to be charted
  31:              int[] line1 = new int[] { 5, 10, 50, 34, 10, 25 };
  32:   
  33:              // Set chart title using default color and font
  34:              lineChart.SetTitle("Step Size Test");
  35:              
  36:              // This is a x and y axis chart. Create two new axis objects
  37:              lineChart.AddAxis(new ChartAxis(ChartAxisType.Left));
  38:              lineChart.AddAxis(new ChartAxis(ChartAxisType.Bottom));
  39:              
  40:              // Load the chart with the dataset (line int array)
  41:              lineChart.SetData(line1);
  42:   
  43:              // Add a grid to the chart (dotted grid lines)
  44:              lineChart.SetGrid(20, 50);
  45:   
  46:              // retuns the FQDN of the chart
  47:              return lineChart.GetUrl();
  48:          }
  49:   
  50:      }
  51:  }
  
Super simple. Good stuff indeed.
 
Enjoy!

Dell Latitude c840 + Ubuntu + Restricted Nvidia == blankScreen;

I picked up a nifty Dell Latitude c840 notebook on Ebay for around $185, nice. So I get it and decide to setup Linux Mint (based on Ubuntu 7.10). After the install completes I then have the bright idea to setup the restricted drivers to get the 3D acceleration working (so I can play with Compiz later) and find that I am presented with a lovely black screen after reboot.

yay! black screen of nothing! yay!

So I troll around on the net and discover it’s some sort of problem with the Nvidia NV17 (GeForce4 440 Go) chip and the way the EDID‘s work on the Samsung 1600×1200 LCD, or somesuch silliness.

Anyhow to make it work( read = "I would like to actually see the screen!") reboot and select the "recovery mode" kernel and then do this:

nano -w /etc/modprobe.d/nvidia-kernel-nkc

# add this to the end of the file
options nvidia NVreg_SoftEDIDs=0 NVreg_Mobile=0

Save file, reboot and click on my Google ads 😉

Enjoy!

C# .NET logging with NLog

After messing around with my own logging engine (boo!) I decided to play around with NLog, it looked much simpler to use and configure than log4net (not that log4net looked all that complicated, just that NLog seemed cleaner to me).

So grab the NLog setup package from SourceForge and install it. So that’s it. Yes, that simple really, the installer includes a series of templates that will be used later to create an empty configuration file.

I like using the Datestamp of YYYYMMDD_HHMM so 1:30 PM on April 1st, 1980 would be 19800401_1330. This is the configuration I used in the Nlog.config file to write the timestamp’ed log data to a text file (add a new file to your project and pick the ‘Empty NLog Configuration File” from the My templates section), this setup will also create a Datestamp on the log file:

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

  <targets>
    <target name="file" xsi:type="File" fileName="${basedir}/${date:format=yyyyMMhh}.log.txt"
            layout="${date:format=yyyyMMhh_HHmm}|${level}|${stacktrace}|${message}"/>
  </targets>

    <rules> 
      <logger name="*" minlevel="Trace" writeTo="file"/>
    </rules>
</nlog>

Here is a example of using the logging:

using System;
using System.Collections.Generic;
using System.Text;
using NLog;

namespace NlogTester
{
    class Program
    {
        private static Logger _logger = LogManager.GetCurrentClassLogger();
        
        static void Main(string[] args)
        {
            _logger.Trace("This is a Trace message");
            _logger.Debug("This is a Debug message");
            _logger.Info("This is an Info message");
            _logger.Warn("This is a Warn message");
            _logger.Error("This is an Error message");
            _logger.Fatal("This is a Fatal error message"); 

            Console.ReadKey();

        }
    }
}
This creates an excellent log file that looks like this:
20080109_2136|Trace|AppDomain.ExecuteAssembly => AppDomain._nExecuteAssembly => Program.Main|This is a Trace message
20080109_2136|Debug|AppDomain.ExecuteAssembly => AppDomain._nExecuteAssembly => Program.Main|This is a Debug message
20080109_2136|Info|AppDomain.ExecuteAssembly => AppDomain._nExecuteAssembly => Program.Main|This is an Info message
20080109_2136|Warn|AppDomain.ExecuteAssembly => AppDomain._nExecuteAssembly => Program.Main|This is a Warn message
20080109_2136|Error|AppDomain.ExecuteAssembly => AppDomain._nExecuteAssembly => Program.Main|This is an Error message
20080109_2136|Fatal|AppDomain.ExecuteAssembly => AppDomain._nExecuteAssembly => Program.Main|This is a Fatal error message

Good stuff indeed.

Enjoy!

Ubuntu 7.10 (Gutsy) Server on VirtualBox

I wanted to setup an Ubuntu 7.10 (Gutsy) server to be a sandbox on my Vista notebook using VirtualBox. Seems there is a known problem with running the Ubuntu server kernel (defaults to PAE and the kernel reports 'CPU Too Old' on boot and bails, seem VirtualBox does not yet support PAE extensions) via VirtualBox, however this can be made to work by switching out to the generic kernel and using that. Sure it's not ideal for a production level server, but it works great in a sandbox mode.

Step-by-step 1, 2, 3 sort-of directions:

  • Download the Ubuntu 7.10 Server ISO (BitTorrent FTW!)
  • Download and install VirtualBox
  • ubuntu_server_virtualbox_setup Setup a new VM instance
    • Recommended settings: OS Type of Linux 2.6,  512MB RAM, 20GB Dynamic Drive, 8MB Video, USB + EHCI, Network NAT (see my post about port forwarding if you need to interact with this VM via your LAN machines).
  • Set the new VM instance CD/DVD-ROM to mount the ISO
  • Install with basically all defaults, let the CD eject and then the OS will reboot the VM
  • Boot again from your ISO mounted CD to get the initial install screen
  • b_ubuntu_server_virtual_boxThis time select the 'Rescue a broken system' option from the menu
  • Go back though like you are setting the system backup (keyboard, locale, hostname, etc.) this is just used to boot up the installer
  • c_ubuntu_server_virtual_box At the Rescue Mode screen be sure and choose your root (/) partition, in my case it was /dev/sda1
  • d_ubuntu_server_virtual_box At the '[!!] Enter rescue mode' screen pick the 'Execute a shell in /dev/sda1' option
  • From here you will be in a shell from your chrooted installed server, execute these commands (press 'Y' to install any needed additional packages  and press 'Y' to confirm):
    • apt-get update
    • apt-get install linux-image-generic
    • apt-get remove linux-server
  • ubuntu_server_editing_grub_menu Now you need to change Grub to use the linux-generic as the default item to boot from. This is done by setting the 'default x' value to be the number of the 'title' block in the menu.lst file. This should be the third block (two linux-server entries and then two more linux-generic entries):
    • nano -w /boot/grub/menu.lst
    • <find the 'default 0' and change to be the number of your linux-genric entry, should be 2 (remember computers count from 0, duh!)>
    • <with Nano its CTRL+X to save the file press 'Y' to confirm the overwrite>
    • exit
  • The 'exit' command should exit you out of the shell and then reboot the VM instance.
  • I would recommend doing both a Snapshot from within VirtualBox (this gives you a reference point in time position you can 'clean' your sandbox back to. Do this before you start monkeying around with your server, else you will have to start again to get it back in a pristine condition.
  • server_up_and_running Enjoy!

VirtualBox + Windows 2003 Server + LAN != working;

So I wanted to setup a Windows 2003 Development virtual machine instance using VirtualBox on my notebook and then have the ability to get to that server from the network. Well it seems that VirtualBox is not real intuitive about handling this setup. Seems that the VirtualBox Guest NAT only does that; NAT’s the outbound traffic from the VM via the Host network adapter and does not allow any inbound packets (not stateful NAT requests) to get back to the VM’s NIC.

So after much toiling around on the VirtualBox forums I found the answer, you can setup a port forward on the host machine to send the particular port traffic to the VM NIC. This is, for some odd reason I must say, is not done via the VirtualBox GUI but via the commandline tool ‘C:\Program Files\innotek VirtualBox\VBoxManage.exe’.

So let’s say you have a VM instance named ‘Win2003Dev’ and you want to send Subversion (port 3690) traffic to/from that VM you would perform this:

  • Close VirtualBox (this requires lock write to the VirtualBox.XML file), if running
  • Open up a command line console (if using Vista you should use  Start -> cmd -> CTRL+SHIFT+ENTER)
  • Enter these three lines (one at a time, doh!):
    VBoxManage setextradata "Win2003Dev" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/svn/Protocol" TCP
    VBoxManage setextradata "Win2003Dev" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/svn/GuestPort" 3690
    VBoxManage setextradata "Win2003Dev" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/svn/HostPort" 3690	
  • Note: The ‘svn’ I used in the lines is just something I picked, it seems you can use ‘hot-potato’ if you like. I thought something logical would make most sense.

Enjoy!

Blog entry via Windows Live Writer

So this post is coming straight from Windows Live Writer.

So far its an impressive piece of software, wonder how well this is going to work. I installed a couple of Plug-ins; Insert Polaroid, Insert Code, Paste from Visual Studio and Text Template.

Lets test some stuff out;

  • A Slashdot Link (should pop new window).
  • A small Icon Image (should be transparent PNG) -> agt_action_success
  • How about some HTML Code:
         1:  <html>
         2:  <body>
         3:  This is some HTML Code
         4:  </body>
         5:  </html>

       
  • And now a quote:
    • "Software is like sex: it’s better when it’s free" – Linux Torvalds

Very, very cool.

Favorite Wallpaper (via Lightbox)

I was wondering how this Lightbox extension for BlogEngine works.

Here is my current favorite wallpaper, (clicky pops 1280×1024).

A New Years Sunset  

 

<a rel="lightbox" href="path_to_image_to_pop" title="popup_title"><img src="path_to_thumbnail"></a>

It’s a blog eat blog world.

A blog? Why you ask?

Well its not meant to be a point of social discussion, or my witty rant's on my conspiracy theories. No, not so much. The intent of this feature filled experience is to basically document my experiences in technology, yes I use the word 'experiences' very loosely. My adventures, dis-adventures, wins, losses and throw-the-damn-thing-out-the-window experiences.

Bottomline, this is meant as a place where I can document things I experiment with hopefully to help me remember what I did to get it working in the first place.

Ramblings of an often confused opinionated yak shaver.