diff --git a/Classes/Command/TradosCommandController.php b/Classes/Command/TradosCommandController.php
index 924168f..f14d31c 100644
--- a/Classes/Command/TradosCommandController.php
+++ b/Classes/Command/TradosCommandController.php
@@ -23,6 +23,7 @@
  */
 class TradosCommandController extends CommandController
 {
+
     /**
      * @Flow\Inject
      * @var ExportService
@@ -40,25 +41,29 @@ class TradosCommandController extends CommandController
      *
      * This command exports a specific site including all content into an XML format.
      *
-     * @param string $startingPoint The node with which to start the export, relative to the site node. Optional.
+     * @param string $startingPoint The node with which to start the export: as identifier or the path relative to the site node.
      * @param string $sourceLanguage The language to use as base for the export.
-     * @param string $targetLanguage The target language for the translation, optional.
-     * @param string $filename Path and filename to the XML file to create.
-     * @param string $modifiedAfter
+     * @param string|null $targetLanguage The target language for the translation, optional.
+     * @param string|null $filename Path and filename to the XML file to create.
+     * @param string|null $modifiedAfter
      * @param boolean $ignoreHidden
+     * @param boolean $excludeChildDocuments
      * @return void
+     * @throws \Exception
      */
-    public function exportCommand($startingPoint, $sourceLanguage, $targetLanguage = null, $filename = null, $modifiedAfter = null, $ignoreHidden = true)
+    public function exportCommand(string $startingPoint, string $sourceLanguage, string $targetLanguage = null, string $filename = null, string $modifiedAfter = null, bool $ignoreHidden = true, bool $excludeChildDocuments = false)
     {
         if ($modifiedAfter !== null) {
             $modifiedAfter = new \DateTime($modifiedAfter);
         }
 
+        $this->exportService->initialize($startingPoint, $sourceLanguage, $targetLanguage, $modifiedAfter, $ignoreHidden, $excludeChildDocuments);
+
         try {
             if ($filename === null) {
-                $this->output($this->exportService->exportToString($startingPoint, $sourceLanguage, $targetLanguage, $modifiedAfter, $ignoreHidden));
+                $this->output($this->exportService->exportToString());
             } else {
-                $this->exportService->exportToFile($filename, $startingPoint, $sourceLanguage, $targetLanguage, $modifiedAfter, $ignoreHidden);
+                $this->exportService->exportToFile($filename);
                 $this->outputLine('<success>The tree starting at "/sites/%s" has been exported to "%s".</success>', [$startingPoint, $filename]);
             }
         } catch (\Exception $exception) {
@@ -73,10 +78,10 @@ public function exportCommand($startingPoint, $sourceLanguage, $targetLanguage =
      * This command imports translated content from XML.
      *
      * @param string $filename Path and filename to the XML file to import.
-     * @param string $targetLanguage The target language for the translation, optional if included in XML.
+     * @param string|null $targetLanguage The target language for the translation, optional if included in XML.
      * @param string $workspace A workspace to import into, optional but recommended
      */
-    public function importCommand($filename, $targetLanguage = null, $workspace = 'live')
+    public function importCommand(string $filename, string $targetLanguage = null, string $workspace = 'live')
     {
         try {
             $importedLanguage = $this->importService->importFromFile($filename, $workspace, $targetLanguage);
diff --git a/Classes/Service/AbstractService.php b/Classes/Service/AbstractService.php
new file mode 100644
index 0000000..350910d
--- /dev/null
+++ b/Classes/Service/AbstractService.php
@@ -0,0 +1,52 @@
+<?php
+namespace Flownative\Neos\Trados\Service;
+
+/*
+ * This file is part of the Flownative.Neos.Trados package.
+ *
+ * (c) Flownative GmbH - https://www.flownative.com/
+ *
+ * This package is Open Source Software. For the full copyright and license
+ * information, please view the LICENSE file which was distributed with this
+ * source code.
+ */
+
+use Neos\Flow\Annotations as Flow;
+
+class AbstractService
+{
+    /**
+     * @var string
+     */
+    const SUPPORTED_FORMAT_VERSION = '1.0';
+
+    /**
+     * @Flow\InjectConfiguration(path = "languageDimension")
+     * @var string
+     */
+    protected $languageDimension;
+
+    /**
+     * @Flow\Inject
+     * @var \Neos\Neos\Domain\Service\ContentContextFactory
+     */
+    protected $contentContextFactory;
+
+    /**
+     * @Flow\Inject
+     * @var \Neos\Flow\Security\Context
+     */
+    protected $securityContext;
+
+    /**
+     * @Flow\Inject
+     * @var \Neos\Neos\Domain\Repository\SiteRepository
+     */
+    protected $siteRepository;
+
+    /**
+     * @Flow\Inject
+     * @var \Neos\ContentRepository\Domain\Repository\WorkspaceRepository
+     */
+    protected $workspaceRepository;
+}
diff --git a/Classes/Service/ExportService.php b/Classes/Service/ExportService.php
index 244ac50..2eeecca 100644
--- a/Classes/Service/ExportService.php
+++ b/Classes/Service/ExportService.php
@@ -13,8 +13,8 @@
 
 use Neos\ContentRepository\Domain\Model\NodeData;
 use Neos\ContentRepository\Domain\Model\NodeInterface;
-use Neos\ContentRepository\Domain\Service\ContextFactoryInterface;
-use Neos\ContentRepository\Domain\Utility\NodePaths;
+use Neos\ContentRepository\Domain\Model\Workspace;
+use Neos\ContentRepository\Domain\Repository\NodeDataRepository;
 use Neos\Flow\Annotations as Flow;
 use Neos\Neos\Domain\Model\Site;
 use Neos\Neos\Domain\Service\ContentContext;
@@ -24,18 +24,19 @@
  *
  * @Flow\Scope("singleton")
  */
-class ExportService
+class ExportService extends AbstractService
 {
     /**
+     * @Flow\InjectConfiguration(path = "export.workspace")
      * @var string
      */
-    const SUPPORTED_FORMAT_VERSION = '1.0';
+    protected string $workspaceName;
 
     /**
-     * @Flow\InjectConfiguration(path = "languageDimension")
+     * @Flow\InjectConfiguration(path = "export.documentTypeFilter")
      * @var string
      */
-    protected $languageDimension;
+    protected string $documentTypeFilter;
 
     /**
      * The XMLWriter that is used to construct the export.
@@ -46,66 +47,141 @@ class ExportService
 
     /**
      * @Flow\Inject
-     * @var ContextFactoryInterface
+     * @var \Neos\ContentRepository\Domain\Service\NodeTypeManager
      */
-    protected $contextFactory;
+    protected $nodeTypeManager;
 
     /**
-     * Doctrine's Entity Manager. Note that "ObjectManager" is the name of the related
-     * interface ...
-     *
      * @Flow\Inject
-     * @var \Doctrine\Common\Persistence\ObjectManager
+     * @var NodeDataRepository
      */
-    protected $entityManager;
+    protected $nodeDataRepository;
 
     /**
      * @Flow\Inject
-     * @var \Neos\ContentRepository\Domain\Service\NodeTypeManager
+     * @var \Neos\ContentRepository\Domain\Service\ContentDimensionCombinator
      */
-    protected $nodeTypeManager;
+    protected $contentDimensionCombinator;
 
     /**
-     * @Flow\Inject
-     * @var \Neos\Neos\Domain\Repository\SiteRepository
+     * @var ContentContext
+     *
      */
-    protected $siteRepository;
+    protected ContentContext $contentContext;
 
     /**
-     * @Flow\Inject
-     * @var \Neos\ContentRepository\Domain\Repository\NodeDataRepository
+     * @var string
      */
-    protected $nodeDataRepository;
+    protected string $startingPoint;
 
     /**
-     * @Flow\Inject
-     * @var \Neos\Flow\Security\Context
+     * @var NodeInterface
      */
-    protected $securityContext;
+    protected NodeInterface $startingPointNode;
 
     /**
-     * @Flow\Inject
-     * @var \Neos\ContentRepository\Domain\Service\ContentDimensionCombinator
+     * @var Site
      */
-    protected $contentDimensionCombinator;
+    protected Site $site;
+
+    /**
+     * @var string
+     */
+    protected string $sourceLanguage;
+
+    /**
+     * @var string|null
+     */
+    protected ?string $targetLanguage;
+
+    /**
+     * @var \DateTime|null
+     */
+    protected ?\DateTime $modifiedAfter;
+
+    /**
+     * @var bool
+     */
+    protected bool $ignoreHidden;
+
+    /**
+     * @var bool
+     */
+    protected bool $excludeChildDocuments;
+
+    /**
+     * @var int
+     */
+    protected int $depth;
 
     /**
-     * Fetches the site with the given name and exports it into XML.
-     *
      * @param string $startingPoint
      * @param string $sourceLanguage
-     * @param string $targetLanguage
-     * @param \DateTime $modifiedAfter
-     * @param boolean $ignoreHidden
+     * @param string|null $targetLanguage
+     * @param \DateTime|null $modifiedAfter
+     * @param bool $ignoreHidden
+     * @param string $documentTypeFilter
+     * @param int $depth
+     */
+    public function initialize(
+        string $startingPoint,
+        string $sourceLanguage,
+        string $targetLanguage = null,
+        \DateTime $modifiedAfter = null,
+        bool $ignoreHidden = true,
+        bool $excludeChildDocuments = false,
+        string $documentTypeFilter = 'Neos.Neos:Document',
+        int $depth = 0
+    ) {
+        $this->startingPoint = $startingPoint;
+        $this->sourceLanguage = $sourceLanguage;
+        $this->targetLanguage = $targetLanguage;
+        $this->modifiedAfter = $modifiedAfter;
+        $this->ignoreHidden = $ignoreHidden;
+        $this->excludeChildDocuments = $excludeChildDocuments;
+        $this->documentTypeFilter = $documentTypeFilter;
+        $this->depth = $depth;
+
+        /** @var ContentContext $contentContext */
+        $contentContext = $this->contentContextFactory->create([
+            'workspaceName' => $this->workspaceName,
+            'invisibleContentShown' => !$this->ignoreHidden,
+            'removedContentShown' => false,
+            'inaccessibleContentShown' => !$this->ignoreHidden,
+            'dimensions' => current($this->getAllowedContentCombinationsForSourceLanguage($this->sourceLanguage))
+        ]);
+        $this->contentContext = $contentContext;
+
+        $startingPointNode = $this->contentContext->getNodeByIdentifier($startingPoint);
+        if ($startingPointNode === null) {
+            $startingPointNode = $this->contentContext->getNode('/sites/' . $this->startingPoint);
+            if ($startingPointNode === null) {
+                throw new \RuntimeException(sprintf('Could not find node "%s"', $this->startingPoint), 1473241812);
+            }
+        }
+
+        $this->startingPointNode = $startingPointNode;
+        $pathArray = explode('/', $this->startingPointNode->findNodePath());
+        $this->site = $this->siteRepository->findOneByNodeName($pathArray[2]);
+
+        if ($this->workspaceRepository->findOneByName($this->workspaceName) === null) {
+            throw new \RuntimeException(sprintf('Could not find workspace "%s"', $this->workspaceName), 14732418113);
+        }
+    }
+
+    /**
+     * Fetches the site with the given name and exports it into XML.
+     *
      * @return string
+     * @throws \Exception
      */
-    public function exportToString($startingPoint, $sourceLanguage, $targetLanguage = null, \DateTime $modifiedAfter = null, $ignoreHidden = true)
+    public function exportToString(): string
     {
         $this->xmlWriter = new \XMLWriter();
         $this->xmlWriter->openMemory();
         $this->xmlWriter->setIndent(true);
 
-        $this->export($startingPoint, $sourceLanguage, $targetLanguage, $modifiedAfter, 'live', $ignoreHidden);
+        $this->exportToXmlWriter();
 
         return $this->xmlWriter->outputMemory(true);
     }
@@ -114,20 +190,16 @@ public function exportToString($startingPoint, $sourceLanguage, $targetLanguage
      * Export into the given file.
      *
      * @param string $pathAndFilename Path to where the export output should be saved to
-     * @param string $startingPoint
-     * @param string $sourceLanguage
-     * @param string $targetLanguage
-     * @param \DateTime $modifiedAfter
-     * @param boolean $ignoreHidden
      * @return void
+     * @throws \Exception
      */
-    public function exportToFile($pathAndFilename, $startingPoint, $sourceLanguage, $targetLanguage = null, \DateTime $modifiedAfter = null, $ignoreHidden = true)
+    public function exportToFile(string $pathAndFilename)
     {
         $this->xmlWriter = new \XMLWriter();
         $this->xmlWriter->openUri($pathAndFilename);
         $this->xmlWriter->setIndent(true);
 
-        $this->export($startingPoint, $sourceLanguage, $targetLanguage, $modifiedAfter, 'live', $ignoreHidden);
+        $this->exportToXmlWriter();
 
         $this->xmlWriter->flush();
     }
@@ -135,48 +207,28 @@ public function exportToFile($pathAndFilename, $startingPoint, $sourceLanguage,
     /**
      * Export to the XMLWriter.
      *
-     * @param string $startingPoint
-     * @param string $sourceLanguage
-     * @param string $targetLanguage
-     * @param \DateTime $modifiedAfter
-     * @param string $workspaceName
-     * @param boolean $ignoreHidden
      * @return void
+     * @throws \Exception
      */
-    protected function export($startingPoint, $sourceLanguage, $targetLanguage = null, \DateTime $modifiedAfter = null, $workspaceName = 'live', $ignoreHidden = true)
+    protected function exportToXmlWriter()
     {
-        $siteNodeName = current(explode('/', $startingPoint));
-        /** @var Site $site */
-        $site = $this->siteRepository->findOneByNodeName($siteNodeName);
-        if ($site === null) {
-            throw new \RuntimeException(sprintf('No site found for node name "%s"', $siteNodeName), 1473241812);
-        }
-
-        /** @var ContentContext $contentContext */
-        $contentContext = $this->contextFactory->create([
-            'workspaceName' => $workspaceName,
-            'currentSite' => $site,
-            'invisibleContentShown' => !$ignoreHidden,
-            'removedContentShown' => false,
-            'inaccessibleContentShown' => !$ignoreHidden,
-            'dimensions' => current($this->getAllowedContentCombinationsForSourceLanguage($sourceLanguage))
-        ]);
-
         $this->xmlWriter->startDocument('1.0', 'UTF-8');
         $this->xmlWriter->startElement('content');
 
-        $this->xmlWriter->writeAttribute('name', $site->getName());
-        $this->xmlWriter->writeAttribute('sitePackageKey', $site->getSiteResourcesPackageKey());
-        $this->xmlWriter->writeAttribute('workspace', $workspaceName);
-        $this->xmlWriter->writeAttribute('sourceLanguage', $sourceLanguage);
-        if ($targetLanguage !== null) {
-            $this->xmlWriter->writeAttribute('targetLanguage', $targetLanguage);
+        $this->xmlWriter->writeAttribute('name', $this->site->getName());
+        $this->xmlWriter->writeAttribute('sitePackageKey', $this->site->getSiteResourcesPackageKey());
+        $this->xmlWriter->writeAttribute('workspace', $this->workspaceName);
+        $this->xmlWriter->writeAttribute('sourceLanguage', $this->sourceLanguage);
+        if ($this->targetLanguage !== null) {
+            $this->xmlWriter->writeAttribute('targetLanguage', $this->targetLanguage);
         }
-        if ($modifiedAfter !== null) {
-            $this->xmlWriter->writeAttribute('modifiedAfter', $targetLanguage);
+        if ($this->modifiedAfter !== null) {
+            $this->xmlWriter->writeAttribute('modifiedAfter', $this->modifiedAfter->format('c'));
         }
 
-        $this->exportNodes('/sites/' . $startingPoint, $contentContext, $sourceLanguage, $targetLanguage, $modifiedAfter);
+        $this->xmlWriter->startElement('nodes');
+        $this->exportNodes($this->startingPointNode->findNodePath(), $this->contentContext);
+        $this->xmlWriter->endElement(); // nodes
 
         $this->xmlWriter->endElement();
         $this->xmlWriter->endDocument();
@@ -188,15 +240,13 @@ protected function export($startingPoint, $sourceLanguage, $targetLanguage = nul
      *
      * @param string $startingPointNodePath path to the root node of the sub-tree to export. The specified node will not be included, only its sub nodes.
      * @param ContentContext $contentContext
-     * @param string $sourceLanguage
-     * @param string $targetLanguage
-     * @param \DateTime $modifiedAfter
      * @return void
+     * @throws \Exception
      */
-    public function exportNodes($startingPointNodePath, ContentContext $contentContext, $sourceLanguage, $targetLanguage = null, \DateTime $modifiedAfter = null)
+    protected function exportNodes(string $startingPointNodePath, ContentContext $contentContext)
     {
-        $this->securityContext->withoutAuthorizationChecks(function () use ($startingPointNodePath, $contentContext, $sourceLanguage, $targetLanguage, $modifiedAfter) {
-            $nodeDataList = $this->findNodeDataListToExport($startingPointNodePath, $contentContext, $sourceLanguage, $targetLanguage, $modifiedAfter);
+        $this->securityContext->withoutAuthorizationChecks(function () use ($startingPointNodePath, $contentContext) {
+            $nodeDataList = $this->findNodeDataListToExport($startingPointNodePath, $contentContext);
             $this->exportNodeDataList($nodeDataList);
         });
     }
@@ -207,25 +257,30 @@ public function exportNodes($startingPointNodePath, ContentContext $contentConte
      *
      * @param string $pathStartingPoint Absolute path specifying the starting point
      * @param ContentContext $contentContext
-     * @param string $sourceLanguage
-     * @param string $targetLanguage
-     * @param \DateTime $modifiedAfter
      * @return array<NodeData>
+     * @throws \Neos\Flow\Persistence\Exception\IllegalObjectTypeException
      */
-    protected function findNodeDataListToExport($pathStartingPoint, ContentContext $contentContext, $sourceLanguage, $targetLanguage = null, \DateTime $modifiedAfter = null)
+    protected function findNodeDataListToExport(string $pathStartingPoint, ContentContext $contentContext): array
     {
-        $allowedContentCombinations = $this->getAllowedContentCombinationsForSourceLanguage($sourceLanguage);
+        $allowedContentCombinations = $this->getAllowedContentCombinationsForSourceLanguage($this->sourceLanguage);
         $sourceContexts = [];
 
         /** @var NodeData[] $nodeDataList */
         $nodeDataList = [];
         foreach ($allowedContentCombinations as $contentDimensions) {
+            // If exclude-child-documents argument is set to true, only add content child nodes to nodeDataList (recursively), don't descend into document child nodes.
+            if ($this->excludeChildDocuments === true) {
+                $node = $contentContext->getNode($pathStartingPoint)->getNodeData();
+                $childNodes = $this->getChildNodeDataOnPage($node, $contentContext->getWorkspace(), $contentDimensions, $contentContext->isRemovedContentShown());
+            } else {
+                $childNodes = $this->nodeDataRepository->findByParentAndNodeType($pathStartingPoint, null, $contentContext->getWorkspace(), $contentDimensions, $contentContext->isRemovedContentShown() ? null : false, true);
+            }
             $nodeDataList = array_merge(
                 $nodeDataList,
                 [$contentContext->getNode($pathStartingPoint)->getNodeData()],
-                $this->nodeDataRepository->findByParentAndNodeType($pathStartingPoint, null, $contentContext->getWorkspace(), $contentDimensions, $contentContext->isRemovedContentShown() ? null : false, true)
+                $childNodes
             );
-            $sourceContexts[] = $this->contextFactory->create([
+            $sourceContexts[] = $this->contentContextFactory->create([
                 'invisibleContentShown' => $contentContext->isInvisibleContentShown(),
                 'removedContentShown' => false,
                 'inaccessibleContentShown' => $contentContext->isInaccessibleContentShown(),
@@ -234,11 +289,11 @@ protected function findNodeDataListToExport($pathStartingPoint, ContentContext $
         }
 
         $uniqueNodeDataList = [];
-        usort($nodeDataList, function (NodeData $node1, NodeData $node2) use ($sourceLanguage) {
-            if ($node1->getDimensionValues()[$this->languageDimension][0] === $sourceLanguage) {
+        usort($nodeDataList, function (NodeData $node1, NodeData $node2) {
+            if ($node1->getDimensionValues()[$this->languageDimension][0] === $this->sourceLanguage) {
                 return 1;
             }
-            if ($node2->getDimensionValues()[$this->languageDimension][0] === $sourceLanguage) {
+            if ($node2->getDimensionValues()[$this->languageDimension][0] === $this->sourceLanguage) {
                 return -1;
             }
 
@@ -247,13 +302,13 @@ protected function findNodeDataListToExport($pathStartingPoint, ContentContext $
         foreach ($nodeDataList as $nodeData) {
             $uniqueNodeDataList[$nodeData->getIdentifier()] = $nodeData;
         }
-        $nodeDataList = array_filter(array_values($uniqueNodeDataList), function (NodeData $nodeData) use ($sourceContexts, $sourceLanguage) {
+        $nodeDataList = array_filter(array_values($uniqueNodeDataList), function (NodeData $nodeData) use ($sourceContexts) {
             /** @var ContentContext $sourceContext */
             foreach ($sourceContexts as $sourceContext) {
-                if ($sourceContext->getDimensions()[$this->languageDimension][0] !== $sourceLanguage) {
+                if ($sourceContext->getDimensions()[$this->languageDimension][0] !== $this->sourceLanguage) {
                     continue;
                 }
-                if ($nodeData->getDimensionValues()[$this->languageDimension][0] !== $sourceLanguage) {
+                if ($nodeData->getDimensionValues()[$this->languageDimension][0] !== $this->sourceLanguage) {
                     // "reload" nodedata in correct dimension
                     $node = $sourceContext->getNodeByIdentifier($nodeData->getIdentifier());
                     if ($node === null || $node->getNodeData() === null) {
@@ -302,28 +357,27 @@ function (NodeData $node1, NodeData $node2) {
      *
      * @param array<NodeData> $nodeDataList The nodes to export
      * @return void The result is written directly into $this->xmlWriter
+     * @throws \Neos\ContentRepository\Exception\NodeTypeNotFoundException
      */
     protected function exportNodeDataList(array &$nodeDataList)
     {
-        $this->xmlWriter->startElement('nodes');
         $this->xmlWriter->writeAttribute('formatVersion', self::SUPPORTED_FORMAT_VERSION);
 
         $currentNodeDataIdentifier = null;
         foreach ($nodeDataList as $nodeData) {
             $this->writeNode($nodeData, $currentNodeDataIdentifier);
         }
-
-        $this->xmlWriter->endElement();
     }
 
     /**
      * Write a single node into the XML structure
      *
      * @param NodeData $nodeData The node data
-     * @param string $currentNodeDataIdentifier The "current" node, as passed by exportNodeDataList()
+     * @param string|null $currentNodeDataIdentifier The "current" node, as passed by exportNodeDataList()
      * @return void The result is written directly into $this->xmlWriter
+     * @throws \Neos\ContentRepository\Exception\NodeTypeNotFoundException
      */
-    protected function writeNode(NodeData $nodeData, &$currentNodeDataIdentifier)
+    protected function writeNode(NodeData $nodeData, ?string &$currentNodeDataIdentifier)
     {
         $nodeName = $nodeData->getName();
 
@@ -349,6 +403,7 @@ protected function writeNode(NodeData $nodeData, &$currentNodeDataIdentifier)
      *
      * @param NodeData $nodeData
      * @return void
+     * @throws \Neos\ContentRepository\Exception\NodeTypeNotFoundException
      */
     protected function writeVariant(NodeData $nodeData)
     {
@@ -383,6 +438,7 @@ protected function writeDimensions(NodeData $nodeData)
      *
      * @param NodeData $nodeData
      * @return void
+     * @throws \Neos\ContentRepository\Exception\NodeTypeNotFoundException
      */
     protected function writeProperties(NodeData $nodeData)
     {
@@ -411,7 +467,7 @@ protected function writeProperties(NodeData $nodeData)
      * @param string $propertyName The name of the property
      * @param string $propertyValue The value of the property
      */
-    protected function writeProperty($propertyName, $propertyValue)
+    protected function writeProperty(string $propertyName, string $propertyValue)
     {
         $this->xmlWriter->startElement($propertyName);
         $this->xmlWriter->writeAttribute('type', 'string');
@@ -431,4 +487,52 @@ protected function getAllowedContentCombinationsForSourceLanguage(string $source
             return (isset($combination[$this->languageDimension]) && $combination[$this->languageDimension][0] === $sourceLanguage);
         });
     }
+
+    /**
+     * Find all content nodes under the given node.
+     *
+     * @param NodeData $node
+     * @param Workspace $workspace
+     * @param array $contentDimensions
+     * @param boolean $isRemovedContentShown
+     * @return array
+     */
+    private function getChildNodeDataOnPage(NodeData $node, Workspace $workspace, array $contentDimensions, bool $isRemovedContentShown): array
+    {
+        $results = [];
+        // We traverse through all Content (=!Document) nodes underneath the start node here and add it to the result list.
+        // NOTE: The $results list is passed into the callback by reference, so that we can modify it in-place.
+        $this->traverseRecursively($node, '!Neos.Neos:Document', $workspace, $contentDimensions, $isRemovedContentShown, function($node) use (&$results) {
+            $results[] = $node;
+        });
+        return $results;
+    }
+
+    /**
+     * This function recursively traverses all nodes underneath $node which match $nodeTypeFilter; and calls
+     * $callback on each of them (Depth-First Traversal).
+     *
+     * You have to watch out yourself to not build very deep nesting; so we suggest to use a node type filter
+     * like "!Neos.Neos:Document" or "Neos.Neos:ContentCollection, Neos.Neos:Content" which matches only content.
+     *
+     * For reference how the Node Type filter works, see:
+     *
+     * - NodeDataRepository::addNodeTypeFilterConstraintsToQueryBuilder
+     * - NodeDataRepository::getNodeTypeFilterConstraintsForDql
+     *
+     * @param NodeData $node
+     * @param string $nodeTypeFilter
+     * @param Workspace $workspace
+     * @param array $contentDimensions
+     * @param boolean $isRemovedContentShown
+     * @param \Closure $callback
+     */
+    private function traverseRecursively(NodeData $node, string $nodeTypeFilter, Workspace $workspace, array $contentDimensions, bool $isRemovedContentShown, \Closure $callback)
+    {
+        $callback($node);
+        $childNodes = $this->nodeDataRepository->findByParentAndNodeType($node->getPath(), $nodeTypeFilter, $workspace, $contentDimensions, $isRemovedContentShown ? null : false, false);
+        foreach ($childNodes as $childNode) {
+            $this->traverseRecursively($childNode, $nodeTypeFilter, $workspace, $contentDimensions, $isRemovedContentShown, $callback);
+        }
+    }
 }
diff --git a/Classes/Service/ImportService.php b/Classes/Service/ImportService.php
index 9645a76..a96b891 100644
--- a/Classes/Service/ImportService.php
+++ b/Classes/Service/ImportService.php
@@ -22,22 +22,11 @@
  *
  * @Flow\Scope("singleton")
  */
-class ImportService
+class ImportService extends AbstractService
 {
-    /**
-     * @var string
-     */
-    const SUPPORTED_FORMAT_VERSION = '1.0';
-
-    /**
-     * @Flow\InjectConfiguration(path = "languageDimension")
-     * @var string
-     */
-    protected $languageDimension;
-
     /**
      * @Flow\Inject
-     * @var \Neos\Flow\Package\PackageManagerInterface
+     * @var \Neos\Flow\Package\PackageManager
      */
     protected $packageManager;
 
@@ -47,30 +36,6 @@ class ImportService
      */
     protected $persistenceManager;
 
-    /**
-     * @Flow\Inject
-     * @var \Neos\Neos\Domain\Repository\SiteRepository
-     */
-    protected $siteRepository;
-
-    /**
-     * @Flow\Inject
-     * @var \Neos\ContentRepository\Domain\Repository\WorkspaceRepository
-     */
-    protected $workspaceRepository;
-
-    /**
-     * @Flow\Inject
-     * @var \Neos\Neos\Domain\Service\ContentContextFactory
-     */
-    protected $contentContextFactory;
-
-    /**
-     * @Flow\Inject
-     * @var \Neos\Flow\Security\Context
-     */
-    protected $securityContext;
-
     /**
      * @Flow\Inject
      * @var \Neos\Neos\Domain\Service\ContentDimensionPresetSourceInterface
@@ -107,11 +72,6 @@ class ImportService
      */
     protected $targetWorkspace;
 
-    /**
-     * @var string
-     */
-    protected $sourceWorkspaceName;
-
     /**
      * @var string
      */
@@ -136,13 +96,13 @@ class ImportService
      *
      *
      * @param string $pathAndFilename
-     * @param string $workspaceName
-     * @param string $targetLanguage
+     * @param string|null $workspaceName
+     * @param string|null $targetLanguage
      * @return string
      * @throws InvalidPackageStateException
      * @throws UnknownPackageException
      */
-    public function importFromFile($pathAndFilename, $workspaceName = null, $targetLanguage = null)
+    public function importFromFile(string $pathAndFilename, string $workspaceName = null, string $targetLanguage = null): string
     {
         /** @var \Neos\Neos\Domain\Model\Site $importedSite */
         $site = null;
@@ -162,7 +122,7 @@ public function importFromFile($pathAndFilename, $workspaceName = null, $targetL
                 throw new \RuntimeException('No target language given (neither in XML nor as argument)', 1475578770);
             }
 
-            $this->languageDimensionPreset = $this->contentDimensionPresetSource->findPresetByDimensionValues($this->languageDimension, [$this->targetLanguage]);
+            $this->languageDimensionPreset = $this->contentDimensionPresetSource->findPresetsByTargetValues([$this->languageDimension => [$this->targetLanguage]]);
 
             if ($this->languageDimensionPreset === null) {
                 throw new \RuntimeException(sprintf('No language dimension preset found for language "%s".', $this->targetLanguage), 1571230670);
@@ -274,7 +234,6 @@ protected function parseElement(\XMLReader $xmlReader)
             break;
             default:
                 throw new \Exception(sprintf('Unexpected element <%s> ', $elementName), 1423578065);
-            break;
         }
     }
 
@@ -296,7 +255,6 @@ protected function parseEndElement(\XMLReader $reader)
             break;
             default:
                 throw new \Exception(sprintf('Unexpected end element <%s> ', $reader->name), 1423578066);
-            break;
         }
     }
 
@@ -307,7 +265,7 @@ protected function parseEndElement(\XMLReader $reader)
      * @param \XMLReader $reader reader positioned just after an opening dimensions-tag
      * @return array the dimension values
      */
-    protected function parseDimensionsElement(\XMLReader $reader)
+    protected function parseDimensionsElement(\XMLReader $reader): array
     {
         $dimensions = [];
         $currentDimension = null;
@@ -340,7 +298,7 @@ protected function parseDimensionsElement(\XMLReader $reader)
      * @return array the properties
      * @throws \Exception
      */
-    protected function parsePropertiesElement(\XMLReader $reader)
+    protected function parsePropertiesElement(\XMLReader $reader): array
     {
         $properties = [];
         $currentProperty = null;
@@ -398,7 +356,7 @@ protected function persistNodeData(array $translatedData)
             return $carry;
         });
 
-        $dimensions = array_merge($translatedData['dimensionValues'], [$this->languageDimension => $this->languageDimensionPreset['values']]);
+        $dimensions = array_merge($translatedData['dimensionValues'], [$this->languageDimension => $this->languageDimensionPreset[$this->languageDimension]['values']]);
         $targetDimensions = array_map(
             function ($values) {
                 return current($values);
diff --git a/Configuration/Settings.yaml b/Configuration/Settings.yaml
index 88fcac6..19e0cdf 100644
--- a/Configuration/Settings.yaml
+++ b/Configuration/Settings.yaml
@@ -2,3 +2,6 @@ Flownative:
   Neos:
     Trados:
       languageDimension: 'language'
+      export:
+        workspace: 'live'
+        documentTypeFilter: 'Neos.Neos:Document'
diff --git a/README.md b/README.md
index 52fbae1..bb0ef67 100644
--- a/README.md
+++ b/README.md
@@ -26,14 +26,15 @@ The export command:
       ./flow trados:export [<options>] <starting point> <source language>
     
     ARGUMENTS:
-      --starting-point     The node with which to start the export, relative to the
-                           site node. Optional.
-      --source-language    The language to use as base for the export.
+      --starting-point              The node with which to start the export, relative to the
+                                    site node. Optional.
+      --source-language             The language to use as base for the export.
     
     OPTIONS:
-      --target-language    The target language for the translation, optional.
-      --filename           Path and filename to the XML file to create.
+      --target-language             The target language for the translation, optional.
+      --filename                    Path and filename to the XML file to create.
       --modified-after
+      --exclude-child-documents     If child documents should not be included in the export.
 
 The import command:
 
diff --git a/composer.json b/composer.json
index 76af44f..649a79a 100644
--- a/composer.json
+++ b/composer.json
@@ -4,7 +4,10 @@
     "license": "MIT",
     "description": "XML import/export for Neos, suited for Trados translations",
     "require": {
-        "neos/neos": "~3.0 || ^4.0 || ^5.0"
+        "neos/neos": "^4.3 || ^5.0 || ^7.0",
+        "php": "^7.4 || ^8.0",
+        "ext-xmlwriter": "*",
+        "ext-xmlreader": "*"
     },
     "autoload": {
         "psr-4": {