protected function exportNodes($oids) {
    // Export starts from root oids and iterates over all children.
    // On every call we have to decide what to do:
    // - If there is an iterator stored in the session we are inside a tree and continue iterating (_NODES_PER_CALL nodes)
    //   until the iterator finishes
    // - If the oids array holds one value!=null this is assumed to be an root oid and a new iterator is constructed
    // - If there is no iterator and no oid given, we return

    $session = $this->getSession();
    $persistenceFacade = $this->getPersistenceFacade();
    $message = $this->getMessage();

    // get document definition
    $docFile = $this->getDownloadFile();
    $nodesPerCall = $this->getRequestValue('nodesPerCall');
    $cacheSection = $this->getRequestValue('cacheSection');

    // check for iterator in session
    $iterator = PersistentIterator::load($this->ITERATOR_ID_VAR, $persistenceFacade, $session);
    // no iterator but oid given, start with new root oid
    if ($iterator == null && sizeof($oids) > 0 && $oids[0] != null) {
      $iterator = new PersistentIterator($this->ITERATOR_ID_VAR, $persistenceFacade, $session, $oids[0]);
    }
    // no iterator, no oid, finish
    if ($iterator == null) {
      $this->addWorkPackage($message->getText('Finish'), 1, [null], 'finishExport');
      return;
    }

    // process nodes
    $fileHandle = fopen($docFile, "a");
    $counter = 0;
    while ($iterator->valid() && $counter < $nodesPerCall) {
      // write node
      $this->writeNode($fileHandle, $iterator->current(), $iterator->key()+1);
      $iterator->next();
      $counter++;
    }
    $this->endTags($fileHandle, 0);
    fclose($fileHandle);

    // decide what to do next
    $rootOIDs = $this->cache->get($cacheSection, self::CACHE_KEY_ROOT_OIDS);
    if (!$iterator->valid() && sizeof($rootOIDs) > 0) {
      // if the current iterator is finished, reset the iterator and proceed with the next root oid
      $nextOID = array_shift($rootOIDs);
      // store remaining root oids in the cache
      $this->cache->put($cacheSection, self::CACHE_KEY_ROOT_OIDS, $rootOIDs);
      // delete iterator to start with new root oid
      PersistentIterator::reset($this->ITERATOR_ID_VAR, $session);

      $name = $message->getText('Exporting tree: start with %0%', [$nextOID]);
      $this->addWorkPackage($name, 1, [$nextOID], 'exportNodes');
    }
    elseif ($iterator->valid()) {
      // proceed with current iterator
      $iterator->save();

      $name = $message->getText('Exporting tree: continue with %0%', [$iterator->current()]);
      $this->addWorkPackage($name, 1, [null], 'exportNodes');
    }
    else {
      // finish
      $this->addWorkPackage($message->getText('Finish'), 1, [null], 'finishExport');
    }
  }