How to Import an ExpressionEngine Blog into WordPress

I’m sure by now that most of you have seen my post on how I feel about ExpressionEngine (here), so this post is a natural follower!  Today, we’re going to talk about migrating your content from ExpressionEngine to WordPress.

I spent quite a bit of time working through EE’s poorly detailed instructions on how to export entries before I decided to just get my hands dirty.  Mind you, this post is only applicable to you if you have template access within EE (aka are an Administrator or have been explicitly granted access by one).

It’s so simple, and with a few minor modifications to account for additional modules and tags that had been used I was able to dump several hundred entries from EE and import the whole site into WordPress in just a few minutes (yay!).  The script grabs comments along with entries, no secondary file needed.  Additionally, there is no need to modify PHP allowances for the export file as it makes use of EE’s existing tags.

Step 1: Create the Template Folder

It’s recommended that a new template folder/set/whatever you’d prefer to call it be created within EE by going to “Design->Templates->Template Manager”.  I named my folder “Export”.

Step 2: Create a File for Articles (AND Comments)

Within your newly created folder:

  1. open the index file
  2. Under the “preferences” menu, change the type to “XML”
  3. Paste in the modified code from below

Step 3: Modify WordPress to Allow Imported Media (if necessary)

By default, the WordPress importing function will strip all embedded media tags, which was a bit tricky to figure out.  There are several available plugins that ‘reportedly’ disable this, however I found that none of them to worked.

Fortunately, the fix is fairly straightforward and takes just a minute…

  • Navigate to your “wordpressinstall > wp-includes > kses.php
  • Scroll to line 1309 in kses.php and comment out three lines under “//Post filtering
  • #add_filter(‘content_save_pre’, ‘wp_filter_post_kses’);
  • #add_filter(‘excerpt_save_pre’, ‘wp_filter_post_kses’);
  • #add_filter(‘content_filtered_save_pre’, ‘wp_filter_post_kses’);
  • Save kses.php

Note: upon completion of your import, it is recommended that you undo the previous modifications for security reasons.

The Script

For brevity’s sake, I’m not going to drop the entire script into this post- only the key parts that you’ll need to be able to modify for your own exporting needs.  Before we get to that, a couple of tips:

  • To extract your data, you’ll want to use Firefox or IE (not an IE fan, but it works for this purpose)
  • Don’t forget to remove the “?”‘s from the “<?xml version=”1.0″ encoding=”UTF-8″ ?>” line at the top BEFORE trying to import into WordPress

Start out by replacing the “URLTOYOURWORDPRESS” vars (highlighted below) with the URL to your WordPress Install (note that the second occurrence does not contain a backslash).



As well as on line 49 of the script:

<guid isPermaLink="false">{entry_id}</guid>

Next we move onto the actual entry content.  This part can be a bit tricky if you have several channels with variances in names, as we certainly don’t want to lose any of our precious data!

Also important to note is the lack of line breaks or spaces between the CDATA tags (which unfortunately makes for some serious side scrolling in my case!).  You’ll want to ensure that there are no line breaks or excess spaces between tags, as they may cause the WP importer to skip entries or error.

<content:encoded><![CDATA[{if blog_content}{blog_content}{if:elseif cc_content}{cc_content}{if:else}{article_content}{/if}]]></content:encoded>

<excerpt:encoded><![CDATA[{if blog_short}{blog_short}{if:elseif cc_teaser}{cc_teaser}{if:else}{teaser}{/if}]]></excerpt:encoded>

Post Status Conversion

ExpressionEngine has three primary post values: open, closed, and draft, while WordPress has: publish, pending, private, and draft.  That being the case, it is important for us to convert these values appropriately to retain out post statuses.

<wp:status>{if status == "open"}publish{if:elseif status == "closed"}private{if:elseif status == "draft"}draft{if:else}publish{/if}</wp:status>

The Entire Script May be Downloaded Here:


Step 4: Import into WordPress

Since we’ve now got all of our entries, and (hopefully) already have your WordPress installation ready for some data, log into your WordPress control panel.  Now we’ll go to “Tools->Import”, and select “WordPress Importer”.

  • Don’t forget to remove the “?”‘s from the XML version in your newly created export file prior to import (if you import only 1 entry and can’t figure out why- it’s the “?”‘s)
  • If you are migrating content with embedded media, make sure that you have first followed the instructions in step 3 to comment out import screening in kses.php

You’ll likely have to do a quick install of the plugin to accommodate the import (no separate steps here, just continue along).

Select your source-code-saved file from above (should have “.wxr” extension), hit “import”, and move on with your life in a less stressful fashion.


44 Comments + Add Comment

  • Hi
    Thanks for a great article. I am looking to move my site from Expression Engine to WordPress. I have followed step 1 and step 2 parts 1 and 2. However, in step 3 is the code to copy into the index file the xml file within the ‘Download ExpressionEngine Export to WordPress’?

    If so I have copied this in (to see what I can get out of EE) but no posts appear?

    Am I making a fundamental error at this early stage?


  • Hi – please ignore previous comment – just realised my setup has completely different weblog names and fields!

    Is it possible/advisable to import one weblog at a time (I have about 15)?


    • It is certainly possible to import multiple weblogs simultaneously, however, it depends on how you’d like the data to appear, and where the current data sources are located.

      I would recommend doing one at a time (it’s a pretty quick process fortunately) for the sake of error handling, that way if an error is encountered it’s less likely to affect large amounts of data.

  • An EE site has a field for Keywords to get added to each blog post. Keywords are comma separated. Would you have any suggestions as to how I can import those as Tags?

    Thanks so much for posting this walk through!

  • […] transition was a bit tricky, but thanks to a few helpful articles and a little trial and error I got most of it done. As far as I can tell all the articles came […]

  • I’m getting this error when I try to view the output:

    XML Parsing Error: mismatched tag. Expected: .
    Line Number 52264, Column 3:

    Any ideas how to remedy this?

    • Are you able to isolate the approximate area within the script that is causing the error (line 52264 would be in the output, but related to a specific area of the script generating the output). If so, send it over and I’ll take a look

  • I’m not a coder *and* I’m an old, so please be patient.

    I’m not understanding your if:else statements to grab content. I’m assuming you’re looking for field id’s here, but I don’t understand where to put them.

    On my site, the relevant fields are {image} {summary} {body} {extended} but I don’t understand where they should live in your script.

  • My ExpressionEngine site is set up so that most commenters are subscribed to the comment threads they contribute to. When a new comment is posted, they are sent an email. Is it possible to keep that subscription info when a site is ported to WordPress?

    Thanks in advance for any info!

    • I don’t believe so. Since wordpress uses more comprehensive user data for comment entries that aren’t exported during the EE export process, it’s unlikely that the subscriptions would remain active, however I haven’t confirmed this.

      • Thanks for this info, Bennett.

        My EE site also has number of views for each post, captured via the EE track_views feature. Is there a way to carry these over to WordPress?

        I am a php/mySQL programmer, so if I can find out the mySQL table name/field name in WordPress that captures this info for each post, I could probably code it myself if need be.

        I should just look at the databases and try to find the mySQL info. Or possibly I can ask on the WordPress forum, and they might tell me how the mySQL info is laid out.

        Does this sound like it could be a reasonable approach?

        • WordPress doesn’t track post views by default, but you can easily add it to the wp_postmeta table. Since you’re familiar with php/MySQL, it may be easier to export the current database contents as a csv file, and use php’s fread function or fgetcsv ( to loop through the file and import directly into wordpress.

          The most effective way of importing data directly into mysql for a wordpress site is to enter some example data, then look in the wp_posts and wp_postmeta tables to see exactly how the data is contained, then replicate in a standard mysql command.

          To track specifically post-views in wordpress, this article has a great snippet designed specifically for this purpose, so you’d just need to modify the importer to handle wp_postmeta values, retrieving the ID of the post along the way…

          • Thanks very much for this great info, Bennett!

  • Hi,

    First, thank you for your tutorial 🙂

    I’m not familiarized with EE and I have some doubts about the steps. In the second step, in three point “Paste in the modified code from below”, do you refer to modified script code?

    I’ve changed the script and removed the ? of line xml:

    But I get the follow error when I go to the “View” link in Index template:

    XML Reading error: the element is not found.
    Location: http://localhost:3469/index.php/Export/index/
    Line number: 83, column 7:

    The changes in my script file are only that you’ve explained in this article (copied & pasted). I’m using Firefox to try it and my EE’s version is 1.6.8.

    Thank you very much,

  • Sorry. I can’t write the xml expression here, the error i get is with the rss tag.

    I think that the error appears when I removed the ? from xml in the script.I’ve revised the tags that I’ve changed and all of them are closed. The rss’s tag also have closing tag.

  • Sorry again. I solved the problem. I was removing the “?” from the script code that I had to paste in Expression Engine template “Index”. And I must remove it only from the “.wxr” file generated after.

    Thanks again.

    • Glad you got it sorted out!

  • Hi,
    I am currently part of an academic project which involves Migration of a website from ExpressionEngine to WordPress CMS. The website is slightly more than a simple blog. I managed to pull the data from a specific weblog of EE and imported it to WordPress.
    But I am not able to find the procedure to replicate the user interface of the EE website on WordPress.

    How do I achieve the same user interface that was provided through the templates in EE? How do I map them onto themes in WordPress?

    Is there a systematic way in which I can achieve this migration without loss of data or User interface replication?

    Any help would be helpful to me.
    Thanks in advance

    • I’m not aware of an automated procedure by which themes can be converted, wordpress uses an entirely different template system (see: that relies on a selected group of files that handle information based on request.

      For example, if in your theme directory, you have a file named “home.php”, that file will always be loaded as the site homepage, whereas in EE, you would enter content associated with the homepage into the editor within the CMS and create new pages/templates that way.

  • I noticed the categories portion didn’t work – it put all the stories in “Uncategorized”. How can I tweak it properly to put it in the proper category?


    • I was able to get the categories to work by first deleting the {categories} and {/categories} tag, and then replacing the code in between with the following (remove the spaces before each >):


      Note: The EE site I inherited neglected to use categories and instead relied on channels in lieu of them, so I replaced category_name with channel_title.

      • Whoops, didn’t realize my tags would be stripped out. Hopefully the following will show. Replace ~ with .


        • Alright mostly there lol. Replace ! with > and ~ with <

  • I followed all the steps, but the resulting xml file I get is very small, containing only overall site info:

    Standing Partnership
    Reputation Management


    Any thoughts on what I’m doing wrong? Thanks!

    • Well, it seems I can’t copy and paste code. 🙁 Suffice to say I don’t seem to be getting any posted content out. Thoughts?

    • Be sure the parameters in the loops correspond with your defined categories. Since they’re user defined, they may (and likely) vary from the example code provided

  • I can’t fathom why anyone would go FROM ExpressionEngine to WordPress

    • LOL! All just a matter of preference, they (obviously) accomplish the same thing. I personally prefer wordpress because of the clearer (and easier to find) documentation, and availability of plugins (without cost).

    • As a user of both…there are a hundred good reasons to migrate and others to not. In general for most sites a more simple CMS with a very well adopted UI WP is brilliant. For more complex sites, it is not so brilliant.

      • Both certainly have their advantages, no arguments there! I have been able to quickly and easily adapt wordpress (both via custom plugins and functions.php files) to do nearly anything you can imagine lately, and when it comes down to it, wordpress is one of my most requested client CMS’s- preferred even over custom branded solutions due to it’s large user base.

  • I am using this to export from an old EE site to a wordpress site. I have no experience with EE. I edited the above code to the correct webblog entries and this did the trick. When i imported it to WP it took in everything, title, author, date but the body content just states {article_content}. I’m not sure what I need to change to pick up the article content from the EE site, i though that parameter would be standard? Any help would be appreciated.

    • (Disclaimer: it’s been quite a while since I took a peek at EE): As I recall, there is a custom setting for what the article content fields are named, much like the categories- so I’d take a peek in the location (name unknown offhand) of the field names and adjust accordingly.

      • I was having the exact same problem. The issue was that I was trying to pull the content from the wrong fields. So, looking at the given code:

        <![CDATA[{if blog_content}{blog_content}…

        I went and looked at the blog editor and noticed that the entry field for the content was labeled “body” in my case instead of “content.” So I modified the code to be:

        <![CDATA[{if blog_body}{blog_body}…

        I also had to change the short/teaser field to be “intro.” That worked like a charm. Thanks to Bennett for the great tutorial and then pointing me in the right direction on this particular issue.

        • Just glad I remembered far enough to point you in the right direction! Enjoy!

  • I can’t recall if ExpressionEngine actually offers a native export function. It’s pretty easy to get data out, but generally requires either some database or PHP knowledge. Also because, every channel/weblog can be very different. We have channels that are pretty basic with maybe 5 fields, then those with close to 50 fields. So they won’t all go into WordPress easily.

    Your script should probably work, for standard ‘blog-like’ set-ups, but that person mentioning the 15 different weblogs, which probably have 15 different field groups, potentially related data, and more, that’s going to need a lot more work on both ends, unless all 15 weblogs/channels are formatted exactly the same. Which I’ve seen done, but isn’t usual.

    While the import process MAY BE the same, I highly recommend AJW Export to get data out of EE (free add-on). There’s other add-ons, notably Export-It ($65), but AJW Export works super well, if you can identify the fields you want. Additionally, I just use Sequel Pro (a MySQL GUI) to do query exports to SQL, CSV, or XML.

    If your data is simple (title, date, author, summary, post) and you want WordPress, then the script should work without too many hiccups. But otherwise, both modifications to EE data and or WordPress structure will be required.

    • Good question, at the time of writing, it did not. And you are correct, a normal exporter script would be a pretty useless way to go for larger websites.

      The best approach for any site that is big enough to have those concerns would be to parse the EE data into WP or other format using standalone PHP and MySQL scripts that circumvent the CMS’s entirely.

  • Got this working, thank you. I have a couple of questions though.

    Is it possible for to create custom post type entries with the import, rather than posts?

    And can custom fields in EE be mapped to relevant custom fields in WordPress?

    • I’ve worked out the Custom Post Type issue (change post to the name of the custom post type.

  • When you did this transfer, what did you do to manage the transfered permalink structure?

    • Going into the worpdress settings > permalinks and updating and importing the batch file then handles the rest of the process

  • I did but there are some data not import like category and meta_key value please give me some best solution for that


  • Hi. Thanks for all the help with this. I’m almost there. Unfortunately, whether I take the question marks out of the XML bit at the top or leave them in, I’m only able to import 1 entry. I was mysteriously able to get 50 at one point, but never again. And as far as I can tell, I didn’t do anything differently. Any tips?

    • Unfortunately, the last time I used EE was several years ago now, so I’m not 100% sure.

  • Thanks this works fine!

Leave a comment