Monday, March 30, 2009
Monday, March 30, 2009 6:45:22 AM (GMT Daylight Time, UTC+01:00) (C# | Utilities)

Alex Gorbatchev has done a great job with version 2.0 of his excellent JavaScript SyntaxHighlighter. And I’ve just updated my code snippet plugin for Windows Live Writer – with SyntaxHighlighter 2.0 support, as well as a new desktop application – useful for pasting code snippets into other apps.. like stackoverflow.com (CTRL-A to select all – and then >> to indent four spaces before pasting into stackoverflow).

The updated plugin is at http://www.codeplex.com/precode

precodeplugin



| Comments [0] | | #  
Sunday, March 22, 2009
Sunday, March 22, 2009 2:04:35 AM (GMT Standard Time, UTC+00:00) (C#)

I decided to create an aggregate sitemap.xml for the root of my domain. There are sitemap handlers in the blog, otherblog and photo subdirectories already – but I wanted a single sitemap.xml in the root that I could submit to Google.

I started with some pretty hacky attempts... fumbling my way around Linq to Xml. Also came unstuck with namespace normalization – since the sitemap handler in dasBlog is using the older 0.84 version namespace from sitemap.org.  So what I thought would take 20 minutes – ended up taking a bit longer, although the results were worth it since the same approach could be used for aggregating Atom or RSS feeds.

(Note – big thanks to Martin Honnen over at http://social.msdn.microsoft.com/Forums/en-US/categories/ for helping out with some of the Linq to Xml).

The ChangeNamespace helper method does not convert attributes although that could be added as well.

The safe method for loading urls along with the use of an iterator block (yield return) makes the GetElements helper method pretty efficient I think. What’s more, since this returns an IEnumerable<XElement> – additional Linq query expressions could be used here – like sorting or grouping; particularly useful if you were aggregating an Atom feed and wanted to sort by date.

static void Main(string[] args)
{
    XDocument feed = MergeSiteMaps(new List<string>() { "http://www.58bits.com/blog/googleSitemap.ashx", "http://www.58bits.com/otherblog/googleSiteMap.ashx",  "http://www.58bits.com/photos/sitemap.xml"});

    XNamespace sm = "http://www.sitemaps.org/schemas/sitemap/0.9";

    foreach (XElement location in feed.Root.Elements(sm + "url").Elements(sm + "loc")) 
    {
        Console.WriteLine((string)location); 
    } 
}

public static XDocument MergeSiteMaps(IEnumerable<string> urls)
{
    XNamespace sm = "http://www.sitemaps.org/schemas/sitemap/0.9";
    XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
    XNamespace xsd = "http://www.w3.org/2001/XMLSchema";
    string schemaLocation = "http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd";

    //Our container sitemap document
    return new XDocument(
        new XDeclaration("1.0", "utf-8", "yes"),
        new XElement(sm + "urlset",
            new XAttribute(XNamespace.Xmlns + "xsi", xsi),
            new XAttribute(XNamespace.Xmlns + "xsd", xsd),
            new XAttribute(xsi + "schemaLocation", schemaLocation),

            new XElement(sm + "url",
                new XElement(sm + "loc", "http://www.58bits.com/"),
                new XElement(sm + "lastmod", DateTime.Now.ToString("yyyy-MM-dd")),
                new XElement(sm + "changefreq", "monthly"),
                new XElement(sm + "priority", "1.0")),

            new XElement(sm + "url",
               new XElement(sm + "loc", "http://www.58bits.com/default.aspx"),
               new XElement(sm + "lastmod", DateTime.Now.ToString("yyyy-MM-dd")),
               new XElement(sm + "changefreq", "monthly"),
               new XElement(sm + "priority", "1.0")),

            GetElements(sm, urls, "url"))
        );
}

private static IEnumerable<XElement> GetElements(XNamespace ns, IEnumerable<string> urls, string elementLocalName)
{
    XElement source;

    foreach (string url in urls)
    {
        try
        {
            source = XElement.Load(url);
        }
        catch (Exception ex)
        {
            //TODO: Log the Url that failed
            string message = ex.Message;
            continue;
        }

        XNamespace defaultNamespace = source.GetDefaultNamespace();
        bool differentNamespace = (ns != defaultNamespace);
        foreach (XElement element in source.Elements(defaultNamespace + elementLocalName))
        {
            if (differentNamespace)
                ChangeNamespace(ns, element);
            yield return element;
        }
    }
}

private static void ChangeNamespace(XNamespace ns, XElement entry)
{
    foreach (XElement e in entry.DescendantsAndSelf())
    {
        if (e.Name.Namespace != XNamespace.None)
        {
            e.Name = ns.GetName(e.Name.LocalName);
        }
    }
}


| Comments [0] | | #  
Friday, March 20, 2009
Friday, March 20, 2009 7:38:45 AM (GMT Standard Time, UTC+00:00) (Hardware)

31XZH33C58L._SL500_AA280_ This is probably more ‘tweet’ worthy than blog worthy – but what the heck. You see that little printer to the left? That’s an HP 930c DeskJet inkjet printer – and I’ve been using it now for eight years. :-)

You can buy one used on Amazon (and no doubt from eBay) for about 10.00 USD. I love the blurb for this printer.

“ This remarkably fast little printer enables you to produce letters, memos, and reports, plus photo-quality prints. Handling up to 100 pages of input and 50 pages of output, the HP DeskJet 930C color printer is a practical companion for your desktop or laptop computer.”

Talk about a lesson in positive branding. I’ve been recommending HP printers to friends and co-workers for at least as long. I suppose having good quality HP printers in the office over the years has helped as well. On the other side – after a traumatic experience with Epson printers years ago, I’ve never forgiven Epson (and always thought their software was a bit wonky). Totally illogical and non-analytic I know – but that’s what branding is about I guess.



| Comments [0] | | #  

search

categories

on this page

ads

archive

Total Posts: 95
This Year: 1
This Month: 0
This Week: 0
Comments: 80