=== modified file 'sites/all/modules/feeds_xpathparser/FeedsXPathParser.inc'
--- FeedsXPathParser.inc	2010-09-16 13:14:32 +0000
+++ FeedsXPathParser.inc	2010-09-18 16:32:50 +0000
@@ -38,9 +38,16 @@
    */
   public function parse(FeedsImportBatch $batch, FeedsSource $source) {
 
-    $mappings = feeds_importer($this->id)->processor->config['mappings'];
-    if (empty($mappings)) {
-      throw new Exception(t('FeedsXPathParser: No mappings were defined.'));
+    if ($batch->context == 'mapping') {
+      // Don't declare mappings. $parser->parse should see this and
+      // return all available fieldnames, instead of only the mapped fields.
+      $mappings = array();
+    }
+    else {
+      $mappings = feeds_importer($this->id)->processor->getMappings();
+      if (empty($mappings)) {
+        throw new Exception(t('FeedsXPathParser: No mappings were defined.'));
+      }
     }
     $source_config = $source->getConfigFor($this);
 
@@ -61,7 +68,10 @@
    * Define defaults.
    */
   public function sourceDefaults() {
-    return array('XML' => 0);
+    return array(
+      'parser_type' => 'HTML',
+      'context' => '',
+    );
   }
 
   /**
@@ -71,7 +81,8 @@
     $form = array();
     $form['#weight'] = -10;
 
-    $mappings = feeds_importer($this->id)->processor->config['mappings'];
+    $mappings = feeds_importer($this->id)->processor->getMappings();
+    $mapping_on_import = !empty(feeds_importer($this->id)->processor->config['mapping_on_import']);
     $sources = $uniques = array();
 
     foreach ($mappings as $mapping) {
@@ -82,8 +93,13 @@
     }
 
     if (empty($sources)) {
-      $form['message']['#value'] = 'FeedsXPathParser: No mappings were defined.';
-      return $form;
+      if ($mapping_on_import) {
+        $form['sources']['#value'] = 'FeedsXPathParser: Mappings need to be defined later, based on the parsed context.';
+      }
+      else {
+        $form['message']['#value'] = 'FeedsXPathParser: No mappings were defined.';
+        return $form;
+      }
     }
 
     ctools_include('dependent');
@@ -133,67 +149,75 @@
       '#default_value' => isset($source_config['context']) ? $source_config['context'] : '',
     );
 
-    $form['sources'] = array(
-      '#type' => 'fieldset',
-    );
-    $items = array(
-      format_plural(count($uniques),
-        t('Field <strong>!column</strong> is mandatory and considered unique: only one item per !column value will be created.',
-          array('!column' => implode(', ', $uniques))),
-        t('Fields <strong>!columns</strong> are mandatory and values in these columns are considered unique: only one entry per value in one of these columns will be created.',
-          array('!columns' => implode(', ', $uniques)))),
-    );
-
-    $form['sources']['help']['#value'] = '<div class="help">' . theme('item_list', $items) . '</div>';
-
-    $form['attrs'] = array(
-      '#type' => 'fieldset',
-      '#input' => TRUE,
-      '#prefix'        => '<div id="edit-feeds-FeedsXPathParser-attrs-wrapper"><div id="edit-feeds-FeedsXPathParser-attrs">',
-      '#suffix'        => '</div></div>',
-      '#process'       => array('ctools_dependent_process'),
-      '#dependency'    => array(
-        'radio:feeds[FeedsXPathParser][parser_type]' => array('QueryPath')
-      ),
-    );
-
-    foreach ($sources as $source) {
-      $form['sources'][$source] = array(
-        '#type'          => 'textfield',
-        '#title'         => $source,
-        '#description'   => t('The query string to run.'),
-        '#default_value' => isset($source_config['sources'][$source]) ? $source_config['sources'][$source] : '',
-      );
-
-      $form['attrs'][$source] = array(
-        '#type'          => 'textfield',
-        '#title'         => $source . ' Attribute',
-        '#description'   => t('The attribute to return.'),
-        '#default_value' => isset($source_config['attrs'][$source]) ? $source_config['attrs'][$source] : '',
+    // NOTE: there's a workflow issue when using 'mapping on import'.
+    // To use the below 'field related properties', you'd actually need to go through
+    // - this config screen (and submit)
+    // - the mapping screen - and after you've defined the mappings, DO NOT
+    //   press 'import' but go back again to
+    // - this config screen, where you now see the below options
+    if (!empty($sources)) {
+      $form['sources'] = array(
+        '#type' => 'fieldset',
+      );
+      $items = array(
+        format_plural(count($uniques),
+          t('Field <strong>!column</strong> is mandatory and considered unique: only one item per !column value will be created.',
+            array('!column' => implode(', ', $uniques))),
+          t('Fields <strong>!columns</strong> are mandatory and values in these columns are considered unique: only one entry per value in one of these columns will be created.',
+            array('!columns' => implode(', ', $uniques)))),
+      );
+
+      $form['sources']['help']['#value'] = '<div class="help">' . theme('item_list', $items) . '</div>';
+
+      $form['attrs'] = array(
+        '#type' => 'fieldset',
+        '#input' => TRUE,
+        '#prefix'        => '<div id="edit-feeds-FeedsXPathParser-attrs-wrapper"><div id="edit-feeds-FeedsXPathParser-attrs">',
+        '#suffix'        => '</div></div>',
+        '#process'       => array('ctools_dependent_process'),
+        '#dependency'    => array(
+          'radio:feeds[FeedsXPathParser][parser_type]' => array('QueryPath')
+        ),
+      );
+
+      foreach ($sources as $source) {
+        $form['sources'][$source] = array(
+          '#type'          => 'textfield',
+          '#title'         => $source,
+          '#description'   => t('The query string to run.'),
+          '#default_value' => isset($source_config['sources'][$source]) ? $source_config['sources'][$source] : '',
+        );
+
+        $form['attrs'][$source] = array(
+          '#type'          => 'textfield',
+          '#title'         => $source . ' Attribute',
+          '#description'   => t('The attribute to return.'),
+          '#default_value' => isset($source_config['attrs'][$source]) ? $source_config['attrs'][$source] : '',
+        );
+      }
+
+      $form['rawXML'] = array(
+        '#type'          => 'checkboxes',
+        '#title'         => t('Select the queries you would like to return raw XML or HTML'),
+        '#options'       => array_combine($sources, $sources),
+        '#process'       => array('ctools_dependent_process', 'expand_checkboxes'),
+        '#prefix'        => '<div id="edit-feeds-FeedsXPathParser-rawXML-wrapper"><div id="edit-feeds-FeedsXPathParser-rawXML">',
+        '#suffix'        => '</div></div>',
+        '#default_value' => isset($source_config['rawXML']) ? $source_config['rawXML'] : array(),
+        '#dependency'    => array(
+          'radio:feeds[FeedsXPathParser][parser_type]' => array(
+            'HTML', 'XML', 'QueryPath',
+          )
+        ),
       );
     }
 
-    $form['rawXML'] = array(
-      '#type'          => 'checkboxes',
-      '#title'         => t('Select the queries you would like to return raw XML or HTML'),
-      '#options'       => array_combine($sources, $sources),
-      '#process'       => array('ctools_dependent_process', 'expand_checkboxes'),
-      '#prefix'        => '<div id="edit-feeds-FeedsXPathParser-rawXML-wrapper"><div id="edit-feeds-FeedsXPathParser-rawXML">',
-      '#suffix'        => '</div></div>',
-      '#default_value' => isset($source_config['rawXML']) ? $source_config['rawXML'] : array(),
-      '#dependency'    => array(
-        'radio:feeds[FeedsXPathParser][parser_type]' => array(
-          'HTML', 'XML', 'QueryPath',
-        )
-      ),
-    );
-
     return $form;
   }
 
   /**
-  * Override parent::getMappingSources().
-  */
+   * Override parent::getMappingSources().
+   */
   public function getMappingSources() {
     return FALSE;
   }

=== modified file 'sites/all/modules/feeds_xpathparser/FeedsXPathParserHTML.inc'
--- FeedsXPathParserHTML.inc	2010-08-16 22:17:20 +0000
+++ FeedsXPathParserHTML.inc	2010-09-18 20:37:14 +0000
@@ -32,10 +32,13 @@
 
     foreach ($mappings as $mapping) {
       $source = $mapping['source'];
-      if ($query = trim($this->config['sources'][$source])) {
-       $this->sources[] = $source;
-       $this->queries[] = $query;
+      $this->sources[] = $source;
+      if (!($query = trim($this->config['sources'][$source]))) {
+        // No query defined: assume that there is a first-level attribute named
+        // $source in every item
+        $query = '//' . $source;
       }
+      $this->queries[] = $query;
     }
   }
 
@@ -48,16 +51,31 @@
       throw new Exception(t('There was an error with the XPath query: %query',
                             array('%query' => $this->sourceConfig['context'])));
     }
+    elseif (!$all_items) {
+      drupal_set_message(t("The XPath query: '%query' returned zero results", array('%query' => $this->sourceConfig['context'])), 'warning');
+    }
     unset($xml);
 
     $parsed_items = array();
-    foreach ($all_items as $item) {
-      $item = $item->asXML();
-      $parsed_item = array();
-      foreach ($this->sources as $source) {
-        $parsed_item[$source] = $this->getSourceElement($item, $source);
+    if (empty($this->sources)) {
+      // No mappings / sources defined.
+      // Assume we're after the source fieldnames only (in order to do mapping);
+      // get them from the first item.
+      // (Should we adjust the xpath query above to do extract only the first item?)
+
+      // Keys in $all_items are already OK (equal to the fieldnames);
+      // we don't care about the values.
+      return $all_items[0];
+    }
+    else {
+      foreach ($all_items as $item) {
+        $item = $item->asXML();
+        $parsed_item = array();
+        foreach ($this->sources as $source) {
+          $parsed_item[$source] = $this->getSourceElement($item, $source);
+        }
+        $parsed_items[] = $parsed_item;
       }
-      $parsed_items[] = $parsed_item;
     }
     return $parsed_items;
   }

