diff --git a/Filters/General/Testing/CMakeLists.txt b/Filters/General/Testing/CMakeLists.txt
index 472dd2206221efa4d6d7fc8919755a19764dde7f..d2a50043f203da9ffe67a53aeaf00c6a7d8f3349 100644
--- a/Filters/General/Testing/CMakeLists.txt
+++ b/Filters/General/Testing/CMakeLists.txt
@@ -8,9 +8,11 @@ vtk_module_test_data(
   Data/2DScalar.vti
   Data/can.vtu
   Data/cow.vtp
+  Data/distTest.vtm
   Data/explicitStructuredGrid.vtu
   Data/fullhead15.png
   Data/hexa.vtk
+  Data/mb-of-mps.vtm
   Data/mine_with_dates.vtp
   Data/quadraticTetra01.vtu
   Data/rectGrid.vtr
diff --git a/Filters/General/Testing/Cxx/TestAxisAlignedReflectionFilter.cxx b/Filters/General/Testing/Cxx/TestAxisAlignedReflectionFilter.cxx
index fb39ef1403eb5e9992ef6cbfba81667b4dd1f2d5..bacda5b883e30820c3c3f620f21ad3924f45dfd0 100644
--- a/Filters/General/Testing/Cxx/TestAxisAlignedReflectionFilter.cxx
+++ b/Filters/General/Testing/Cxx/TestAxisAlignedReflectionFilter.cxx
@@ -1,6 +1,8 @@
 // SPDX-FileCopyrightText: Copyright (c) Kitware Inc.
 // SPDX-License-Identifier: BSD-3-Clause
 
+#include <vtkXMLMultiBlockDataReader.h>
+
 #include "vtkAxisAlignedReflectionFilter.h"
 #include "vtkCellData.h"
 #include "vtkDataAssembly.h"
@@ -281,7 +283,7 @@ int TestHyperTreeGrid(int argc, char* argv[])
   return EXIT_SUCCESS;
 }
 
-int TestCompositeData(int argc, char* argv[])
+int TestPartitionedDataSetCollection(int argc, char* argv[])
 {
   ReadFileMacro("Data/sphereMirror.vtpc", vtkXMLPartitionedDataSetCollectionReader);
 
@@ -302,25 +304,14 @@ int TestCompositeData(int argc, char* argv[])
   AssertMacro(strcmp(assembly->GetNodeName(reflectionId), "Reflection") == 0,
     output->GetClassName(), "Incorrect assembly");
 
-  int inputCompositeId = assembly->GetChild(inputId, 0);
-  int reflectionCompositeId = assembly->GetChild(reflectionId, 0);
-  AssertMacro(strcmp(assembly->GetNodeName(inputCompositeId), "Composite") == 0,
-    output->GetClassName(), "Incorrect assembly");
-  AssertMacro(strcmp(assembly->GetNodeName(reflectionCompositeId), "Composite") == 0,
-    output->GetClassName(), "Incorrect assembly");
-
-  AssertMacro(
-    strcmp(assembly->GetNodeName(assembly->GetChild(inputCompositeId, 0)), "Input_Input") == 0,
+  AssertMacro(strcmp(assembly->GetNodeName(assembly->GetChild(inputId, 0)), "Input") == 0,
     output->GetClassName(), "Incorrect assembly");
-  AssertMacro(
-    strcmp(assembly->GetNodeName(assembly->GetChild(inputCompositeId, 1)), "Input_Reflection") == 0,
+  AssertMacro(strcmp(assembly->GetNodeName(assembly->GetChild(inputId, 1)), "Reflection") == 0,
     output->GetClassName(), "Incorrect assembly");
 
-  AssertMacro(
-    strcmp(assembly->GetNodeName(assembly->GetChild(reflectionCompositeId, 0)), "Input") == 0,
+  AssertMacro(strcmp(assembly->GetNodeName(assembly->GetChild(reflectionId, 0)), "Input") == 0,
     output->GetClassName(), "Incorrect assembly");
-  AssertMacro(
-    strcmp(assembly->GetNodeName(assembly->GetChild(reflectionCompositeId, 1)), "Reflection") == 0,
+  AssertMacro(strcmp(assembly->GetNodeName(assembly->GetChild(reflectionId, 1)), "Reflection") == 0,
     output->GetClassName(), "Incorrect assembly");
 
   AssertMacro(output->GetNumberOfPartitionedDataSets() == 4, output->GetClassName(),
@@ -335,11 +326,81 @@ int TestCompositeData(int argc, char* argv[])
   return EXIT_SUCCESS;
 }
 
+int TestMultiBlockMultiPiece(int argc, char* argv[])
+{
+  ReadFileMacro("Data/mb-of-mps.vtm", vtkXMLMultiBlockDataReader);
+
+  vtkSmartPointer<vtkPartitionedDataSetCollection> output =
+    Reflect(reader->GetOutputPort(), true, true, vtkAxisAlignedReflectionFilter::X_MIN);
+
+  vtkDataAssembly* assembly = output->GetDataAssembly();
+
+  int rootId = assembly->GetRootNode();
+
+  int inputId = assembly->GetChild(rootId, 0);
+  int reflectionId = assembly->GetChild(rootId, 1);
+
+  AssertMacro(strcmp(assembly->GetNodeName(inputId), "Input") == 0, output->GetClassName(),
+    "Incorrect assembly");
+  AssertMacro(strcmp(assembly->GetNodeName(reflectionId), "Reflection") == 0,
+    output->GetClassName(), "Incorrect assembly");
+
+  AssertMacro(strcmp(assembly->GetNodeName(assembly->GetChild(inputId, 0)), "Composite") == 0,
+    output->GetClassName(), "Incorrect assembly");
+  AssertMacro(strcmp(assembly->GetNodeName(assembly->GetChild(inputId, 1)), "Composite") == 0,
+    output->GetClassName(), "Incorrect assembly");
+  AssertMacro(strcmp(assembly->GetNodeName(assembly->GetChild(inputId, 2)), "Composite") == 0,
+    output->GetClassName(), "Incorrect assembly");
+  AssertMacro(strcmp(assembly->GetNodeName(assembly->GetChild(reflectionId, 0)), "Composite") == 0,
+    output->GetClassName(), "Incorrect assembly");
+  AssertMacro(strcmp(assembly->GetNodeName(assembly->GetChild(reflectionId, 1)), "Composite") == 0,
+    output->GetClassName(), "Incorrect assembly");
+  AssertMacro(strcmp(assembly->GetNodeName(assembly->GetChild(reflectionId, 2)), "Composite") == 0,
+    output->GetClassName(), "Incorrect assembly");
+
+  return EXIT_SUCCESS;
+}
+
+int TestMultiBlockOnlyDataSets(int argc, char* argv[])
+{
+  ReadFileMacro("Data/distTest.vtm", vtkXMLMultiBlockDataReader);
+
+  vtkSmartPointer<vtkPartitionedDataSetCollection> output =
+    Reflect(reader->GetOutputPort(), true, true, vtkAxisAlignedReflectionFilter::X_MIN);
+
+  vtkDataAssembly* assembly = output->GetDataAssembly();
+
+  int rootId = assembly->GetRootNode();
+
+  int inputId = assembly->GetChild(rootId, 0);
+  int reflectionId = assembly->GetChild(rootId, 1);
+
+  AssertMacro(strcmp(assembly->GetNodeName(inputId), "Input") == 0, output->GetClassName(),
+    "Incorrect assembly");
+  AssertMacro(strcmp(assembly->GetNodeName(reflectionId), "Reflection") == 0,
+    output->GetClassName(), "Incorrect assembly");
+
+  for (int i = 0; i < 10; i++)
+  {
+    std::string inputCorrect = "Input_" + std::to_string(i);
+    AssertMacro(
+      strcmp(assembly->GetNodeName(assembly->GetChild(inputId, i)), inputCorrect.c_str()) == 0,
+      output->GetClassName(), "Incorrect assembly");
+    std::string reflectionCorrect = "Reflection_" + std::to_string(i);
+    AssertMacro(strcmp(assembly->GetNodeName(assembly->GetChild(reflectionId, i)),
+                  reflectionCorrect.c_str()) == 0,
+      output->GetClassName(), "Incorrect assembly");
+  }
+
+  return EXIT_SUCCESS;
+}
+
 // This function tests all the input types, and each input type will test a different plane mode.
 int TestAxisAlignedReflectionFilter(int argc, char* argv[])
 {
   return TestUnstructuredGrid(argc, argv) || TestImageData(argc, argv) ||
     TestRectilinearGrid(argc, argv) || TestExplicitStructuredGrid(argc, argv) ||
     TestStructuredGrid(argc, argv) || TestPolyData(argc, argv) || TestHyperTreeGrid(argc, argv) ||
-    TestCompositeData(argc, argv);
+    TestPartitionedDataSetCollection(argc, argv) || TestMultiBlockMultiPiece(argc, argv) ||
+    TestMultiBlockOnlyDataSets(argc, argv);
 }
diff --git a/Filters/General/vtkAxisAlignedReflectionFilter.cxx b/Filters/General/vtkAxisAlignedReflectionFilter.cxx
index 3d9aaf6740e6552d992c9147018ad4e70dfb4c9d..08796b173a0796e3298142aac02facf43f404fd3 100644
--- a/Filters/General/vtkAxisAlignedReflectionFilter.cxx
+++ b/Filters/General/vtkAxisAlignedReflectionFilter.cxx
@@ -7,6 +7,7 @@
 #include "vtkCompositeDataSet.h"
 #include "vtkDataArray.h"
 #include "vtkDataAssembly.h"
+#include "vtkDataObjectTreeIterator.h"
 #include "vtkDataSet.h"
 #include "vtkDoubleArray.h"
 #include "vtkExplicitStructuredGrid.h"
@@ -17,6 +18,7 @@
 #include "vtkImageData.h"
 #include "vtkInformation.h"
 #include "vtkInformationVector.h"
+#include "vtkMultiBlockDataSet.h"
 #include "vtkPartitionedDataSet.h"
 #include "vtkPartitionedDataSetCollection.h"
 #include "vtkPlane.h"
@@ -63,8 +65,6 @@ bool vtkAxisAlignedReflectionFilter::ProcessComposite(vtkPartitionedDataSetColle
   vtkCompositeDataSet* inputCD, double bounds[6], int inputNodeId, int reflectionNodeId,
   vtkDataAssembly* outputHierarchy, int& partitionIndex, int& inputCount, int& reflectionCount)
 {
-  const std::string compositeNodeName = "Composite";
-
   vtkDataObjectTree* inputTree = vtkDataObjectTree::SafeDownCast(inputCD);
   if (!inputTree)
   {
@@ -72,26 +72,46 @@ bool vtkAxisAlignedReflectionFilter::ProcessComposite(vtkPartitionedDataSetColle
     return false;
   }
 
-  if (this->CopyInput)
-  {
-    inputNodeId = outputHierarchy->AddNode(compositeNodeName.c_str(), inputNodeId);
-  }
-  reflectionNodeId = outputHierarchy->AddNode(compositeNodeName.c_str(), reflectionNodeId);
+  vtkMultiBlockDataSet* mb = vtkMultiBlockDataSet::SafeDownCast(inputCD);
 
-  vtkSmartPointer<vtkCompositeDataIterator> iter;
-  iter.TakeReference(inputCD->NewIterator());
-  int childIdx = 0;
+  vtkSmartPointer<vtkDataObjectTreeIterator> iter;
+  iter.TakeReference(inputTree->NewTreeIterator());
+  iter->SetVisitOnlyLeaves(false);
+  iter->SetTraverseSubTree(false);
   for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
   {
     if (this->CheckAbort())
     {
       break;
     }
+
     vtkCompositeDataSet* cds = vtkCompositeDataSet::SafeDownCast(iter->GetCurrentDataObject());
     if (cds)
     {
-      return ProcessComposite(outputPDSC, cds, bounds, inputNodeId, reflectionNodeId,
-        outputHierarchy, partitionIndex, inputCount, reflectionCount);
+      std::string compositeNodeName = "Composite";
+      if (inputTree->HasMetaData(iter) &&
+        inputTree->GetMetaData(iter)->Has(vtkCompositeDataSet::NAME()))
+      {
+        compositeNodeName = outputHierarchy->MakeValidNodeName(
+          inputTree->GetMetaData(iter)->Get(vtkCompositeDataSet::NAME()));
+      }
+
+      int compositeInputNodeId = -1;
+      if (this->CopyInput)
+      {
+        compositeInputNodeId = outputHierarchy->AddNode(compositeNodeName.c_str(), inputNodeId);
+      }
+      int compositeReflectionNodeId =
+        outputHierarchy->AddNode(compositeNodeName.c_str(), reflectionNodeId);
+
+      if (!ProcessComposite(outputPDSC, cds, bounds, compositeInputNodeId,
+            compositeReflectionNodeId, outputHierarchy, partitionIndex, inputCount,
+            reflectionCount))
+      {
+        vtkErrorMacro("Failed to process composite dataset " << cds->GetClassName());
+        return false;
+      }
+      continue;
     }
 
     vtkDataSet* ds = vtkDataSet::SafeDownCast(iter->GetCurrentDataObject());
@@ -110,19 +130,28 @@ bool vtkAxisAlignedReflectionFilter::ProcessComposite(vtkPartitionedDataSetColle
       vtkSmartPointer<vtkDataObject> inputCopy = dObj->NewInstance();
       inputCopy->ShallowCopy(dObj);
       outputPDSC->SetPartitionedDataSet(partitionIndex, CreatePartitionedDataSet(inputCopy));
-      const char* objName = inputTree->GetChildMetaData(childIdx)->Get(vtkCompositeDataSet::NAME());
       std::string nodeName;
-      if (objName)
+      if (inputTree->HasMetaData(iter) &&
+        inputTree->GetMetaData(iter)->Has(vtkCompositeDataSet::NAME()))
       {
-        nodeName = "Input_" + std::string(objName);
+        nodeName = "Input_" +
+          outputHierarchy->MakeValidNodeName(
+            inputTree->GetMetaData(iter)->Get(vtkCompositeDataSet::NAME()));
       }
       else
       {
         nodeName = "Input_" + std::to_string(inputCount++);
       }
       outputPDSC->GetMetaData(partitionIndex)->Set(vtkCompositeDataSet::NAME(), nodeName.c_str());
-      int id = outputHierarchy->AddNode(nodeName.c_str(), inputNodeId);
-      outputHierarchy->AddDataSetIndex(id, partitionIndex);
+      if (mb)
+      {
+        int dsNodeId = outputHierarchy->AddNode(nodeName.c_str(), inputNodeId);
+        outputHierarchy->AddDataSetIndex(dsNodeId, partitionIndex);
+      }
+      else
+      {
+        outputHierarchy->AddDataSetIndex(inputNodeId, partitionIndex);
+      }
       inputCopy->Delete();
       partitionIndex++;
     }
@@ -135,21 +164,29 @@ bool vtkAxisAlignedReflectionFilter::ProcessComposite(vtkPartitionedDataSetColle
     }
 
     outputPDSC->SetPartitionedDataSet(partitionIndex, CreatePartitionedDataSet(outputObj));
-    const char* objName = inputTree->GetChildMetaData(childIdx)->Get(vtkCompositeDataSet::NAME());
     std::string nodeName;
-    if (objName)
+    if (inputTree->HasMetaData(iter) &&
+      inputTree->GetMetaData(iter)->Has(vtkCompositeDataSet::NAME()))
     {
-      nodeName = objName;
+      nodeName = outputHierarchy->MakeValidNodeName(
+        inputTree->GetMetaData(iter)->Get(vtkCompositeDataSet::NAME()));
     }
     else
     {
-      nodeName = "Reflection" + std::to_string(reflectionCount++);
+      nodeName = "Reflection_" + std::to_string(reflectionCount++);
     }
+
     outputPDSC->GetMetaData(partitionIndex)->Set(vtkCompositeDataSet::NAME(), nodeName.c_str());
-    int id = outputHierarchy->AddNode(nodeName.c_str(), reflectionNodeId);
-    outputHierarchy->AddDataSetIndex(id, partitionIndex);
+    if (mb)
+    {
+      int dsNodeId = outputHierarchy->AddNode(nodeName.c_str(), reflectionNodeId);
+      outputHierarchy->AddDataSetIndex(dsNodeId, partitionIndex);
+    }
+    else
+    {
+      outputHierarchy->AddDataSetIndex(reflectionNodeId, partitionIndex);
+    }
     partitionIndex++;
-    childIdx++;
 
     outputObj->Delete();
   }
@@ -244,13 +281,14 @@ int vtkAxisAlignedReflectionFilter::RequestData(vtkInformation* vtkNotUsed(reque
     int partitionIndex = 0;
 
     // For naming purposes
-    int inputCount = 1;
-    int reflectionCount = 1;
+    int inputCount = 0;
+    int reflectionCount = 0;
 
     if (!ProcessComposite(outputPDSC, inputCD, bounds, inputNodeId, reflectionNodeId,
           outputHierarchy, partitionIndex, inputCount, reflectionCount))
     {
       vtkErrorMacro("Failed to process composite dataset " << inputCD->GetClassName());
+      return 0;
     }
   }
   else