Remy Denton

Senior Developer

Imagine there was a way to enter content on one Drupal website and have it automatically appear on another.  Suppose you could just as easily send it to five, or for that matter a hundred other sites if you wanted, and on each one it could be edited or deleted just like you'd entered it manually...

Okay, maybe it's not that romantic after all.  But assuming this site-to-site transfer of content is something you're after, you can stop imagining and start building using the instructions below.

Real world use case: A client of ours has three Drupal sites, each managed by a different administrator who adds news stories to his or her own site.  In order to make the most of their content, they want to be able to share some stories between sites, but each administrator needs to have control over whether any particular story is published on his or her site.

Alternate use cases: In addition to sharing almost any kind of content between two or more sites on an ongoing basis, you could also use the setup below for a one-time content migration.  If the thought of eliminating hours of dull copying and pasting doesn’t get your blood pumping, stop reading here and consult your therapist.

What you’ll need:

Part I: Set up an outgoing feed using Views on Site A

1.     Enable the Views and Views Data Export modules on Site A.
2.     Create a new view to aggregate the content that you want to send to Site B.   In our case, this was just a view that displayed published nodes of the ‘News Story’ content type.
3.     Create a new display, but instead of choosing ‘Block’ or ‘Page’, choose ‘Data Export’.
4.     Add a path for your new display, just like you would for a page display.
5.     Change the format of this display to ‘XML file’.  Note that you won’t actually be creating a file unless you check the box next to ‘Provide as file’ in the settings.  DON’T check this box—you want to create an XML feed, not a downloadable file.
6.     Add all the fields from this content type that you want to pass on to site Site B.  If it’s just the title and body fields, great, but you can also add more complex ones like the author or date.   In any case, make sure that you keep the labels on each field (you’ll need these when reading the feed to figure out which field is which).
7.     (optional) If you want to get really fancy and send an image, you’ll have to add the URL of the image since the image itself won’t show up in the XML output.  One way to do this is to first add a relationship to the attached image (‘File Usage: File’), and then use this relationship to add the URL as a field (‘File:Path’).  If you can’t get that working, you could also use the Image URL Formatter module.
8.     Save the view and go to the path that you set up in step 4.   If you see some XML gobbledygook that looks like it might have the fields you just added, you’re in good shape.

Part II: Set up a Feed importer and Feed Processor Node on Site B

For this part, follow the Xpath module documentation to create an XPath feed importer and feed processor.   The instructions are reasonably good up until about step 7 or 8, at which point they become practically unintelligible.  Ah, the joys of open source documentation.  I’ll try to fill in here as best I can:

Once you have your importer set up, you need to create a new feed processor node (as described in roughly step 7 in the link above).  In their example, this is just a new node of the ‘xml job feed’ content type. In our example below, the content type is just 'feed'.

In the title field for this new node, put whatever you like.  In the URL field, put the path of the feed that you created on Site A (see Part I, Step 4).  

Creating a new feed processor node on Site B.  Note the XPath Parser Settings field is collapsed.

So far, so good.  Next, click “XPath Parser settings” (right below the URL field) to expand it. This is where you determine which fields from the XML feed correspond, or “map”, to which fields on the imported nodes.   You need to use XPath syntax, which you can read more about here.  Better yet, since your XML was created by the Views Data Export module and should look almost identical to ours, just take a look at the example below and tweak as necessary:

The expanded XPath Parser Settings field on Site B.  

The outgoing XML feed as shown in the Views preview on Site A.

The trickiest part about this is the 'Context' field, which essentially tells the feed processor where to look in the XML for the other fields-- in our case, inside the <nodes> tag, and then inside each <node> tag.  The other three fields determine which XML data should be used for each field on the new nodes.  For example, the data inside the <image-url> tag in the XML will be mapped to the 'field_image' field when a new imported node is created.

One final interesting note: while we initially assumed we'd have to map the image URL field to a plain text field, it turns out that's not the case: if you map it to a file upload field instead, it works just fine and actually imports the image for you.  If only the rest of the setup were this easy!

Part III: Import!

1.     Click the ‘import’ tab on the feed processor node you created in Part II.
2.     Sit back and enjoy the fruits of your labor.   Once you’ve got it working, you can turn on “Periodic Import” on your feed importer and set this up to happen on its own in the future.

* It’s possible to avoid the XPath parser module altogether by using CSV (comma separate value) format instead.  The downside is that you’ll lose all your HTML formatting in transit because that data export module’s CSV setting strips it out—if this is unacceptable, you’ll have to stick with the longer (but more rewarding) route described above.

Read more entries by Remy Denton.


I just wanna ask if i can follow these steps in drupal 6 , so how can I map image field comes from site A to site B, in default use the image generated in the description as html with the buddy, But i wanna get it standalone in image field.

I haven't actually tested this, but there are Drupal 6 versions of all the modules you need so I don't see why it shouldn't work.

As for getting the image fields working, the key is to get the URL of the image into your XML feed on Site A (as I did in the example above). Then, in your parser settings on site B, just map this URL to an image upload field. It's possible this part may not work in Drupal 6 for some reason-- you could always test it by setting up a basic Drupal 7 site with a feed importer to make sure you're doing it right. Let us know if you're able to figure it out!

Remy, Thank you so much for writing a such a great step by step for syndication. It seems to be working pretty well all of the fields for my content type are syndicating quite nicely except for Images and Field Collections. I can't seem to get those working. My XML doesn't display those fields as XML but rather as HTML, I think. I can change this using relationships? How is that possible.



Glad to hear the post was helpful to you. Looks like your problem is indeed that you've got HTML in your feed that could use some further formatting. Here's a little more detail on the images:

1. As I describe in the post, add a relationship to your view. I believe the one you'll want to use is 'File Usage:File'.
2. Next, add the field called 'file:path'. This probably won't show up until you've added the relationship. Make sure to select the 'File Usage:File' relationship from the dropdown menu when you're adding this field.

When you've got it right, images in your feed should look something like this:


If you're new to views relationships, this video may be of some help: . The whole concept takes a little getting used to, but it's worth spending some time on.

As for field collections, that may be a bit trickier (and perhaps not possible, depending on what kind of support feeds has support for field collections). You might try adding the field collection as a relationship too, then adding the individual fields from the collection to your feed and tweaking your feeds importer to parse them properly.

Good luck!

Further to your statement "when you've got it right" ... the option you need to set (and which I missed first time around) is this:

Display download path instead of file storage URI

Otherwise you get a URL that starts with public:// instead of the full absolute URL to the image.

Thanks for the excellent tutorial. I have one small problem on the export side. My image field can have multiple values. In my view this duplicates the whole row. Any suggestions on how to get around this?

To answer my own question, a module at each end did the trick. At the source end, the image_url_formatter module gives a formatter option in views to output the image url, with the standard options for multiple field values. So I set this up to output multiple urls separated with a comma.
At the receiving end, the feeds_tamper module allows you to add various plugins to alter each mapped value before it is imported. Adding an 'explode' plugin lets you explode comma separated values into an array. This is also helpful for taxonomy terms, or any field with multiple values.

I've been looking for a tutorial like this for several months. I've given up, thinking it wasn't possible without lots of custom coding, and then stumbled upon this article. EXACTLY what I was looking for. Thank you!!

I have been looking around to setup content sync b/w my development and live site, though i found couple of documentations but no luck. Yours is a clear, descriptive and perfect blog. It made me clear of mapping the fields, importing images and mechanism of Feeds module.

It all worked like a charm when i have placed '/nodes/node' instead of 'nodes/node' in 'XPATH PARSER SETTINGS'. Images got imported and downloaded in the files directory.

Thanks again.

Syncing content from a development site is a use case I hadn't thought of, but certainly an interesting one! Glad to hear it was helpful.

Tahnk you very much. I have placed '/nodes/node' instead of 'nodes/node' in 'XPATH PARSER SETTINGS', like Sashi kiran.

After eventually getting this working there are several tips I'd like to add from my experiences. I was getting a lot of "There are no new nodes" messages during testing which took ages to track down. This is what I had to do to get it working:

1. Don't rely on the views preview - the feed is treated as an anonymous user when fetched, so although the preview looked good, the actual feed being delivered was empty.

2. Previewing the feed url in a browser was also misleading - when logged in the feed appears to work, as soon as I logged out it became empty.

3. My view had a "view published content" access control set, which was preventing fields being rendered to the anonymous feed. I also had access control set on my nodes - I had to open these to anonymous users.

4. On the import side the feed can be cached, which means that even after fixing all of the above I was still seeing no data. Clearing the drupal cache didn't fix this. I found that in the Basic Settings of the feed importer, checking "import on submission" and setting "Periodic Import" to "as fast as possible" fixed this. I imagine that once testing is complete I will change "as fast as possible" to something more reasonable.

5. The mapping and debugging settings can be changed in two places - in the Feed Importer XPath XML parser settings or in the importer node. Which one of these is used depends on a checkbox "Allow source configuration override" in the parser settings.

Fantastic tutorial! Works perfectly. Saved a lot of time messing around with settings and other modules.

One thing I wanted to mention though that was giving me a headache:
On import I kept getting duplicate nodes. So if I left the site for any length of time I would have multiple nodes with the same title and content. I did some digging and found there is a Target Configuration tied to the Title (and I'm assuming other fields) that needs to be "Unique." Once that was check Duplicate nodes were not being imported, only new ones with a new title.

Hope this helps someone.

I am currently working on a project which is a D6 to D7 migration. But it's a *slow* migration! There is a beta period for the D7 site during which we need to be able to resynchronize content (nodes, comments, users) from the old to new sites.

The exact logic which defines what should be imported and how it is mapped from D6 to D7 is complex, and there is a lot of custom code involved. Code running on the two sites communicates via CodeServer -

Would this handles the creation of new users, for example.
If a new user signs up to Site A and would this create them on Site B, remembering that Drupal gives a user a UID and everything to do with that user is linked via this in the database?

Refresh Type the characters you see in this picture. Type the characters you see in the picture; if you can't read them, submit the form and a new image will be generated. Not case sensitive.  Switch to audio verification.