Archives

Archives / 2003 / April
  • NiftyPortal.com

    NiftyPortal is a web based aggregator with a really nice look.

    NiftyPortal is a free website, designed to be a central point to monitor the content on many websites of your interest. These are displayed in a summarized form. When a link is clicked, NiftyPortal directs you to the original site that published the article.

     Great job Teun!

  • Debugging Windows Services

    As seen on Peter Provost's Geek Noise

    I have to say that debugging Windows Services in VS.NET is certainly much easier than it was in VC++, but I still wish it was easier. If you need to do it, here are a few tricks:

    I had a similar list with one addition, adding a Thread.Sleep(10000); in the OnStart method inside a #if DEBUG so I had time to attach the debugger. I think this is the only way to really debug startup code.

    Recently I've found a better way to deal with services, first I create a console project that has nothing but a little startup and shoutdown code. Then I create a "library" project that has the real meat of the service. Once I have everything to my liking I create a windows service project and installer/deployment project in the same solution as the console and library projects. The console project remains the startup project for the solution, but the installer uses the primary output from the service project.

    The benefits are that debugging during development is trivial, it forces you to seperate the real functionality from the "host", the final transition to a service is trivial.

  • XPath & Namespaces

    I'm sure many out there know this or figured it out eons ago, but it was new to me and took awhile to figure out.

    Say you have a RDF style XML document that looks something like:

    <?xml version="1.0" encoding="iso-8859-1" ?>
    <
    rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns
    ="http://purl.org/rss/1.0/">
    <
    channel rdf:about
    ="http://someplace.com/weblog/">
    <
    title>
    News from Bob</title>
    <
    link>http:// someplace.com/weblog/</link
    >
    <
    description></description
    >
    <
    dc:language>en-us</dc:language
    >
    <
    dc:creator>Bob</dc:creator
    >
    <
    dc:rights>Copyright 2003 Bob</dc:rights
    >
    <
    dc:date>2003-03-19T22:30:34-07:00</dc:date
    >
    <
    admin:generatorAgent rdf:resource="http://www.movabletype.org/?v=2.51"
    />
    <
    admin:errorReportsTo rdf:resource="mailto:tbob@somewhere.com"
    />
    <
    sy:updatePeriod>hourly</sy:updatePeriod
    >
    <
    sy:updateFrequency>1</sy:updateFrequency
    >
    </
    channel
    >
    <
    item rdf:about
    ="http://somewhere/weblog/archives/2003/03/19.shtml#how_i_really_feel_about_cheese">
    <
    title>How I really feel about Cheese</title
    >
    <
    description>&lt;p
    &gt;
    I was asked in a comment why I really don't like cheese...</description>
    </item>
    </rdf:RDF>

    Simplistically I thought the following code would work:

    XmlNode dateNode = rdfXml.SelectSingleNode("/RDF/channel/date");

    But of course it returns Null. So I tried the following:

    XmlNode dateNode = rdfXml.SelectSingleNode("/rdf:RDF/channel/dc:date");

     

    Of course this returned Null as well. So it was time to turn to the help file, which didn’t help much. My next best friend is Google, and Google Groups didn’t let me down. Turns out SelectSingleNode is overloaded and takes a XmlNamespaceManager as the second parameter. I now had this:

     

    nsMgr = new XmlNamespaceManager(rdfXml.NameTable);

    nsMgr.AddNamespace("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");

    nsMgr.AddNamespace("dc", "http://purl.org/dc/elements/1.1/");

     

    XmlNode dateNode = rdfXml.SelectSingleNode("/rdf:RDF/channel/dc:date", nsMgr);

     

    However, I didn’t know what to do with the default namespace. A little more research lead me to the nugget that there is no such thing as a default namespace in XPath, so all I has to do was add the default namespace with the prefix of my choosing.

     

    nsMgr = new XmlNamespaceManager(feedXml.NameTable);

    nsMgr.AddNamespace("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");

    nsMgr.AddNamespace("dc", "http://purl.org/dc/elements/1.1/");

    nsMgr.AddNamespace("rss", "http://purl.org/rss/1.0/");

     

    XmlNode dateNode = rdfXml.SelectSingleNode("/rdf:RDF/rss:channel/dc:date", nsMgr);

     

    Now everything works like it should.

     

    Full example (.Net 2.0):

     

    using System.Xml;

    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                XmlDocument rdfXml = new XmlDocument();
                rdfXml.Load("data.xml");
                XmlNamespaceManager nsMgr = new XmlNamespaceManager(rdfXml.NameTable);
                nsMgr.AddNamespace("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
                nsMgr.AddNamespace("dc", "http://purl.org/dc/elements/1.1/");
                nsMgr.AddNamespace("rss", "http://purl.org/rss/1.0/");

                XmlNode dateNode = rdfXml.SelectSingleNode("/rdf:RDF/rss:channel/dc:date", nsMgr);
            }
        }
    }