Apostrophe has a ready-to-eat import recipe for Wordpress blog posts. If you are importing from Wordpress, you can use a task designed for that purpose to get it done easily. We will be adding similar tasks for other CMSes if our client work demands it. For more information, check out the apostropheImportersPlugin.
Since there are so many content management systems we cannot possibly write importers for every one. Instead, we have written a generic set of import tasks that expect a documented XML format. As an expert in your existing CMS, you can take care of creating an exporter that takes whatever format your CMS can export and transforms it to our XML format. Then use our import tasks to complete the job. We suggest that you create a Symfony task to convert the native export format of your CMS to Apostrophe XML and release it as a plugin so others can contribute and improve it for everyone's benefit.
Apostrophe includes an import task that is capable of importing a site from a valid xml document. The task can be run using
The task expects xml files to be located in sfRoot/data/a
A sample document is shown below.
<?xml version="1.0" encoding="UTF-8" ?> <site> <Page slug="/" title="Home" template="home" > <Area name="body"> <Slot type="aRichText"> <value>This is my body text</value> </Slot> <Slot type="aVideo"> <embed> <![CDATA[<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/Abt8aAB-Dr0&rel=0&color1=0xb1b1b1&color2=0xcfcfcf&hl=en&feature=player_embedded&fs=1"></param><param name="allowFullScreen" value="true"></param><embed src="http://www.youtube.com/v/Abt8aAB-Dr0&rel=0&color1=0xb1b1b1&color2=0xcfcfcf&hl=en&feature=player_embedded&fs=1" type="application/x-shockwave-flash" allowfullscreen="true" width="425" height="344"></embed></object>]]> </embed> </Slot> </Area> <Area name="header_image"> <Slot type="aImage"> <MediaItem src="header.jpg" alt="Header"/> </Slot> </Area> <Page slug="/about" title="About" file-id="2" template="default" /> <Page slug="/people" title="People" file-id="3" template="default" > <Page slug="/people/students" title="Students" file-id="4" template="default" /> <Page slug="/people/teachers" title="Teachers" file-id="5" template="default" /> </Page> </Page> </site>
Here is an example of an external file used to provide the slot content for a specific page:
<?xml version="1.0" encoding="UTF-8"?> <Page> <Area name="body"> <Slot type="foreignHtml"> <value><![CDATA[ <b>This is bold text</b><img src="food-fast.gif">More regular text. <a href="http://www.punkave.com"><img src="http://farm5.static.flickr.com/4090/5073384290_63ea8ab19d_b.jpg"></a> And another <b><i>box</i></b> ]]> </value> </Slot> </Area> </Page>
Page elements have several attributes. Currently both the slug and title are required. Template is optional and will default to default. The file-id is used to specify an external file where information about areas and slots can be found. This is useful for particularly large sites where loading one gigantic XML file is not feasible. A file-id of 2 will result in the importer looking for the file data/pages/2.xml. If file-id is not specified the importer will look for areas in the main xml file.
Currently several slot types are supported by the importer: aText, aRichText, aImage, aSlideshow, aButton (needs MediaItem?, title and URL sub-elements), and foreignHtml. The foreignHtml content type is used to import rich text with embedded images and videos. The import process will create multiple rich text, video and single-image slots, or button slots if the images are links.
The src attribute for a slot of type aImage can either be a http:// url pointing to another site or a relative url. If relative the importer will expect the file to be located at data/a/images and will bring it into the media repository of the site.
The embed element for a slot of type aVideo can be any embed code using an object or iframe element. YouTube videos are understood natively, importing their thumbnails into the media repository automatically. The same applies to Vimeo, Viddler, and SlideShare if you have configured API keys for your project. Any embed codes not understood natively are still accepted, but you won't see thumbnails in the media repository unless you manually add them later.
When you use <site>...</site> as the enclosing element, the entire site is replaced, and any existing content is dropped.
You can also add pages to an existing site, if the top level element of your XML file is <subset> rather than <site>. If the top level element is <site> the existing content is discarded just like before, so there is no backwards compatibility impact.
Also, if you specify a "parent" attribute for a <page> element, the page with that slug is considered to be the parent. This allows you take advantage of <subset> to create new subpages of an existing site. It can also be used at any time when you prefer to avoid creating nested <page> elements in the XML file. However the XML elements for parent pages must still appear before their children in the file.
IMPORTANT: this is true as of apostrophePlugin's 1.5 svn branch, commit 4981. If you are using a tarball release or an older svn revision, all imports will overwrite the existing site, regardless of what the top level element is called.
An importer for blog and events also exists in apostrophe. The importer can be run with the command
The command accepts options --posts and --events that are the paths to an xml file of posts and events. An example of the xml used to import post is shown below.
<posts> <post published_at="2008-08-01 18:10:51" slug="apostrophe-is-awesome"> <title>Apostrophe is Awesome</title> <categories> <category>Apostrophe</category> <category>Blog</category> </categories> <Page> <Area name="blog-body"> <Slot type="foreignHtml"> <value>This is my body</value> </Slot> </Area> </Page> </post> </posts>
If you have installed apostropheImportersPlugin, each post can have an optional disqus_thread_identifier attribute to associate it with an existing Disqus thread that began life in a different system. If you have not installed that plugin that attribute is not supported because it requires a schema addition.
When importing events, enclose many event elements in an events element. Otherwise the format is the similar. You would also include the start_date and end_date attributes in each event element, and also enclose a location element within the event containing any reasonable text description of the location where the event takes place (hint: this is typically passed to Google Maps). The outermost element would be called events, and the individual events are represented by event elements. If you do not have a location for an event you may leave that element empty.