02 April, 2006

Migrating from dasBlog to SubText

As I wrote in my previous post I changed my blogging software. In order to migrate all posts and comments from my previous blog i wrote a little program to do it. I did not read a lot of documentation on how to do this, strictly a trail and error approach.

I started out by looking for what web services the different blog systems exposed by doing a file search for *.asmx and just pointing my browser to then to have a look at the API’s.

For dasBlog the one that cauth my eye was /SyndicationService.asmx and for SubText it was the /Services/SimpleBlogService.asmx. So, I cranked up Visual Studio .Net 2005 and added those two web references.

WebRererences.Jpeg

After being at it a while I realized I did not know how to create the comments using the SimpleBlogService in SubText. So I got the SubText source code from sourceforge.net and opened up the solution in Visual Studio and added a method to the web service. Not at all backward compatible, but that don’t matter cause I only need it for the migration. So in SimpleBlogService.asmx.cs I added the following method.

[WebMethod(MessageName="AddCommentToEntry",   Description="Add comment to post",EnableSession=false)]
public void AddComment(int entryid, string username,    string password, DateTime commentdate, string title, string body,
    string author, string email, string sourceIP, string sourceUrl)
{
    CheckUser(username,password);

    Entry entry = new Entry(PostType.Comment);
    entry.Author = author;
    entry.Title = title;
    entry.TitleUrl = sourceUrl;
    entry.Body = body;
    entry.ParentID = entryid;
    entry.SourceName = sourceIP;
    entry.Email = email;
    entry.DateCreated = commentdate;
    entry.DateUpdated = commentdate;

    Entries.InsertComment(entry);
}

Deployed that to my webserver and updated the web reference in the migration project. Now I got crunching on the migtraion. I choosed to use the Atom feed from dasBlog and in order to get all posts I went in to dasBlog admin and changed the syndication settings so that all posts would be in the feed.

SyndicationSettings.Png

Get to the code you’re saying and that i will. I created a console application for this. Starting out the main method with getting instances of the web services.

SubText.SBSSimpleBlogService sbsSvc =    new dasBlogSubTextMigratio.SubText.SBSSimpleBlogService();
dasBlog.SyndicationService dasBlogSvc =    new dasBlogSubTextMigratio.dasBlog.SyndicationService();

Next, get the feed.

class Program
{
    static void Main(string[] args)
    {
        //Get instances of the webservices
        SubText.SBSSimpleBlogService sbsSvc =          new dasBlogSubTextMigratio.SubText.SBSSimpleBlogService();
        dasBlog.SyndicationService dasBlogSvc =          new dasBlogSubTextMigratio.dasBlog.SyndicationService();

        //Get the feed
        dasBlog.AtomRoot atomElement = dasBlogSvc.GetAtom();

        foreach (dasBlog.AtomEntry e in atomElement.entry)
        {

            Console.WriteLine("Migrating post: \""                + e.title + "\" ...");

            string title = HttpUtility.HtmlEncode( e.title );
            DateTime date = e.published;
            string body = e.content.Any[0].InnerXml;
            string[] categories = new string[0]; ;


            if (e.category != null)
            {
                categories = new string[e.category.Length];

                for (int i = 0; i < e.category.Length; i++)
                {
                    categories[i] = e.category[i].label;
                }
            }

            //Retrive guid for entry, I'll use it to extract the comments
            string guid = e.id.Substring(e.id.IndexOf("guid,") + 5, 36);

            Console.WriteLine("   Creating post in SubText");
            int id = sbsSvc.InsertCategoryPost("username", "password", date,                title, body, categories);

            XmlDocument commentsDoc = new XmlDocument();
            commentsDoc.Load("http://MyDasBlogSite/Content/AllComments.xml");

            XmlNamespaceManager nsManager =                new XmlNamespaceManager(commentsDoc.NameTable);
            nsManager.AddNamespace("def",                "urn:newtelligence-com:dasblog:runtime:data");

            XmlNodeList commentsForPost =                commentsDoc.SelectNodes(                  "/def:ArrayOfComment/def:Comment[def:TargetEntryId = '"                   + guid.ToUpper() + "']", nsManager);

            if (commentsForPost.Count > 0)
            {
                Console.WriteLine("   Adding comment(s)");
            }

            foreach (XmlNode node in commentsForPost)
            {
                DateTime dt = Convert.ToDateTime(GetValue(node, "def:Created",                   nsManager));
                string commentTitle = GetValue(node, "def:TargetTitle", nsManager);
                string commentBody = GetValue(node, "def:Content", nsManager);
                string email = GetValue(node, "def:AuthorEmail", nsManager);
                string author = GetValue(node, "def:Author", nsManager);
                string url = GetValue(node, "def:AuthorHomepage", nsManager);
                string ip = GetValue(node, "def:AuthorIPAddress", nsManager);

                sbsSvc.AddComment(id, "username", "password", dt,                   commentTitle, commentBody, author, email, ip, url);
            }
        }

        Console.WriteLine("Done!");
        return;

    }

    private static string GetValue(XmlNode node, string subnode,       XmlNamespaceManager nsManager)
    {
        if (node.SelectSingleNode(subnode, nsManager) != null)
        {
            return node.SelectSingleNode(subnode, nsManager).InnerText;
        }
        else
        {
            return "";
        }

    }
}

As you can see I did not (fast enough) find a way to get the comments from the web service so I went for the AllComments.xml file in dasblog.

There is probably a lot of better ways to do this, but this I how I did it and it seems to work so far.


Tags: ,