Index: wp-includes/Oxymel.php
===================================================================
--- wp-includes/Oxymel.php	(revision 0)
+++ wp-includes/Oxymel.php	(working copy)
@@ -0,0 +1,211 @@
+<?php
+class Oxymel {
+	private $xml;
+	private $dom;
+	private $current_element;
+	private $last_inserted;
+	private $go_deep_on_next_element = 0;
+	private $go_up_on_next_element = 0;
+	private $nesting_level = 0;
+	private $contains_nesting_level = 0;
+	private $indentation= '  ';
+
+	public function __construct() {
+		$this->xml = '';
+		$this->init_new_dom();
+	}
+
+	public function to_string() {
+		return $this->xml .= $this->indent( $this->xml_from_dom(), $this->nesting_level );
+	}
+
+	public function __call( $name, $args ) {
+		array_unshift( $args, $name );
+		return call_user_func_array( array( $this, 'tag' ), $args );
+	}
+
+	public function __get( $name ) {
+		return $this->$name();
+	}
+
+	public function contains() {
+		$this->contains_nesting_level++;
+		$this->nesting_level++;
+		if ( $this->go_deep_on_next_element ) {
+			throw new OxymelException( 'contains cannot be used consecutively more than once' );
+		}
+		$this->go_deep_on_next_element++;
+		return $this;
+	}
+
+	public function end() {
+		$this->contains_nesting_level--;
+		$this->nesting_level--;
+		if ( $this->contains_nesting_level < 0 ) {
+			throw new OxymelException( 'end is used without a matching contains' );
+		}
+		$this->go_up_on_next_element++;
+		return $this;
+	}
+
+	public function tag( $name, $content_or_attributes = null, $attributes = array() ) {
+		list( $content, $attributes ) = $this->get_content_and_attributes_from_tag_args( $content_or_attributes, $attributes );
+		$is_opening =  0 === strpos( $name, 'open_' );
+		$is_closing =  0 === strpos( $name, 'close_' );
+		$name = preg_replace("/^(open|close)_/", '', $name );
+
+		$element = $this->create_element( $name, $content, $attributes );
+
+		if ( !$is_opening && !$is_closing )
+			$this->add_element_to_dom( $element );
+		elseif ( $is_opening )
+			$this->add_opening_tag_from_element( $element );
+		elseif ( $is_closing )
+			$this->add_closing_tag_from_tag_name( $name );
+
+		return $this;
+	}
+
+	public function cdata( $text ) {
+		$this->add_element_to_dom( $this->dom->createCDATASection( $text ) );
+		return $this;
+	}
+
+	public function text( $text ) {
+		$this->add_element_to_dom( $this->dom->createTextNode( $text ) );
+		return $this;
+	}
+
+	public function comment( $text ) {
+		$this->add_element_to_dom( $this->dom->createComment( $text ) );
+		return $this;
+	}
+
+	public function xml() {
+		$this->add_element_to_dom( $this->dom->createProcessingInstruction( 'xml', 'version="1.0" encoding="UTF-8"' ) );
+		return $this;
+	}
+
+	public function oxymel( Oxymel $other ) {
+		foreach( $other->dom->childNodes as $child ) {
+			$child = $this->dom->importNode( $child, true );
+			$this->add_element_to_dom( $child );
+		}
+		return $this;
+	}
+
+	public function raw(  $raw_xml ) {
+		if ( !$raw_xml ) {
+			return $this;
+		}
+		$fragment = $this->dom->createDocumentFragment();
+		$fragment->appendXML($raw_xml);
+		$this->add_element_to_dom( $fragment );
+		return $this;
+	}
+
+	private function add_element_to_dom( $element ) {
+		$this->move_current_element_deep();
+		$this->move_current_element_up();
+		$this->last_inserted = $this->current_element->appendChild($element);
+	}
+
+	private function move_current_element_deep() {
+		if ( $this->go_deep_on_next_element ) {
+			if ( !$this->last_inserted ) {
+				throw new OxymelException( 'contains has been used before adding any tags' );
+			}
+			$this->current_element = $this->last_inserted;
+			$this->go_deep_on_next_element--;
+		}
+	}
+
+	private function move_current_element_up() {
+		if ( $this->go_up_on_next_element ) {
+			while ( $this->go_up_on_next_element ) {
+				$this->current_element = $this->current_element->parentNode;
+				$this->go_up_on_next_element--;
+			}
+		}
+	}
+
+	private function get_content_and_attributes_from_tag_args( $content_or_attributes, array $attributes ) {
+		$content = null;
+		if ( !$attributes ) {
+			if ( is_array( $content_or_attributes ) )
+				$attributes = $content_or_attributes;
+			else
+				$content = $content_or_attributes;
+		} else {
+			$content = $content_or_attributes;
+		}
+		return array( $content, $attributes );
+	}
+
+	private function init_new_dom() {
+		unset( $this->dom, $this->current_element );
+		$this->dom = new DOMDocument();
+		$this->dom->formatOutput = true;
+		$this->current_element = $this->dom;
+		$this->last_inserted = null;
+	}
+
+	private function xml_from_dom() {
+		if ( 0 !== $this->contains_nesting_level ) {
+			throw new OxymelException( 'contains and end calls do not match' );
+		}
+		$xml = '';
+		foreach( $this->dom->childNodes as $child ) {
+			$xml .= $this->dom->saveXML( $child ) . "\n";
+		}
+		return $xml;
+	}
+
+	private function create_element( $name, $content, $attributes ) {
+		if ( !is_null( $content ) )
+			$element = $this->dom->createElement( $name, $content );
+		else
+			$element = $this->dom->createElement( $name );
+
+		foreach( $attributes as $attribute_name => $attribute_value ) {
+			$element->setAttribute( $attribute_name, $attribute_value );
+		}
+
+		return $element;
+	}
+
+	private function add_opening_tag_from_element( $element ) {
+		$this->xml .= $this->indent( $this->xml_from_dom(), $this->nesting_level );
+		$tag = $this->dom->saveXML($element);
+		$this->xml .= $this->indent( str_replace( '/>', '>', $tag ) . "\n", $this->nesting_level );
+		$this->nesting_level++;
+		$this->init_new_dom();
+	}
+
+	private function add_closing_tag_from_tag_name( $name ) {
+		$this->xml .= $this->xml_from_dom();
+		$this->nesting_level--;
+		if ( $this->nesting_level < 0 ) {
+			$this->xml = $this->indent( $this->xml, -$this->nesting_level );
+			$this->nesting_level = 0;
+		}
+		$this->xml .= $this->indent( "</$name>\n", $this->nesting_level );
+		$this->init_new_dom();
+	}
+
+	private function indent( $string, $level ) {
+		if ( !$level ) {
+			return $string;
+		}
+		$lines = explode( "\n", $string );
+		foreach( $lines as &$line ) {
+			if ( !trim( $line ) )
+				continue;
+			$line = str_repeat( $this->indentation, $level ) . $line;
+		}
+		return implode( "\n", $lines );
+	}
+}
+
+class OxymelException extends Exception {
+}

Property changes on: wp-includes/Oxymel.php
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: wp-includes/default-constants.php
===================================================================
--- wp-includes/default-constants.php	(revision 23447)
+++ wp-includes/default-constants.php	(working copy)
@@ -80,6 +80,17 @@
 	define( 'DAY_IN_SECONDS',    24 * HOUR_IN_SECONDS   );
 	define( 'WEEK_IN_SECONDS',    7 * DAY_IN_SECONDS    );
 	define( 'YEAR_IN_SECONDS',  365 * DAY_IN_SECONDS    );
+
+	// Constants for expressing human-readable data sizes
+	// in their respective number of bytes.
+	define( 'KB_IN_BYTES', 1024 );
+	define( 'MB_IN_BYTES', 1024 * KB_IN_BYTES );
+	define( 'GB_IN_BYTES', 1024 * MB_IN_BYTES );
+	define( 'TB_IN_BYTES', 1024 * GB_IN_BYTES );
+	define( 'PB_IN_BYTES', 1024 * TB_IN_BYTES );
+	define( 'EB_IN_BYTES', 1024 * PB_IN_BYTES );
+	define( 'ZB_IN_BYTES', 1024 * EB_IN_BYTES );
+	define( 'YB_IN_BYTES', 1024 * ZB_IN_BYTES );
 }
 
 /**
Index: wp-includes/export/class-wp-export-query.php
===================================================================
--- wp-includes/export/class-wp-export-query.php	(revision 0)
+++ wp-includes/export/class-wp-export-query.php	(working copy)
@@ -0,0 +1,300 @@
+<?php
+/**
+ * Represents a set of posts and other site data to be exported.
+ *
+ * An immutable object, which gathers all data needed for the export.
+ */
+class WP_Export_Query {
+	const QUERY_CHUNK = 100;
+
+	private static $defaults = array(
+		'post_ids' => null,
+		'post_type' => null,
+		'status' => null,
+		'author' => null,
+		'start_date' => null,
+		'end_date' => null,
+		'category' => null,
+	);
+
+	private $post_ids;
+	private $filters;
+	private $xml_gen;
+
+	private $wheres = array();
+	private $joins = array();
+
+	private $author;
+	private $category;
+
+	public function __construct( $filters = array() ) {
+		$this->filters = wp_parse_args( $filters, self::$defaults );
+		$this->post_ids = $this->calculate_post_ids();
+	}
+
+	public function post_ids() {
+		return $this->post_ids;
+	}
+
+	public function charset() {
+		return get_bloginfo( 'charset' );
+	}
+
+	public function site_metadata() {
+		$metadata = array(
+			'name' => $this->bloginfo_rss( 'name' ),
+			'url' => $this->bloginfo_rss( 'url' ),
+			'language' => $this->bloginfo_rss( 'language' ),
+			'description' => $this->bloginfo_rss( 'description' ),
+			'pubDate' => date( 'D, d M Y H:i:s +0000' ),
+			'site_url' => is_multisite()? network_home_url() : $this->bloginfo_rss( 'url' ),
+			'blog_url' => $this->bloginfo_rss( 'url' ),
+		);
+		return $metadata;
+	}
+
+	public function wp_generator_tag() {
+		return apply_filters( 'the_generator', get_the_generator( 'export' ), 'export' );
+	}
+
+	public function authors() {
+		global $wpdb;
+		$authors = array();
+		$author_ids = $wpdb->get_col( "SELECT DISTINCT post_author FROM $wpdb->posts WHERE post_status != 'auto-draft'" );
+		foreach ( (array) $author_ids as $author_id ) {
+			$authors[] = get_userdata( $author_id );
+		}
+		$authors = array_filter( $authors );
+		return $authors;
+	}
+
+	public function categories() {
+		if ( $this->category ) {
+			return $this->category;
+		}
+		if ( $this->filters['post_type'] ) {
+			return array();
+		}
+		$categories = (array) get_categories( array( 'get' => 'all' ) );
+		$categories = self::topologically_sort_terms( $categories );
+		return $categories;
+	}
+
+	public function tags() {
+		if ( $this->filters['post_type'] ) {
+			return array();
+		}
+		$tags = (array) get_tags( array( 'get' => 'all' ) );
+		return $tags;
+	}
+
+	public function custom_taxonomies_terms() {
+		if ( $this->filters['post_type'] ) {
+			return array();
+		}
+		$custom_taxonomies = get_taxonomies( array( '_builtin' => false ) );
+		$custom_terms = (array) get_terms( $custom_taxonomies, array( 'get' => 'all' ) );
+		$custom_terms = self::topologically_sort_terms( $custom_terms );
+		return $custom_terms;
+	}
+
+	public function nav_menu_terms() {
+		$nav_menus = wp_get_nav_menus();
+		foreach( $nav_menus as &$term ) {
+			$term->description = '';
+		}
+		return $nav_menus;
+	}
+
+	public function exportify_post( $post ) {
+		$GLOBALS['wp_query']->in_the_loop = true;
+		$previous_global_post = isset( $GLOBALS['post'] )? $GLOBALS['post'] : null;
+		$GLOBALS['post'] = $post;
+		setup_postdata( $post );
+		$post->post_content = apply_filters( 'the_content_export', $post->post_content );
+		$post->post_excerpt = apply_filters( 'the_excerpt_export', $post->post_excerpt );
+		$post->is_sticky = is_sticky( $post->ID ) ? 1 : 0;
+		$post->terms = self::get_terms_for_post( $post );
+		$post->meta = self::get_meta_for_post( $post );
+		$post->comments = self::get_comments_for_post( $post );
+		$GLOBALS['post'] = $previous_global_post;
+		return $post;
+	}
+
+	public function posts() {
+		$posts_iterator = new WP_Post_IDs_Iterator( $this->post_ids, self::QUERY_CHUNK );
+		return new WP_Map_Iterator( $posts_iterator, array( $this, 'exportify_post' ) );
+	}
+
+	private function calculate_post_ids() {
+		global $wpdb;
+		if ( is_array( $this->filters['post_ids'] ) ) {
+			return $this->filters['post_ids'];
+		}
+		$this->post_type_where();
+		$this->status_where();
+		$this->author_where();
+		$this->start_date_where();
+		$this->end_date_where();
+		$this->category_where();
+
+		$where = implode( ' AND ', array_filter( $this->wheres ) );
+		if ( $where ) $where = "WHERE $where";
+		$join = implode( ' ', array_filter( $this->joins ) );
+
+		$post_ids = $wpdb->get_col( "SELECT ID FROM {$wpdb->posts} AS p $join $where" );
+		$post_ids = array_merge( $post_ids, $this->attachments_for_specific_post_types( $post_ids ) );
+		return $post_ids;
+	}
+
+	private function post_type_where() {
+		global $wpdb;
+		$post_types_filters = array( 'can_export' => true );
+		if ( $this->filters['post_type'] ) {
+			$post_types_filters = array_merge( $post_types_filters, array( 'name' => $this->filters['post_type'] ) );
+		}
+		$post_types = get_post_types( $post_types_filters );
+		if ( !$post_types ) {
+			$this->wheres[] = 'p.post_type IS NULL';
+			return;
+		}
+		$this->wheres[] = $wpdb->build_IN_condition( 'p.post_type', $post_types );
+	}
+
+	private function status_where() {
+		global $wpdb;
+		if ( !$this->filters['status'] ) {
+			$this->wheres[] = "p.post_status != 'auto-draft'";
+			return;
+		}
+		$this->wheres[] = $wpdb->prepare( 'p.post_status = %s', $this->filters['status'] );
+	}
+
+	private function author_where() {
+		global $wpdb;
+		$user = $this->find_user_from_any_object( $this->filters['author'] );
+		if ( !$user || is_wp_error( $user ) ) {
+			return;
+		}
+		$this->author = $user;
+		$this->wheres[] = $wpdb->prepare( 'p.post_author = %d', $user->ID );
+	}
+
+	private function start_date_where() {
+		global $wpdb;
+		$timestamp = strtotime( $this->filters['start_date'] );
+		if ( !$timestamp ) {
+			return;
+		}
+		$this->wheres[] = $wpdb->prepare( 'p.post_date >= %s', date( 'Y-m-d 00:00:00', $timestamp ) );
+	}
+
+	private function end_date_where() {
+		global $wpdb;
+		$timestamp = strtotime( $this->filters['end_date'] );
+		if ( !$timestamp ) {
+			return;
+		}
+		$this->wheres[] = $wpdb->prepare( 'p.post_date <= %s', date( 'Y-m-d 23:59:59', $timestamp ) );
+	}
+
+	private function category_where() {
+		global $wpdb;
+		if ( 'post' != $this->filters['post_type'] ) {
+			return;
+		}
+		$category = $this->find_category_from_any_object( $this->filters['category'] );
+		if ( !$category ) {
+			return;
+		}
+		$this->category = $category;
+		$this->joins[] = "INNER JOIN {$wpdb->term_relationships} AS tr ON (p.ID = tr.object_id)";
+		$this->wheres[] = $wpdb->prepare( 'tr.term_taxonomy_id = %d', $category->term_taxonomy_id );
+	}
+
+	private function attachments_for_specific_post_types( $post_ids ) {
+		global $wpdb;
+		if ( !$this->filters['post_type'] ) {
+			return array();
+		}
+		$attachment_ids = array();
+		while ( $batch_of_post_ids = array_splice( $post_ids, 0, self::QUERY_CHUNK ) ) {
+			$post_parent_condition = $wpdb->build_IN_condition( 'post_parent', $batch_of_post_ids );
+			$attachment_ids = array_merge( $attachment_ids, (array)$wpdb->get_col( "SELECT ID FROM {$wpdb->posts} WHERE post_type = 'attachment' AND $post_parent_condition" ) );
+		}
+		return array_map( 'intval', $attachment_ids );
+	}
+
+	private function bloginfo_rss( $section ) {
+		return apply_filters( 'bloginfo_rss', get_bloginfo_rss( $section ), $section );
+	}
+
+	private function find_user_from_any_object( $user ) {
+		if ( is_numeric( $user ) ) {
+			return get_user_by( 'id', $user );
+		} elseif ( is_string( $user ) ) {
+			return get_user_by( 'login', $user );
+		} elseif ( isset( $user->ID ) ) {
+			return get_user_by( 'id', $user->ID );
+		}
+		return false;
+	}
+
+	private function find_category_from_any_object( $category ) {
+		if ( is_numeric( $category ) ) {
+			return get_term( $category, 'category' );
+		} elseif ( is_string( $category ) ) {
+			$term = term_exists( $category, 'category' );
+			return isset( $term['term_id'] )? get_term( $term['term_id'], 'category' ) : false;
+		} elseif ( isset( $category->term_id ) ) {
+			return get_term( $category->term_id, 'category' );
+		}
+		return false;
+	}
+
+	private static function topologically_sort_terms( $terms ) {
+		$sorted = array();
+		while ( $term = array_shift( $terms ) ) {
+			if ( $term->parent == 0 || isset( $sorted[$term->parent] ) )
+				$sorted[$term->term_id] = $term;
+			else
+				$terms[] = $term;
+		}
+		return $sorted;
+	}
+
+	private static function get_terms_for_post( $post ) {
+		$taxonomies = get_object_taxonomies( $post->post_type );
+		if ( empty( $taxonomies ) )
+			return array();
+		$terms = wp_get_object_terms( $post->ID, $taxonomies );
+		$terms = $terms? $terms : array();
+		return $terms;
+	}
+
+	private static function get_meta_for_post( $post ) {
+		global $wpdb;
+		$meta_for_export = array();
+		$meta_from_db = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->postmeta WHERE post_id = %d", $post->ID ) );
+		foreach ( $meta_from_db as $meta ) {
+			if ( apply_filters( 'wxr_export_skip_postmeta', false, $meta->meta_key, $meta ) )
+				continue;
+			$meta_for_export[] = $meta;
+		}
+		return $meta_for_export;
+	}
+
+	private static function get_comments_for_post( $post ) {
+		global $wpdb;
+		$comments = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved <> 'spam'", $post->ID ) );
+		foreach( $comments as $comment ) {
+			$meta = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->commentmeta WHERE comment_id = %d", $comment->comment_ID ) );
+			$meta = $meta? $meta : array();
+			$comment->meta = $meta;
+		}
+		return $comments;
+	}
+}
+
+class WP_Export_Exception extends RuntimeException {
+}

Property changes on: wp-includes/export/class-wp-export-query.php
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: wp-includes/export/class-wp-export-wxr-formatter.php
===================================================================
--- wp-includes/export/class-wp-export-wxr-formatter.php	(revision 0)
+++ wp-includes/export/class-wp-export-wxr-formatter.php	(working copy)
@@ -0,0 +1,279 @@
+<?php
+/**
+ * Version number for the export format.
+ *
+ * Bump this when something changes that might affect compatibility.
+ *
+ * @since 2.5.0
+ */
+define( 'WXR_VERSION', '1.2' );
+
+require_once ABSPATH . WPINC . '/Oxymel.php';
+
+class WP_Export_Oxymel extends Oxymel {
+	public function optional( $tag_name, $contents ) {
+		if ( $contents ) {
+			$this->$tag_name( $contents );
+		}
+		return $this;
+	}
+
+	public function optional_cdata( $tag_name, $contents ) {
+		if ( $contents ) {
+			$this->$tag_name->contains->cdata( $contents )->end;
+		}
+		return $this;
+	}
+}
+
+/**
+ * Responsible for formatting the data in WP_Export_Query to WXR
+ */
+class WP_Export_WXR_Formatter {
+	function __construct( $export ) {
+		$this->export = $export;
+		$this->wxr_version = WXR_VERSION;
+	}
+
+	function before_posts() {
+		$before_posts_xml = '';
+		$before_posts_xml .= $this->header();
+		$before_posts_xml .= $this->site_metadata();
+		$before_posts_xml .= $this->authors();
+		$before_posts_xml .= $this->categories();
+		$before_posts_xml .= $this->tags();
+		$before_posts_xml .= $this->nav_menu_terms();
+		$before_posts_xml .= $this->custom_taxonomies_terms();
+		$before_posts_xml .= $this->rss2_head_action();
+		return $before_posts_xml;
+	}
+
+	function posts() {
+		return new WP_Map_Iterator( $this->export->posts(), array( $this, 'post' ) );
+	}
+
+	function after_posts() {
+		return $this->footer();
+	}
+
+	function header() {
+		$oxymel = new Oxymel;
+		$charset = $this->export->charset();
+		$wp_generator_tag = $this->export->wp_generator_tag();
+		$comment = <<<COMMENT
+
+ This is a WordPress eXtended RSS file generated by WordPress as an export of your site.
+ It contains information about your site's posts, pages, comments, categories, and other content.
+ You may use this file to transfer that content from one site to another.
+ This file is not intended to serve as a complete backup of your site.
+
+ To import this information into a WordPress site follow these steps:
+ 1. Log in to that site as an administrator.
+ 2. Go to Tools: Import in the WordPress admin panel.
+ 3. Install the "WordPress" importer from the list.
+ 4. Activate & Run Importer.
+ 5. Upload this file using the form provided on that page.
+ 6. You will first be asked to map the authors in this export file to users
+    on the site. For each author, you may choose to map to an
+    existing user on the site or to create a new user.
+ 7. WordPress will then import each of the posts, pages, comments, categories, etc.
+    contained in this file into your site.
+
+COMMENT;
+		return $oxymel
+			->xml
+			->comment( $comment )
+			->raw( $wp_generator_tag )
+			->open_rss( array(
+				'version' => '2.0',
+				'xmlns:excerpt' => "http://wordpress.org/export/{$this->wxr_version}/excerpt/",
+				'xmlns:content' => "http://purl.org/rss/1.0/modules/content/",
+				'xmlns:wfw' => "http://wellformedweb.org/CommentAPI/",
+				'xmlns:dc' => "http://purl.org/dc/elements/1.1/",
+				'xmlns:wp' => "http://wordpress.org/export/{$this->wxr_version}/",
+			) )
+				->open_channel
+				->to_string();
+
+	}
+
+	function site_metadata() {
+		$oxymel = new Oxymel;
+		$metadata = $this->export->site_metadata();
+		return $oxymel
+			->title( $metadata['name'] )
+			->link( $metadata['url'] )
+			->description( $metadata['description'] )
+			->pubDate( $metadata['pubDate'] )
+			->language( $metadata['language'] )
+			->tag( 'wp:wxr_version', $this->wxr_version )
+			->tag( 'wp:base_site_url', $metadata['site_url'] )
+			->tag( 'wp:base_blog_url', $metadata['blog_url'] )
+			->to_string();
+	}
+
+	function authors() {
+		$oxymel = new Oxymel;
+		$authors = $this->export->authors();
+		foreach ( $authors as $author ) {
+			$oxymel
+				->tag( 'wp:wp_author' )->contains
+					->tag( 'wp:author_login', $author->user_login )
+					->tag( 'wp:author_email', $author->user_email )
+					->tag( 'wp:author_display_name' )->contains->cdata( $author->display_name )->end
+					->tag( 'wp:author_first_name' )->contains->cdata( $author->user_first_name )->end
+					->tag( 'wp:author_last_name' )->contains->cdata( $author->user_last_name )->end
+					->end;
+		}
+		return $oxymel->to_string();
+	}
+
+	function categories() {
+		$oxymel = new WP_Export_Oxymel;
+		$categories = $this->export->categories();
+		foreach( $categories as $term_id => $category ) {
+			$category->parent_slug = $category->parent? $categories[$category->parent]->slug : '';
+			$oxymel->tag( 'wp:category' )->contains
+				->tag( 'wp:term_id', $category->term_id )
+				->tag( 'wp:category_nicename', $category->slug )
+				->tag( 'wp:category_parent', $category->parent_slug )
+				->optional_cdata( 'wp:cat_name', $category->name )
+				->optional_cdata( 'wp:category_description', $category->description )
+				->end;
+		}
+		return $oxymel->to_string();
+	}
+
+	function tags() {
+		$oxymel = new WP_Export_Oxymel;
+		$tags = $this->export->tags();
+		foreach( $tags as $tag ) {
+			$oxymel->tag( 'wp:tag' )->contains
+				->tag( 'wp:term_id', $tag->term_id )
+				->tag( 'wp:tag_slug', $tag->slug )
+				->optional_cdata( 'wp:tag_name', $tag->name )
+				->optional_cdata( 'wp:tag_description', $tag->description )
+				->end;
+		}
+		return $oxymel->to_string();
+	}
+
+	function nav_menu_terms() {
+		return $this->terms( $this->export->nav_menu_terms() );
+	}
+
+	function custom_taxonomies_terms() {
+		return $this->terms( $this->export->custom_taxonomies_terms() );
+	}
+
+	function rss2_head_action() {
+		ob_start();
+		do_action( 'rss2_head' );
+		$action_output = ob_get_clean();
+		return $action_output;
+	}
+
+	private function terms( $terms ) {
+		$oxymel = new WP_Export_Oxymel;
+		foreach( $terms as $term ) {
+			$term->parent_slug = $term->parent? $terms[$term->parent]->slug : '';
+			$oxymel->tag( 'wp:term' )->contains
+				->tag( 'wp:term_id', $term->term_id )
+				->tag( 'wp:term_taxonomy', $term->taxonomy )
+				->tag( 'wp:term_slug', $term->slug );
+			if ( 'nav_menu' != $term->taxonomy ) {
+				$oxymel
+				->tag( 'wp:term_parent', $term->parent_slug );
+			}
+				$oxymel
+				->optional_cdata( 'wp:term_name', $term->name )
+				->optional_cdata( 'wp:term_description', $term->description )
+				->end;
+		}
+		return $oxymel->to_string();
+	}
+
+	function post( $post ) {
+		$oxymel = new WP_Export_Oxymel;
+		$GLOBALS['wp_query']->in_the_loop = true;
+		$GLOBALS['post'] = $post;
+		setup_postdata( $post );
+
+		$oxymel->item->contains
+			->title( apply_filters( 'the_title_rss', $post->post_title ) )
+			->link( apply_filters('the_permalink_rss', get_permalink() ) )
+			->pubDate( mysql2date( 'D, d M Y H:i:s +0000', get_post_time( 'Y-m-d H:i:s', true ), false ) )
+			->tag( 'dc:creator', get_the_author_meta( 'login' ) )
+			->guid( get_the_guid(), array( 'isPermaLink' => 'false' ) )
+			->description( '' )
+			->tag( 'content:encoded' )->contains->cdata( $post->post_content )->end
+			->tag( 'excerpt:encoded' )->contains->cdata( $post->post_excerpt )->end
+			->tag( 'wp:post_id', $post->ID )
+			->tag( 'wp:post_date', $post->post_date )
+			->tag( 'wp:post_date_gmt', $post->post_date_gmt )
+			->tag( 'wp:comment_status', $post->comment_status )
+			->tag( 'wp:ping_status', $post->ping_status )
+			->tag( 'wp:post_name', $post->post_name )
+			->tag( 'wp:status', $post->post_status )
+			->tag( 'wp:post_parent', $post->post_parent )
+			->tag( 'wp:menu_order', $post->menu_order )
+			->tag( 'wp:post_type', $post->post_type )
+			->tag( 'wp:post_password', $post->post_password )
+			->tag( 'wp:is_sticky', $post->is_sticky )
+			->optional( 'wp:attachment_url', wp_get_attachment_url( $post->ID ) );
+		foreach( $post->terms as $term ) {
+			$oxymel
+			->category( array( 'domain' => $term->taxonomy, 'nicename' => $term->slug  ) )->contains->cdata( $term->name )->end;
+		}
+		foreach( $post->meta as $meta ) {
+			$oxymel
+			->tag( 'wp:postmeta' )->contains
+				->tag( 'wp:meta_key', $meta->meta_key )
+				->tag( 'wp:meta_value' )->contains->cdata( $meta->meta_value )->end
+				->end;
+		}
+		foreach( $post->comments as $comment ) {
+			$oxymel
+			->tag( 'wp:comment' )->contains
+				->tag( 'wp:comment_id', $comment->comment_ID )
+				->tag( 'wp:comment_author' )->contains->cdata( $comment->comment_author )->end
+				->tag( 'wp:comment_author_email', $comment->comment_author_email )
+				->tag( 'wp:comment_author_url', $comment->comment_author_url )
+				->tag( 'wp:comment_author_IP', $comment->comment_author_IP )
+				->tag( 'wp:comment_date', $comment->comment_date )
+				->tag( 'wp:comment_date_gmt', $comment->comment_date_gmt )
+				->tag( 'wp:comment_content' )->contains->cdata( $comment->comment_content )->end
+				->tag( 'wp:comment_approved', $comment->comment_approved )
+				->tag( 'wp:comment_type', $comment->comment_type )
+				->tag( 'wp:comment_parent', $comment->comment_parent )
+				->tag( 'wp:comment_user_id', $comment->user_id )
+				->oxymel( $this->comment_meta( $comment ) )
+				->end;
+		}
+		$oxymel
+			->end;
+		return $oxymel->to_string();
+	}
+
+	private function comment_meta( $comment ) {
+		global $wpdb;
+		$metas = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->commentmeta WHERE comment_id = %d", $comment->comment_ID ) );
+		if ( !$metas ) {
+			return new Oxymel;
+		}
+		$oxymel = new WP_Export_Oxymel;
+		foreach( $metas as $meta ) {
+			$oxymel->tag( 'wp:commentmeta' )->contains
+				->tag( 'wp:meta_key', $meta->meta_key )
+				->tag( 'wp:meta_value', $meta->meta_value )
+			->end;
+		}
+		return $oxymel;
+	}
+
+
+	function footer() {
+		$oxymel = new Oxymel;
+		return $oxymel->close_channel->close_rss->to_string();
+	}
+}

Property changes on: wp-includes/export/class-wp-export-wxr-formatter.php
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: wp-includes/export/functions.export.php
===================================================================
--- wp-includes/export/functions.export.php	(revision 0)
+++ wp-includes/export/functions.export.php	(working copy)
@@ -0,0 +1,19 @@
+<?php
+
+function wp_export( $args = array() ) {
+	$defaults = array(
+		'filters' => array(),
+		'format' => 'WP_Export_WXR_Formatter',
+		'writer' => 'WP_Export_Returner',
+		'writer_args' => null,
+	);
+	$args = wp_parse_args( $args, $defaults );
+	$export_query = new WP_Export_Query( $args['filters'] );
+	$formatter = new $args['format']( $export_query );
+	$writer = new $args['writer']( $formatter, $args['writer_args'] );
+	try {
+		return $writer->export();
+	} catch ( WP_Export_Exception $e ) {
+		return new WP_Error( 'wp-export-error', $e->getMessage() );
+	}
+}

Property changes on: wp-includes/export/functions.export.php
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: wp-includes/export/writers.php
===================================================================
--- wp-includes/export/writers.php	(revision 0)
+++ wp-includes/export/writers.php	(working copy)
@@ -0,0 +1,145 @@
+<?php
+abstract class WP_Export_Base_Writer {
+	protected $formatter;
+
+	function __construct( $formatter ) {
+		$this->formatter = $formatter;
+	}
+
+	public function export() {
+		$this->write( $this->formatter->before_posts() );
+		foreach( $this->formatter->posts() as $post_in_wxr ) {
+			$this->write( $post_in_wxr );
+		}
+		$this->write( $this->formatter->after_posts() );
+	}
+
+	abstract protected function write( $xml );
+}
+
+class WP_Export_XML_Over_HTTP extends WP_Export_Base_Writer {
+	private $file_name;
+
+	function __construct( $formatter, $file_name ) {
+		parent::__construct( $formatter );
+		$this->file_name = $file_name;
+	}
+
+	public function export() {
+		header( 'Content-Description: File Transfer' );
+		header( 'Content-Disposition: attachment; filename=' . $this->file_name );
+		header( 'Content-Type: text/xml; charset=' . get_option( 'blog_charset' ), true );
+		parent::export();
+	}
+
+	protected function write( $xml ) {
+		echo $xml;
+	}
+}
+
+class WP_Export_Returner extends WP_Export_Base_Writer {
+	private $result = '';
+
+	public function export() {
+		$this->private = '';
+		parent::export();
+		return $this->result;
+	}
+	protected function write( $xml ) {
+		$this->result .= $xml;
+	}
+}
+
+class WP_Export_File_Writer extends WP_Export_Base_Writer {
+	private $f;
+	private $file_name;
+
+	public function __construct( $formatter, $file_name ) {
+		parent::__construct( $formatter );
+		$this->file_name = $file_name;
+	}
+
+	public function export() {
+		$this->f = fopen( $this->file_name, 'w' );
+		if ( !$this->f ) {
+			throw new WP_Export_Exception( sprintf( __( 'WP Export: error opening %s for writing.' ), $this->file_name ) );
+		}
+		parent::export();
+		fclose( $this->f );
+	}
+
+	protected function write( $xml ) {
+		$res = fwrite( $this->f, $xml);
+		if ( false === $res ) {
+			throw new WP_Export_Exception( __( 'WP Export: error writing to export file.' ) );
+		}
+	}
+}
+
+class WP_Export_Split_Files_Writer extends WP_Export_Base_Writer {
+	private $result = '';
+	private $f;
+	private $next_file_number = 0;
+	private $current_file_size = 0;
+
+	function __construct( $formatter, $writer_args = array() ) {
+		parent::__construct( $formatter );
+		//TODO: check if args are not missing
+		$this->max_file_size = is_null( $writer_args['max_file_size'] ) ? 15 * MB_IN_BYTES : $max_file_size;
+		$this->destination_directory = $writer_args['destination_directory'];
+		$this->filename_template = $writer_args['filename_template'];
+		$this->before_posts_xml = $this->formatter->before_posts();
+		$this->after_posts_xml = $this->formatter->after_posts();
+	}
+
+	public function export() {
+		$this->start_new_file();
+		foreach( $this->formatter->posts() as $post_xml ) {
+			if ( $this->current_file_size + strlen( $post_xml ) > $this->max_file_size ) {
+				$this->start_new_file();
+			}
+			$this->write( $post_xml );
+		}
+		$this->close_current_file();
+	}
+
+	protected function write( $xml ) {
+		$res = fwrite( $this->f, $xml);
+		if ( false === $res ) {
+			throw new WP_Export_Exception( __( 'WP Export: error writing to export file.' ) );
+		}
+		$this->current_file_size += strlen( $xml );
+	}
+
+	private function start_new_file() {
+		if ( $this->f ) {
+			$this->close_current_file();
+		}
+		$file_path = $this->next_file_path();
+		$this->f = fopen( $file_path, 'w' );
+		if ( !$this->f ) {
+			throw new WP_Export_Exception( sprintf( __( 'WP Export: error opening %s for writing.' ), $file_path ) );
+		}
+		$this->current_file_size = 0;
+		$this->write( $this->before_posts_xml );
+	}
+
+	private function close_current_file() {
+		if ( !$this->f ) {
+			return;
+		}
+		$this->write( $this->after_posts_xml );
+		fclose( $this->f );
+	}
+
+	private function next_file_name() {
+		$next_file_name = sprintf( $this->filename_template, $this->next_file_number );
+		$this->next_file_number++;
+		return $next_file_name;
+	}
+
+	private function next_file_path() {
+		return untrailingslashit( $this->destination_directory ) . DIRECTORY_SEPARATOR . $this->next_file_name();
+	}
+
+}
Index: wp-includes/iterators.php
===================================================================
--- wp-includes/iterators.php	(revision 0)
+++ wp-includes/iterators.php	(working copy)
@@ -0,0 +1,80 @@
+<?php
+class WP_Map_Iterator extends IteratorIterator {
+	function __construct( $iterator, $callback ) {
+		$this->callback = $callback;
+		parent::__construct( $iterator );
+	}
+
+	function current() {
+		$original_current = parent::current();
+		return call_user_func( $this->callback, $original_current );
+	}
+}
+
+class WP_Post_IDs_Iterator implements Iterator {
+	private $limit = 100;
+	private $post_ids;
+	private $ids_left;
+	private $results = array();
+
+	public function __construct( $post_ids, $limit = null ) {
+		$this->db = $GLOBALS['wpdb'];
+		$this->post_ids = $post_ids;
+		$this->ids_left = $post_ids;
+		if ( !is_null( $limit ) ) {
+			$this->limit = $limit;
+		}
+	}
+
+	public function current() {
+		return $this->results[$this->index_in_results];
+	}
+
+	public function key() {
+		return $this->global_index;
+	}
+
+	public function next() {
+		$this->index_in_results++;
+		$this->global_index++;
+	}
+
+	public function rewind() {
+		$this->results = array();
+		$this->global_index = 0;
+		$this->index_in_results = 0;
+		$this->ids_left = $this->post_ids;
+	}
+
+	public function valid() {
+		if ( isset( $this->results[$this->index_in_results] ) ) {
+			return true;
+		}
+		if ( empty( $this->ids_left ) ) {
+			return false;
+		}
+		$has_posts = $this->load_next_posts_from_db();
+		if ( !$has_posts ) {
+			return false;
+		}
+		$this->index_in_results = 0;
+		return true;
+	}
+
+	private function load_next_posts_from_db() {
+		$next_batch_post_ids = array_splice( $this->ids_left, 0, $this->limit );
+		$in_post_ids_sql = $this->db->build_IN_condition( 'ID', $next_batch_post_ids );
+		$this->results = $this->db->get_results( "SELECT * FROM {$this->db->posts} WHERE $in_post_ids_sql" );
+		if ( !$this->results ) {
+			if ( $this->db->last_error ) {
+				throw new WP_Iterator_Exception( 'Database error: ' . $this->db->last_error );
+			} else {
+				return false;
+			}
+		}
+		return true;
+	}
+}
+
+class WP_Iterator_Exception extends Exception {
+}
Index: wp-includes/wp-db.php
===================================================================
--- wp-includes/wp-db.php	(revision 23447)
+++ wp-includes/wp-db.php	(working copy)
@@ -1734,4 +1734,22 @@
 	function db_version() {
 		return preg_replace( '/[^0-9.].*/', '', mysql_get_server_info( $this->dbh ) );
 	}
+
+	/**
+	 * Builds a SQL condition in the form "post_id IN (1, 2, 3, 4)"
+	 *
+	 * @since 3.6.0
+	 *
+	 * @param string $column_name The name of the table column from the IN condition
+	 * @param array $values Array of values in which the column value should be
+	 * @param string $format Optional printf format specifier for the elements of the array. Defaults to %s.
+	 * @return string The IN condition, with escaped values. If there are no values, the return value is an empty string.
+	 */
+	function build_IN_condition( $column_name, $values, $format = '%s' ) {
+		if ( !is_array( $values ) || empty( $values ) ) {
+			return '';
+		}
+		$formats = implode( ', ', array_fill( 0, count( $values ), $format ) );
+		return $this->prepare( "$column_name IN ($formats)", $values );
+	}
 }
Index: wp-settings.php
===================================================================
--- wp-settings.php	(revision 23447)
+++ wp-settings.php	(working copy)
@@ -123,6 +123,11 @@
 require( ABSPATH . WPINC . '/comment.php' );
 require( ABSPATH . WPINC . '/comment-template.php' );
 require( ABSPATH . WPINC . '/rewrite.php' );
+require( ABSPATH . WPINC . '/iterators.php' );
+require( ABSPATH . WPINC . '/export/class-wp-export-query.php' );
+require( ABSPATH . WPINC . '/export/class-wp-export-wxr-formatter.php' );
+require( ABSPATH . WPINC . '/export/writers.php' );
+require( ABSPATH . WPINC . '/export/functions.export.php' );
 require( ABSPATH . WPINC . '/feed.php' );
 require( ABSPATH . WPINC . '/bookmark.php' );
 require( ABSPATH . WPINC . '/bookmark-template.php' );
