Migrating from Expression Engine to WordPress

Recently, at King, we moved our blog over from an old Expression Engine build (v2) over to a new WordPress install. I figured it would be helpful to share my experiences since a lot of the other articles I read were pretty outdated.

First, I’d like to thank Domenico Bettinelli for his article and Travis Smith for his article giving me the initial information for my workflow.

The Workflow

Broken down as simply as possible: we’re going to create a template inside Expression Engine that will convert all of our blog posts into data that WordPress can interpret, save that as an .xml file, and import that file into WordPress.

Step 1

Inside Expression Engine, create a blank template called export and make sure it’s in the default template group. Add this code to the template:


<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"     >
<channel>

<link>{site_url}</link>
<description>SITE_DESCRIPTION_HERE</description>
<pubDate>{current_time format="{DATE_RSS}"}</pubDate>
<generator>http://wordpress.org/?v=2.8.6</generator>
<language>en</language>
<wp:wxr_version>1.0</wp:wxr_version>
<wp:base_site_url>{homepage}</wp:base_site_url>
<wp:base_blog_url>{site_url}</wp:base_blog_url>
{exp:weblog:categories style="linear" weblog="default_site"}
<wp:category>
<wp:category_nicename>{category_url_title}</wp:category_nicename>
<wp:category_parent></wp:category_parent>
<wp:cat_name><![CDATA[{category_name}]]></wp:cat_name>
</wp:category>
{/exp:weblog:categories}
{exp:weblog:entries weblog="default_site" orderby="date" sort="desc" limit="200" offset="0" rdf="off"}
<item>

<link>YOUR_BLOG_URL_WITH_TRAILING_SLASH/?p={entry_id}</link>
<pubDate>{entry_date format="{DATE_RSS}"}</pubDate>
<dc:creator><![CDATA[{author}]]></dc:creator>
{categories}

<category domain="category" nicename="{category_url_title}"><![CDATA[{category_name}]]></category>
{/categories}
<guid isPermaLink="false">YOUR_BLOG_URL_WITH_TRAILING_SLASH/?p={entry_id}</guid>
<description></description>
<content:encoded><![CDATA[{body}]]></content:encoded>
<excerpt:encoded><![CDATA[{summary}]]></excerpt:encoded>
<wp:post_id>{entry_id}</wp:post_id>
<wp:post_date>{entry_date format="%Y-%m-%d %H:%i:%s"}</wp:post_date>
<wp:post_date_gmt>{gmt_entry_date format="%Y-%m-%d %H:%i:%s"}</wp:post_date_gmt>
<wp:comment_status>open</wp:comment_status>
<wp:ping_status>open</wp:ping_status>
<wp:post_name>{url_title}</wp:post_name>
<wp:status>publish</wp:status>
<wp:post_parent>0</wp:post_parent>
<wp:menu_order>0</wp:menu_order>
<wp:post_type>post</wp:post_type>
<wp:post_password></wp:post_password>
<wp:postmeta>
<wp:meta_key>extended</wp:meta_key>
<wp:meta_value><![CDATA[{extended}]]></wp:meta_value>
</wp:postmeta>
{embed="comments.xml" the_entry_id="{entry_id}"}
</item>
{/exp:weblog:entries}
</channel>
</rss>

Under Template Preferences, change type to “XML” and “Yes” for Allow PHP.

Enabling PHP in a template will enable anyone with editing rights for that template to become a de-facto Super Admin since they can execute any PHP they want in that template, including PHP that can reveal information about your system, PHP that can delete data from your database, etc. Exercise extreme caution before enabling this option if you permit others to edit your templates.

If you are also exporting comments, create another template called comments, with the same preferences, and with this code:

<!--?php global $IN; $IN--->QSTR = '{embed:the_entry_id}'; ?>
<?php global $IN; $IN->QSTR = '{embed:the_entry_id}'; ?>
{exp:comment:entries weblog="default_site" sort="asc"}
<wp:comment>
<wp:comment_id>{comment_id}</wp:comment_id>
<wp:comment_author><![CDATA[{name}]]></wp:comment_author>
<wp:comment_author_email>{url_or_email}</wp:comment_author_email>
<wp:comment_author_url>{url}</wp:comment_author_url>
<wp:comment_author_IP>{ip_address}</wp:comment_author_IP>
<wp:comment_date>{comment_date format="%Y-%m-%d %h:%i:%s"}</wp:comment_date>
<wp:comment_date_gmt>{gmt_comment_date format="%Y-%m-%d %h:%i:%s"}</wp:comment_date_gmt>
<wp:comment_content><![CDATA[{comment}]]></wp:comment_content>
<wp:comment_approved>1</wp:comment_approved>
<wp:comment_type></wp:comment_type>
<wp:comment_parent>0</wp:comment_parent>
<wp:comment_user_id>0</wp:comment_user_id>
</wp:comment>
{/exp:comment:entries}

Step 2

Now we have to go through the code and replace the placeholders and general Expression Engine tags with your custom tags.

  • Where it says SITE_DESCRIPTION_HERE put the tagline for your site
  • Where you see YOUR_BLOG_URL_WITH_TRAILING_SLASH/, put the URL to where your WordPress install will go. For example, it might http://www.site.com/blog/
  • Where it says channel=”DEFAULT_SITE”, replace DEFAULT_SITE with the actual channel for your blog.
  • Take a look at the EE tags and change any to match your custom tags. In my instance, I only needed to change the actual post body and excerpt which are:
<content:encoded><![CDATA[{body}]]></content:encoded>
<excerpt:encoded><![CDATA[{summary}]]></excerpt:encoded>

Step 3

Now that we have our template to generate the data, let’s make it work. Go to the url of that new template file (http://www.site.com/export) and view the page’s source. Save that .xml file as full_export.xml. Open up that .xml file in a text editor such as Coda or Sublime. You should be able to see all the posts and data now. If you don’t have a lot of posts skip to Step 5 but if you do, like I did, we want to just test out the import on one post. Since each tag is an individual entry, delete all but one and save it as single.xml.

When you import your posts you have to assign them to an associated author. Create these authors as “Users” inside WordPress and/or a general user to be used. If this isn’t done all the posts will be authored to your admin account.

Step 4

Inside your WordPress dashboard, go to Tools, Import, WordPress. If you’ve never imported anything, you’re most likely going to have to install the WordPress Importer plugin. Depending on if you’re just testing out a one post import or your full one from Step 4, choose the associated .xml file. Head over to your Posts tab and double check if all of the information made it over. If you were just doing a one post test and everything looks good, delete that post (also from the trash) and import the full one.

Step 5

Once everything is good to go, go back into Expression Engine and delete the template(s) you created.

Conclusion

Hopefully everything went smoothly for you and you have all your old posts on a brand spankin’ new WordPress site. If you know of a better way or feel like I need to elaborate more, let me know below. Good luck exporting!

Posted By

Posted on

Have a project
to discuss?

Let's see if we can help.

Start a Conversation
dribbblefacebookinstagramtwittervimeoyoutube