diff --git a/src/SAML2/XML/saml/AbstractEvidenceType.php b/src/SAML2/XML/saml/AbstractEvidenceType.php
new file mode 100644
index 000000000..2e4f9ff31
--- /dev/null
+++ b/src/SAML2/XML/saml/AbstractEvidenceType.php
@@ -0,0 +1,151 @@
+assertionIDRef)
+ && empty($this->assertionURIRef)
+ && empty($this->assertion)
+ && empty($this->encryptedAssertion)
+ );
+ }
+
+
+ /**
+ * @return \SimpleSAML\SAML2\XML\saml\AssertionIDRef[]
+ */
+ public function getAssertionIDRef(): array
+ {
+ return $this->assertionIDRef;
+ }
+
+
+ /**
+ * @return \SimpleSAML\SAML2\XML\saml\AssertionURIRef[]
+ */
+ public function getAssertionURIRef(): array
+ {
+ return $this->assertionURIRef;
+ }
+
+
+ /**
+ * @return \SimpleSAML\SAML2\XML\saml\Assertion[]
+ */
+ public function getAssertion(): array
+ {
+ return $this->assertion;
+ }
+
+
+ /**
+ * @return \SimpleSAML\SAML2\XML\saml\EncryptedAssertion[]
+ */
+ public function getEncryptedAssertion(): array
+ {
+ return $this->encryptedAssertion;
+ }
+
+
+ /**
+ * Convert XML into an AbstractEvidenceType
+ *
+ * @param \DOMElement $xml The XML element we should load
+ * @return static
+ *
+ * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
+ * If the qualified name of the supplied element is wrong
+ */
+ public static function fromXML(DOMElement $xml): static
+ {
+ $qualifiedName = static::getClassName(static::class);
+ Assert::eq(
+ $xml->localName,
+ $qualifiedName,
+ 'Unexpected name for endpoint: ' . $xml->localName . '. Expected: ' . $qualifiedName . '.',
+ InvalidDOMElementException::class,
+ );
+
+ $assertionIDRef = AssertionIDRef::getChildrenOfClass($xml);
+ $assertionURIRef = AssertionURIRef::getChildrenOfClass($xml);
+ $assertion = Assertion::getChildrenOfClass($xml);
+ $encryptedAssertion = EncryptedAssertion::getChildrenOfClass($xml);
+
+ return new static(
+ $assertionIDRef,
+ $assertionURIRef,
+ $assertion,
+ $encryptedAssertion,
+ );
+ }
+
+
+ /**
+ * Convert this AbstractEvidenceType to XML.
+ *
+ * @param \DOMElement $parent The element we are converting to XML.
+ * @return \DOMElement The XML element after adding the data corresponding to this Condition.
+ */
+ public function toXML(DOMElement $parent = null): DOMElement
+ {
+ $e = $this->instantiateParentElement($parent);
+
+ foreach ($this->getAssertionIDRef() as $assertionIDRef) {
+ $assertionIDRef->toXML($e);
+ }
+
+ foreach ($this->getAssertionURIRef() as $assertionURIRef) {
+ $assertionURIRef->toXML($e);
+ }
+
+ foreach ($this->getAssertion() as $assertion) {
+ $assertion->toXML($e);
+ }
+
+ foreach ($this->getEncryptedAssertion() as $encryptedAssertion) {
+ $encryptedAssertion->toXML($e);
+ }
+
+ return $e;
+ }
+}
diff --git a/src/SAML2/XML/saml/Evidence.php b/src/SAML2/XML/saml/Evidence.php
new file mode 100644
index 000000000..5c5f0be7e
--- /dev/null
+++ b/src/SAML2/XML/saml/Evidence.php
@@ -0,0 +1,14 @@
+schema = dirname(__FILE__, 5) . '/schemas/saml-schema-assertion-2.0.xsd';
+
+ $this->testedClass = Evidence::class;
+
+ $this->xmlRepresentation = DOMDocumentFactory::fromFile(
+ dirname(__FILE__, 4) . '/resources/xml/saml_Evidence.xml',
+ );
+
+ $this->assertionIDRef = DOMDocumentFactory::fromFile(
+ dirname(__FILE__, 4) . '/resources/xml/saml_AssertionIDRef.xml',
+ );
+
+ $this->assertionURIRef = DOMDocumentFactory::fromFile(
+ dirname(__FILE__, 4) . '/resources/xml/saml_AssertionURIRef.xml',
+ );
+
+ $this->assertion = DOMDocumentFactory::fromFile(
+ dirname(__FILE__, 4) . '/resources/xml/saml_Assertion.xml',
+ );
+
+ $this->encryptedAssertion = DOMDocumentFactory::fromFile(
+ dirname(__FILE__, 4) . '/resources/xml/saml_EncryptedAssertion.xml',
+ );
+ }
+
+
+ /**
+ */
+ public function testMarshalling(): void
+ {
+ $evidence = new Evidence(
+ [AssertionIDRef::fromXML($this->assertionIDRef->documentElement)],
+ [AssertionURIRef::fromXML($this->assertionURIRef->documentElement)],
+ [Assertion::fromXML($this->assertion->documentElement)],
+ [EncryptedAssertion::fromXML($this->encryptedAssertion->documentElement)],
+ );
+
+ $this->assertFalse($evidence->isEmptyElement());
+
+ $this->assertEquals(
+ $this->xmlRepresentation->saveXML($this->xmlRepresentation->documentElement),
+ strval($evidence),
+ );
+ }
+
+
+ /**
+ */
+ public function testMarshallingWithNoContent(): void
+ {
+ $evidence = new Evidence();
+ $this->assertEquals(
+ '',
+ strval($evidence)
+ );
+ $this->assertTrue($evidence->isEmptyElement());
+ }
+
+
+ /**
+ */
+ public function testUnmarshalling(): void
+ {
+ $evidence = Evidence::fromXML($this->xmlRepresentation->documentElement);
+
+ $this->assertEquals(
+ $this->xmlRepresentation->saveXML($this->xmlRepresentation->documentElement),
+ strval($evidence),
+ );
+ }
+}
diff --git a/tests/resources/xml/saml_Evidence.xml b/tests/resources/xml/saml_Evidence.xml
new file mode 100644
index 000000000..fdb888884
--- /dev/null
+++ b/tests/resources/xml/saml_Evidence.xml
@@ -0,0 +1,59 @@
+
+ _Test
+ urn:x-simplesamlphp:reference
+
+ Provider
+
+ SomeNameIDValue
+
+ SomeOtherNameIDValue
+
+
+
+
+
+ https://simplesamlphp.org/sp/metadata
+
+
+
+
+
+ urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
+
+
+
+
+ 1
+
+
+ 1
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+ sNLWjwyj/R0oPwSgNnqowahiOwM0YU3YaH3jsH0t2YUDcHkcgouvW5x6YbNdgvGq0ImsNrkjI//0hrL4HvrOX33+DkhCo2FX5+a7UCdftfBfSjvt0houF8z3Zq/XOm6HxBUbWt5MULYpMKMZ9iAY6+raydxk2tFWgnAyHaBfzvU=
+
+
+
+
+
+ self::xenc:CipherValue[@Id="example1"]
+
+
+
+
+
+ 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
+
+
+
+