diff --git a/src/main/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreator.java b/src/main/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreator.java
index cfbade2e911eaf2398d9e206a20a57ef79bf77f9..2ed5f8cb707922f99dd1557a9276ccb7f7d36b5f 100644
--- a/src/main/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreator.java
+++ b/src/main/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreator.java
@@ -4,6 +4,8 @@ import static java.util.Collections.*;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.List;
+import java.util.Set;
 
 import javax.xml.parsers.DocumentBuilder;
 
@@ -33,13 +35,13 @@ public class XdomeaXtaMessageCreator {
 
 	public XtaMessage createMessage(XtaFile xdomeaZipFile) throws ClientException {
 		return XtaMessage.builder()
-				.metaData(deriveMetaData(xdomeaZipFile))
+				.metaData(deriveValidMetaData(xdomeaZipFile))
 				.messageFile(xdomeaZipFile)
 				.attachmentFiles(emptyList())
 				.build();
 	}
 
-	XtaMessageMetaData deriveMetaData(XtaFile xdomeaZipFile) throws ClientException {
+	XtaMessageMetaData deriveValidMetaData(XtaFile xdomeaZipFile) throws ClientException {
 		try {
 			var xdomeaXmlValues = readXdomeaXmlValues(xdomeaZipFile);
 			var messageMetadataData = metadataMapper.mapXtaMessageMetadata(xdomeaXmlValues);
@@ -48,9 +50,19 @@ public class XdomeaXtaMessageCreator {
 					xdomeaXmlValues.processId(),
 					messageMetadataData.messageTypeCode()
 			);
+			validatePrimaryDocumentReferences(xdomeaZipFile, xdomeaXmlValues.primaryDocumentNames());
 			return messageMetadataData;
 		} catch (TechnicalException e) {
-			throw new ClientException("Failed to derive message metadata from xdomea document!", e);
+			throw new ClientException("Failed to derive valid message metadata from xdomea document!", e);
+		}
+	}
+
+	void validatePrimaryDocumentReferences(XtaFile xdomeaZipFile, List<String> primaryDocumentNames) throws ClientException {
+		var entryNames = Set.copyOf(zipFileEntryReader.getEntryNames(xdomeaZipFile.content()));
+		for (var primaryDocumentName : primaryDocumentNames) {
+			if (!entryNames.contains(primaryDocumentName)) {
+				throw new ClientException("Primary document reference '%s' not found in xdomea zip file!".formatted(primaryDocumentName));
+			}
 		}
 	}
 
diff --git a/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XdomeaValueReader.java b/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XdomeaValueReader.java
index df4cff99ead99f19b2b6b3ae70fb413674245ef3..45adea934b21aeec30fdb28f5055ed2887f0ddac 100644
--- a/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XdomeaValueReader.java
+++ b/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XdomeaValueReader.java
@@ -1,6 +1,7 @@
 package de.ozgcloud.xta.client.xdomea.reader;
 
 import java.util.Arrays;
+import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 
@@ -14,16 +15,16 @@ import lombok.RequiredArgsConstructor;
 @RequiredArgsConstructor
 public class XdomeaValueReader {
 
-	static final String PROCESS_ID_XPATH = getTextXpath("Kopf", "ProzessID");
-	static final String AUTHOR_ID_SUFFIX_XPATH = getTextXpath("Kopf", "Absender", "code");
-	static final String READER_ID_SUFFIX_XPATH = getTextXpath("Kopf", "Empfaenger", "code");
-	static final String MESSAGE_TYPE_ID_SUFFIX_XPATH = getTextXpath("Kopf", "Nachrichtentyp", "code");
+	static final String PROCESS_ID_XPATH = getXpath("Kopf", "ProzessID");
+	static final String AUTHOR_ID_SUFFIX_XPATH = getXpath("Kopf", "Absender", "code");
+	static final String READER_ID_SUFFIX_XPATH = getXpath("Kopf", "Empfaenger", "code");
+	static final String MESSAGE_TYPE_ID_SUFFIX_XPATH = getXpath("Kopf", "Nachrichtentyp", "code");
+	static final String PRIMARY_DOCUMENT_NAME_XPATH = getXpath("Primaerdokument", "Dateiname");
 
-	static String getTextXpath(String... hierarchy) {
+	static String getXpath(String... hierarchy) {
 		return Arrays.stream(hierarchy)
 				.map(h -> "//*[local-name() = '" + h + "']")
-				.collect(Collectors.joining())
-				+ "/text()";
+				.collect(Collectors.joining());
 	}
 
 	private final Map<String, XmlValueReader> xmlValueReaders;
@@ -34,12 +35,20 @@ public class XdomeaValueReader {
 				.messageTypeCode(readRequiredValue(xdomeaXmlDocument, MESSAGE_TYPE_ID_SUFFIX_XPATH))
 				.authorIdSuffix(readRequiredValue(xdomeaXmlDocument, AUTHOR_ID_SUFFIX_XPATH))
 				.readerIdSuffix(readRequiredValue(xdomeaXmlDocument, READER_ID_SUFFIX_XPATH))
+				.primaryDocumentNames(readPrimaryDocumentNames(xdomeaXmlDocument))
 				.build();
 	}
 
+	List<String> readPrimaryDocumentNames(Document xdomeaXmlDocument) {
+		return getXmlValueReader(PRIMARY_DOCUMENT_NAME_XPATH)
+				.readNonEmptyTexts(xdomeaXmlDocument)
+				.toList();
+	}
+
 	String readRequiredValue(Document xdomeaXmlDocument, String xpathString) throws ClientException {
 		return getXmlValueReader(xpathString)
-				.readString(xdomeaXmlDocument)
+				.readNonEmptyTexts(xdomeaXmlDocument)
+				.findFirst()
 				.orElseThrow(() -> new ClientException("Required value " + xpathString + " not found in xdomea xml document!"));
 	}
 
diff --git a/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XdomeaValueReaderFactory.java b/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XdomeaValueReaderFactory.java
index 569488d2f3d6cbb673657b8ed309d16af1c173bc..9dbcf5e1c3b6d317870ffd93e4c062bea1976af7 100644
--- a/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XdomeaValueReaderFactory.java
+++ b/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XdomeaValueReaderFactory.java
@@ -33,7 +33,8 @@ public class XdomeaValueReaderFactory {
 						PROCESS_ID_XPATH,
 						MESSAGE_TYPE_ID_SUFFIX_XPATH,
 						AUTHOR_ID_SUFFIX_XPATH,
-						READER_ID_SUFFIX_XPATH
+						READER_ID_SUFFIX_XPATH,
+						PRIMARY_DOCUMENT_NAME_XPATH
 				).collect(Collectors.toMap(
 						xpath -> xpath,
 						this::createXmlValueReader
diff --git a/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XdomeaXmlValues.java b/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XdomeaXmlValues.java
index 8f7ce947440a879d0761f87abefd1ba9a64ea85e..7783474d380204b3ea6b9c9d168db9c847440318 100644
--- a/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XdomeaXmlValues.java
+++ b/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XdomeaXmlValues.java
@@ -1,5 +1,8 @@
 package de.ozgcloud.xta.client.xdomea.reader;
 
+import java.util.List;
+
+import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotBlank;
 
 import lombok.Builder;
@@ -9,6 +12,7 @@ public record XdomeaXmlValues(
 		@NotBlank String processId,
 		@NotBlank String messageTypeCode,
 		@NotBlank String authorIdSuffix,
-		@NotBlank String readerIdSuffix
+		@NotBlank String readerIdSuffix,
+		@Valid List<@NotBlank String> primaryDocumentNames
 ) {
 }
diff --git a/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReader.java b/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReader.java
index 094ae50eabdf1dc9aad81e76bf2c09d051fa25a5..642bff51e49b4c7ff2b3c2d8f7cbefc362dc4b67 100644
--- a/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReader.java
+++ b/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReader.java
@@ -1,12 +1,15 @@
 package de.ozgcloud.xta.client.xdomea.reader;
 
-import java.util.Optional;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
 
 import javax.xml.xpath.XPathConstants;
 import javax.xml.xpath.XPathExpression;
 import javax.xml.xpath.XPathExpressionException;
 
 import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
 
 import de.ozgcloud.common.errorhandling.TechnicalException;
 import lombok.Builder;
@@ -16,24 +19,34 @@ import lombok.RequiredArgsConstructor;
 @RequiredArgsConstructor
 public class XmlValueReader {
 
-	private final XPathExpression textXpath;
+	private final XPathExpression xPathExpression;
 
-	public Optional<String> readString(Document xmlDocument) {
-		return findStringByTextXpath(xmlDocument, textXpath)
-				.map(String::trim)
-				.filter(s -> !s.isBlank());
+	public Stream<String> readNonEmptyTexts(Document xmlDocument) {
+		return getTextsFromNodes(queryNodeList(xmlDocument, xPathExpression))
+				.filter(s -> !s.isEmpty());
 	}
 
-	private Optional<String> findStringByTextXpath(Document xdomeaXmlDocument, XPathExpression textXpath) {
+	private NodeList queryNodeList(Document xmlDocument, XPathExpression xPathExpression) {
 		try {
-			return Optional.ofNullable((String) textXpath
+			return (NodeList) xPathExpression
 					.evaluate(
-							xdomeaXmlDocument.getDocumentElement(),
-							XPathConstants.STRING
-					));
+							xmlDocument.getDocumentElement(),
+							XPathConstants.NODESET
+					);
 		} catch (XPathExpressionException e) {
 			throw new TechnicalException("Failed to execute xpath search!", e);
 		}
 	}
 
+	private Stream<String> getTextsFromNodes(NodeList nodeList) {
+		return streamNodeList(nodeList)
+				.map(Node::getTextContent)
+				.map(String::trim);
+	}
+
+	private Stream<Node> streamNodeList(NodeList nodeList) {
+		return IntStream.range(0, nodeList.getLength())
+				.mapToObj(nodeList::item);
+	}
+
 }
diff --git a/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReaderFactory.java b/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReaderFactory.java
index 90966ec68d9e684e225bfe02aee739b51fba0659..5f28091a231a036a4dfefd2b6e9a08883199e0c4 100644
--- a/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReaderFactory.java
+++ b/src/main/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReaderFactory.java
@@ -25,7 +25,7 @@ public class XmlValueReaderFactory {
 
 	public XmlValueReader create() {
 		return XmlValueReader.builder()
-				.textXpath(compileXPathExpression())
+				.xPathExpression(compileXPathExpression())
 				.build();
 	}
 }
diff --git a/src/main/java/de/ozgcloud/xta/client/xdomea/reader/ZipFileEntryReader.java b/src/main/java/de/ozgcloud/xta/client/xdomea/reader/ZipFileEntryReader.java
index 2164cb8d8c5d05833e87325984876a2e22d45f37..8b0df0b9cc40098cd285e228fed1895c0a66e862 100644
--- a/src/main/java/de/ozgcloud/xta/client/xdomea/reader/ZipFileEntryReader.java
+++ b/src/main/java/de/ozgcloud/xta/client/xdomea/reader/ZipFileEntryReader.java
@@ -2,6 +2,8 @@ package de.ozgcloud.xta.client.xdomea.reader;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.function.Function;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
@@ -30,4 +32,18 @@ public class ZipFileEntryReader {
 			throw new TechnicalException("Failed reading zip file!", e);
 		}
 	}
+
+	public List<String> getEntryNames(DataHandler zipFileContent) {
+		var entryNames = new ArrayList<String>();
+		try (var zipInputStream = new ZipInputStream(zipFileContent.getInputStream())) {
+			ZipEntry entry;
+			while ((entry = zipInputStream.getNextEntry()) != null) {
+				entryNames.add(entry.getName());
+				zipInputStream.closeEntry();
+			}
+			return entryNames;
+		} catch (IOException e) {
+			throw new TechnicalException("Failed reading zip file!", e);
+		}
+	}
 }
diff --git a/src/test/java/de/ozgcloud/xta/client/factory/XdomeaXmlValuesTestFactory.java b/src/test/java/de/ozgcloud/xta/client/factory/XdomeaXmlValuesTestFactory.java
index 2c62293e5ce016249122a58d4845e6b13ac4482f..ca099c7446385e4efee53a903dd6b922e2cd6fe7 100644
--- a/src/test/java/de/ozgcloud/xta/client/factory/XdomeaXmlValuesTestFactory.java
+++ b/src/test/java/de/ozgcloud/xta/client/factory/XdomeaXmlValuesTestFactory.java
@@ -1,5 +1,7 @@
 package de.ozgcloud.xta.client.factory;
 
+import java.util.List;
+
 import de.ozgcloud.xta.client.xdomea.reader.XdomeaXmlValues;
 
 public class XdomeaXmlValuesTestFactory {
@@ -9,6 +11,8 @@ public class XdomeaXmlValuesTestFactory {
 	public static final String AUTHOR_ID_SUFFIX = "authorIdSuffix";
 	public static final String READER_ID_SUFFIX = "readerIdSuffix";
 
+	public static final List<String> PRIMARY_DOCUMENT_NAMES = List.of("doc.pdf", "doc.xml");
+
 	public static XdomeaXmlValues create() {
 		return createBuilder().build();
 	}
@@ -18,6 +22,7 @@ public class XdomeaXmlValuesTestFactory {
 				.processId(PROCESS_ID)
 				.messageTypeCode(SHORT_MESSAGE_TYPE_CODE)
 				.authorIdSuffix(AUTHOR_ID_SUFFIX)
-				.readerIdSuffix(READER_ID_SUFFIX);
+				.readerIdSuffix(READER_ID_SUFFIX)
+				.primaryDocumentNames(PRIMARY_DOCUMENT_NAMES);
 	}
 }
diff --git a/src/test/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreatorITCase.java b/src/test/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreatorITCase.java
index 4859c4cda6c4cdb80157f882c6fc817ea70e3fa2..b508b5322ee0c21a7b3d9dfb8077399e6259f3bb 100644
--- a/src/test/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreatorITCase.java
+++ b/src/test/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreatorITCase.java
@@ -106,12 +106,12 @@ class XdomeaXtaMessageCreatorITCase {
 		}
 
 		@DisplayName("should throw client exception for invalid message 0401")
-		@Test
-		@SneakyThrows
-		void shouldThrowClientExceptionForInvalidMessage0401() {
+		@ParameterizedTest
+		@ValueSource(strings = { "invalid-ProzessID.patch", "invalid-reference-to-primary-document.patch" })
+		void shouldThrowClientExceptionForInvalidMessage0401(String patchName) {
 			var invalidMessageZipFile = loadMessageFileWithPatch(
 					"abgabe0401-kleiner-waffenschein",
-					"invalid-ProzessID.patch"
+					patchName
 			);
 
 			assertThatThrownBy(() -> creator.createMessage(invalidMessageZipFile))
diff --git a/src/test/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreatorTest.java b/src/test/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreatorTest.java
index 0155421cdcf5b27527a87d57eb41777646035790..134454daa3c437f6180b664e6b416598ee8ce594 100644
--- a/src/test/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreatorTest.java
+++ b/src/test/java/de/ozgcloud/xta/client/xdomea/XdomeaXtaMessageCreatorTest.java
@@ -7,6 +7,7 @@ import static org.assertj.core.api.Assertions.*;
 import static org.mockito.Mockito.*;
 
 import java.io.InputStream;
+import java.util.List;
 import java.util.function.Function;
 
 import javax.xml.parsers.DocumentBuilder;
@@ -69,7 +70,7 @@ class XdomeaXtaMessageCreatorTest {
 		@BeforeEach
 		@SneakyThrows
 		void mock() {
-			doReturn(metaData).when(creator).deriveMetaData(xdomeaZipFile);
+			doReturn(metaData).when(creator).deriveValidMetaData(xdomeaZipFile);
 		}
 
 		@DisplayName("should return metadata")
@@ -102,9 +103,9 @@ class XdomeaXtaMessageCreatorTest {
 		}
 	}
 
-	@DisplayName("derive meta data")
+	@DisplayName("derive valid meta data")
 	@Nested
-	class TestDeriveMetaData {
+	class TestDeriveValidMetaData {
 
 		private XtaFile xdomeaZipFile;
 
@@ -130,7 +131,7 @@ class XdomeaXtaMessageCreatorTest {
 		void shouldReturn() {
 			mockValidMetadata();
 
-			var result = creator.deriveMetaData(xdomeaZipFile);
+			var result = creator.deriveValidMetaData(xdomeaZipFile);
 
 			assertThat(result).isEqualTo(metaData);
 		}
@@ -141,7 +142,7 @@ class XdomeaXtaMessageCreatorTest {
 		void shouldVerifyZipFileName() {
 			mockValidMetadata();
 
-			creator.deriveMetaData(xdomeaZipFile);
+			creator.deriveValidMetaData(xdomeaZipFile);
 
 			verify(creator).validateZipFileName(
 					XTA_FILE_NAME,
@@ -150,14 +151,25 @@ class XdomeaXtaMessageCreatorTest {
 			);
 		}
 
+		@DisplayName("should verify primary document references")
+		@Test
+		@SneakyThrows
+		void shouldVerifyPrimaryDocumentReferences() {
+			mockValidMetadata();
+
+			creator.deriveValidMetaData(xdomeaZipFile);
+
+			verify(creator).validatePrimaryDocumentReferences(
+					xdomeaZipFile,
+					PRIMARY_DOCUMENT_NAMES
+			);
+		}
+
 		@SneakyThrows
 		private void mockValidMetadata() {
 			doReturn(metaData).when(metadataMapper).mapXtaMessageMetadata(xdomeaXmlValues);
-			doNothing().when(creator).validateZipFileName(
-					any(),
-					any(),
-					any()
-			);
+			doNothing().when(creator).validateZipFileName(any(), any(), any());
+			doNothing().when(creator).validatePrimaryDocumentReferences(any(), any());
 		}
 
 		@DisplayName("should throw client exception")
@@ -165,7 +177,7 @@ class XdomeaXtaMessageCreatorTest {
 		void shouldThrowClientException() {
 			doThrow(technicalException).when(metadataMapper).mapXtaMessageMetadata(xdomeaXmlValues);
 
-			assertThatThrownBy(() -> creator.deriveMetaData(xdomeaZipFile))
+			assertThatThrownBy(() -> creator.deriveValidMetaData(xdomeaZipFile))
 					.isInstanceOf(ClientException.class);
 		}
 
@@ -281,4 +293,44 @@ class XdomeaXtaMessageCreatorTest {
 
 	}
 
+	@DisplayName("validate primary document references")
+	@Nested
+	class TestValidatePrimaryDocumentReferences {
+
+		private static final List<String> VALID_ZIP_ENTRY_NAMES = List.of("doc.pdf", "doc.xml", "other.doc");
+		private static final List<String> INVALID_ZIP_ENTRY_NAMES = List.of("doc.pdf");
+
+		@Mock
+		private XtaFile xdomeaZipFile;
+
+		@Mock
+		private DataHandler contentDataHandler;
+
+		@BeforeEach
+		@SneakyThrows
+		void mock() {
+			when(xdomeaZipFile.content()).thenReturn(contentDataHandler);
+
+		}
+
+		@DisplayName("should not throw exception for valid primary document references")
+		@Test
+		@SneakyThrows
+		void shouldNotThrowExceptionForValidPrimaryDocumentReferences() {
+			when(zipFileEntryReader.getEntryNames(contentDataHandler)).thenReturn(VALID_ZIP_ENTRY_NAMES);
+
+			creator.validatePrimaryDocumentReferences(xdomeaZipFile, PRIMARY_DOCUMENT_NAMES);
+		}
+
+		@DisplayName("should throw client exception for missing primary document references")
+		@Test
+		@SneakyThrows
+		void shouldThrowClientExceptionForMissingPrimaryDocumentReferences() {
+			when(zipFileEntryReader.getEntryNames(contentDataHandler)).thenReturn(INVALID_ZIP_ENTRY_NAMES);
+
+			assertThatThrownBy(() -> creator.validatePrimaryDocumentReferences(xdomeaZipFile, PRIMARY_DOCUMENT_NAMES))
+					.isInstanceOf(ClientException.class);
+		}
+	}
+
 }
\ No newline at end of file
diff --git a/src/test/java/de/ozgcloud/xta/client/xdomea/reader/XdomeaValueReaderFactoryTest.java b/src/test/java/de/ozgcloud/xta/client/xdomea/reader/XdomeaValueReaderFactoryTest.java
index 630e4bc0d8cdcfd3aaae7bf7060b6d018339d861..e2fd3afd7e8daf8e5c006b135741a9f77515b190 100644
--- a/src/test/java/de/ozgcloud/xta/client/xdomea/reader/XdomeaValueReaderFactoryTest.java
+++ b/src/test/java/de/ozgcloud/xta/client/xdomea/reader/XdomeaValueReaderFactoryTest.java
@@ -44,6 +44,9 @@ class XdomeaValueReaderFactoryTest {
 		@Mock
 		XmlValueReader readerIdReader;
 
+		@Mock
+		XmlValueReader primaryDocumentNameReader;
+
 		@DisplayName("should return")
 		@Test
 		@SneakyThrows
@@ -52,6 +55,7 @@ class XdomeaValueReaderFactoryTest {
 			doReturn(messageTypeReader).when(factory).createXmlValueReader(MESSAGE_TYPE_ID_SUFFIX_XPATH);
 			doReturn(authorIdReader).when(factory).createXmlValueReader(AUTHOR_ID_SUFFIX_XPATH);
 			doReturn(readerIdReader).when(factory).createXmlValueReader(READER_ID_SUFFIX_XPATH);
+			doReturn(primaryDocumentNameReader).when(factory).createXmlValueReader(PRIMARY_DOCUMENT_NAME_XPATH);
 
 			var reader = factory.create();
 
@@ -60,7 +64,8 @@ class XdomeaValueReaderFactoryTest {
 							PROCESS_ID_XPATH, procesIdReader,
 							MESSAGE_TYPE_ID_SUFFIX_XPATH, messageTypeReader,
 							AUTHOR_ID_SUFFIX_XPATH, authorIdReader,
-							READER_ID_SUFFIX_XPATH, readerIdReader
+							READER_ID_SUFFIX_XPATH, readerIdReader,
+							PRIMARY_DOCUMENT_NAME_XPATH, primaryDocumentNameReader
 					)).build());
 		}
 	}
diff --git a/src/test/java/de/ozgcloud/xta/client/xdomea/reader/XdomeaValueReaderTest.java b/src/test/java/de/ozgcloud/xta/client/xdomea/reader/XdomeaValueReaderTest.java
index 99abcbe5940c5fa75aa9ad77f96d37b4632453e2..5b47cc40f94490514007355bef9e10c618a38840 100644
--- a/src/test/java/de/ozgcloud/xta/client/xdomea/reader/XdomeaValueReaderTest.java
+++ b/src/test/java/de/ozgcloud/xta/client/xdomea/reader/XdomeaValueReaderTest.java
@@ -3,8 +3,9 @@ package de.ozgcloud.xta.client.xdomea.reader;
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.Mockito.*;
 
+import java.util.List;
 import java.util.Map;
-import java.util.Optional;
+import java.util.stream.Stream;
 
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
@@ -37,6 +38,7 @@ class XdomeaValueReaderTest {
 		private static final String MESSAGE_TYPE_CODE = "message type code";
 		private static final String AUTHOR_ID_SUFFIX = "author id suffix";
 		private static final String READER_ID_SUFFIX = "reader id suffix";
+		private static final List<String> PRIMARY_DOCUMENT_NAMES = List.of("primary document name");
 
 		@Mock
 		Document xdomeaXmlDocument;
@@ -48,6 +50,7 @@ class XdomeaValueReaderTest {
 			doReturn(MESSAGE_TYPE_CODE).when(xdomeaValueReader).readRequiredValue(xdomeaXmlDocument, XdomeaValueReader.MESSAGE_TYPE_ID_SUFFIX_XPATH);
 			doReturn(AUTHOR_ID_SUFFIX).when(xdomeaValueReader).readRequiredValue(xdomeaXmlDocument, XdomeaValueReader.AUTHOR_ID_SUFFIX_XPATH);
 			doReturn(READER_ID_SUFFIX).when(xdomeaValueReader).readRequiredValue(xdomeaXmlDocument, XdomeaValueReader.READER_ID_SUFFIX_XPATH);
+			doReturn(PRIMARY_DOCUMENT_NAMES).when(xdomeaValueReader).readPrimaryDocumentNames(xdomeaXmlDocument);
 		}
 
 		@DisplayName("should return process id")
@@ -82,12 +85,50 @@ class XdomeaValueReaderTest {
 			assertThat(result.readerIdSuffix()).isEqualTo(READER_ID_SUFFIX);
 		}
 
+		@DisplayName("should return primary document names")
+		@Test
+		void shouldReturnPrimaryDocumentNames() {
+			var result = readValues();
+
+			assertThat(result.primaryDocumentNames()).isEqualTo(PRIMARY_DOCUMENT_NAMES);
+		}
+
 		@SneakyThrows
 		private XdomeaXmlValues readValues() {
 			return xdomeaValueReader.readValues(xdomeaXmlDocument);
 		}
 	}
 
+	@DisplayName("read primary document names")
+	@Nested
+	class TestReadPrimaryDocumentNames {
+
+		@Mock
+		XmlValueReader xmlValueReader;
+
+		@Mock
+		Document xdomeaXmlDocument;
+
+		final String documentName1 = "dou.pdf";
+		final String documentName2 = "doc.png";
+
+		@BeforeEach
+		void mock() {
+			doReturn(xmlValueReader).when(xdomeaValueReader).getXmlValueReader(XdomeaValueReader.PRIMARY_DOCUMENT_NAME_XPATH);
+		}
+
+		@DisplayName("should return")
+		@Test
+		@SneakyThrows
+		void shouldReturn() {
+			when(xmlValueReader.readNonEmptyTexts(xdomeaXmlDocument)).thenReturn(Stream.of(documentName1, documentName2));
+
+			var result = xdomeaValueReader.readPrimaryDocumentNames(xdomeaXmlDocument);
+
+			assertThat(result).containsExactly(documentName1, documentName2);
+		}
+	}
+
 	@DisplayName("read required value")
 	@Nested
 	class TestReadRequiredValue {
@@ -109,7 +150,7 @@ class XdomeaValueReaderTest {
 		@Test
 		@SneakyThrows
 		void shouldReturn() {
-			when(xmlValueReader.readString(xdomeaXmlDocument)).thenReturn(Optional.of(foundValue));
+			when(xmlValueReader.readNonEmptyTexts(xdomeaXmlDocument)).thenReturn(Stream.of(foundValue));
 
 			var result = xdomeaValueReader.readRequiredValue(xdomeaXmlDocument, XPATH_STRING);
 
@@ -119,7 +160,7 @@ class XdomeaValueReaderTest {
 		@DisplayName("should throw client exception if missing")
 		@Test
 		void shouldThrowClientExceptionIfMissing() {
-			when(xmlValueReader.readString(xdomeaXmlDocument)).thenReturn(Optional.empty());
+			when(xmlValueReader.readNonEmptyTexts(xdomeaXmlDocument)).thenReturn(Stream.empty());
 
 			assertThatThrownBy(() -> xdomeaValueReader.readRequiredValue(xdomeaXmlDocument, XPATH_STRING))
 					.isInstanceOf(ClientException.class);
diff --git a/src/test/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReaderFactoryTest.java b/src/test/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReaderFactoryTest.java
index 345df89592accc360d48b4696e376d4ff7ce9f3c..b848a3aea0f792d85c9676b501b53c6b7037eae9 100644
--- a/src/test/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReaderFactoryTest.java
+++ b/src/test/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReaderFactoryTest.java
@@ -62,7 +62,7 @@ class XmlValueReaderFactoryTest {
 			var result = factory.create();
 
 			assertThat(result).usingRecursiveComparison().isEqualTo(XmlValueReader.builder()
-					.textXpath(expression)
+					.xPathExpression(expression)
 					.build());
 		}
 
diff --git a/src/test/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReaderTest.java b/src/test/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReaderTest.java
index ec8631562e1ff698e96313ff0970efb0c5a8448b..aa059508e802f341efb712d056c235a14d33eb9b 100644
--- a/src/test/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReaderTest.java
+++ b/src/test/java/de/ozgcloud/xta/client/xdomea/reader/XmlValueReaderTest.java
@@ -10,46 +10,46 @@ import org.w3c.dom.Document;
 
 public class XmlValueReaderTest {
 
-	@DisplayName("read string")
+	@DisplayName("read non empty texts")
 	@Nested
-	class TestReadString {
+	class TestReadNonEmptyTexts {
+		private static final Document XML_DOCUMENT = createXMLDocument("<root><value attr=\"val\">test</value><value>test2</value></root>");
 
-		private static final Document XML_DOCUMENT = createXMLDocument("<root><value>test</value></root>");
+		@DisplayName("should return with two matches")
+		@Test
+		void shouldReturnWithTwoMatches() {
+			var xmlValueReader = createXmlValueReaderWithXPath("/root/value/text()");
 
-		@DisplayName("when xml contains value")
-		@Nested
-		class TestWhenXmlContainsValue {
+			var result = xmlValueReader.readNonEmptyTexts(XML_DOCUMENT);
 
-			@DisplayName("should return value")
-			@Test
-			void testShouldReturnValue() {
-				var xmlValueReader = createXmlValueReaderWithXPath("/root/value/text()");
+			assertThat(result).containsExactly("test", "test2");
+		}
 
-				var result = xmlValueReader.readString(XML_DOCUMENT);
+		@DisplayName("should return with one match")
+		@Test
+		void shouldReturnWithOneMatch() {
+			var xmlValueReader = createXmlValueReaderWithXPath("/root/value[@attr]/text()");
 
-				assertThat(result).contains("test");
-			}
-		}
+			var result = xmlValueReader.readNonEmptyTexts(XML_DOCUMENT);
 
-		@DisplayName("when xml does not contain value")
-		@Nested
-		class TestWhenXmlDoesNotContainValue {
+			assertThat(result).containsExactly("test");
+		}
 
-			@DisplayName("should return empty")
-			@Test
-			void testShouldReturnEmpty() {
-				var xmlValueReader = createXmlValueReaderWithXPath("/root/missing/text()");
+		@DisplayName("should return with no match")
+		@Test
+		void shouldReturnWithNoMatch() {
+			var xmlValueReader = createXmlValueReaderWithXPath("/root/missing/text()");
 
-				var result = xmlValueReader.readString(XML_DOCUMENT);
+			var result = xmlValueReader.readNonEmptyTexts(XML_DOCUMENT);
 
-				assertThat(result).isEmpty();
-			}
+			assertThat(result).isEmpty();
 		}
+
 	}
 
 	private XmlValueReader createXmlValueReaderWithXPath(String xPathString) {
 		return XmlValueReader.builder()
-				.textXpath(createXPathExpression(xPathString))
+				.xPathExpression(createXPathExpression(xPathString))
 				.build();
 	}
 
diff --git a/src/test/java/de/ozgcloud/xta/client/xdomea/reader/ZipFileEntryReaderTest.java b/src/test/java/de/ozgcloud/xta/client/xdomea/reader/ZipFileEntryReaderTest.java
index 31a55f0346f0d6a8fbbd843be14cc4c06843d820..37d1a0346e915cdb7f7ac542cafcbf1c74029470 100644
--- a/src/test/java/de/ozgcloud/xta/client/xdomea/reader/ZipFileEntryReaderTest.java
+++ b/src/test/java/de/ozgcloud/xta/client/xdomea/reader/ZipFileEntryReaderTest.java
@@ -3,11 +3,13 @@ package de.ozgcloud.xta.client.xdomea.reader;
 import static de.ozgcloud.xta.client.factory.XtaMessageTestFactory.*;
 import static org.assertj.core.api.Assertions.*;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.function.Function;
 
 import jakarta.activation.DataHandler;
+import jakarta.activation.FileDataSource;
 import jakarta.mail.util.ByteArrayDataSource;
 
 import org.junit.jupiter.api.DisplayName;
@@ -24,14 +26,13 @@ class ZipFileEntryReaderTest {
 
 	private final ZipFileEntryReader reader = ZipFileEntryReaderFactory.builder().build().create();
 
-
 	@DisplayName("map entry data")
 	@Nested
 	class TestMapEntryData {
 
 		private final Function<InputStream, String> inputStreamConsumer = inputStream -> {
 			try {
-				var data= inputStream.readAllBytes();
+				var data = inputStream.readAllBytes();
 				return new String(data);
 			} catch (IOException e) {
 				throw new RuntimeException(e);
@@ -61,6 +62,35 @@ class ZipFileEntryReaderTest {
 		}
 	}
 
+	@DisplayName("get entry names")
+	@Nested
+	class TestGetEntryNames {
+
+		@DisplayName("should return entry names")
+		@Test
+		void shouldReturnEntryNames() {
+			var entryNames = reader.getEntryNames(ZIP_FILE);
+
+			assertThat(entryNames).containsExactlyInAnyOrder(
+					"66a7635a-3872-3519-5ad8-00000000e7db_small_png.png",
+					"66a76331-3872-3519-5ad8-00000000e7d8_XML-Daten.xml",
+					"66a76372-3872-3519-5ad8-00000000e7df_Tempo.pdf",
+					"84be3140-e069-4d4a-80c7-889b5eec539e_Abgabe.Abgabe.0401.xml"
+			);
+		}
+
+		@DisplayName("should throw exception on bad zip file")
+		@Test
+		void shouldThrowExceptionOnBadZipFile() {
+			assertThatThrownBy(() -> reader.getEntryNames(createMissingFileDataHandler()))
+					.isInstanceOf(TechnicalException.class);
+		}
+
+		private static DataHandler createMissingFileDataHandler() {
+			return new DataHandler(new FileDataSource(new File("missing-file")));
+		}
+	}
+
 	private static DataHandler createContentDataHandler(byte[] data) {
 		return new DataHandler(new ByteArrayDataSource(data, "application/octet-stream"));
 	}
diff --git a/src/test/resources/messages/abgabe0401-kleiner-waffenschein/invalid-reference-to-primary-document.patch b/src/test/resources/messages/abgabe0401-kleiner-waffenschein/invalid-reference-to-primary-document.patch
new file mode 100644
index 0000000000000000000000000000000000000000..6df712f6ee1e31b30c12873dcef1ffe33e495d91
--- /dev/null
+++ b/src/test/resources/messages/abgabe0401-kleiner-waffenschein/invalid-reference-to-primary-document.patch
@@ -0,0 +1,13 @@
+diff --git a/src/test/resources/messages/abgabe0401-kleiner-waffenschein/message/84be3140-e069-4d4a-80c7-889b5eec539e_Abgabe.Abgabe.0401.zip/84be3140-e069-4d4a-80c7-889b5eec539e_Abgabe.Abgabe.0401.xml b/src/test/resources/messages/abgabe0401-kleiner-waffenschein/message/84be3140-e069-4d4a-80c7-889b5eec539e_Abgabe.Abgabe.0401.zip/84be3140-e069-4d4a-80c7-889b5eec539e_Abgabe.Abgabe.0401.xml
+index cac00bf..9103baa 100644
+--- a/src/test/resources/messages/abgabe0401-kleiner-waffenschein/message/84be3140-e069-4d4a-80c7-889b5eec539e_Abgabe.Abgabe.0401.zip/84be3140-e069-4d4a-80c7-889b5eec539e_Abgabe.Abgabe.0401.xml
++++ b/src/test/resources/messages/abgabe0401-kleiner-waffenschein/message/84be3140-e069-4d4a-80c7-889b5eec539e_Abgabe.Abgabe.0401.zip/84be3140-e069-4d4a-80c7-889b5eec539e_Abgabe.Abgabe.0401.xml
+@@ -158,7 +158,7 @@
+                             </xdomea:Name>
+                             <xdomea:Version></xdomea:Version>
+                             <xdomea:Primaerdokument>
+-                                <xdomea:Dateiname>66a7635a-3872-3519-5ad8-00000000e7db_small_png.png</xdomea:Dateiname>
++                                <xdomea:Dateiname>66a7635a-3872-3519-5ad8-00000000e7db_unkonwn_png.png</xdomea:Dateiname>
+                                 <xdomea:DateinameOriginal>small_png.png</xdomea:DateinameOriginal>
+                             </xdomea:Primaerdokument>
+                         </xdomea:Format>