diff --git a/composer.json b/composer.json index c9ad66a..aca1439 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,8 @@ ], "autoload": { "psr-4": { - "SimpleSAML\\XML\\": "src/" + "SimpleSAML\\XML\\": "src/", + "SimpleSAML\\XML\\xsd\\": "src/XML/xsd" } }, "autoload-dev": { diff --git a/resources/schemas/XMLSchema.xsd b/resources/schemas/XMLSchema.xsd new file mode 100644 index 0000000..f0c9505 --- /dev/null +++ b/resources/schemas/XMLSchema.xsd @@ -0,0 +1,2534 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ]> + + + + Part 1 version: Id: structures.xsd,v 1.2 2004/01/15 11:34:25 ht Exp + Part 2 version: Id: datatypes.xsd,v 1.3 2004/01/23 18:11:13 ht Exp + + + + + + The schema corresponding to this document is normative, + with respect to the syntactic constraints it expresses in the + XML Schema language. The documentation (within <documentation> elements) + below, is not normative, but rather highlights important aspects of + the W3C Recommendation of which this is a part + + + + + The simpleType element and all of its members are defined + towards the end of this schema document + + + + + + Get access to the xml: attribute groups for xml:lang + as declared on 'schema' and 'documentation' below + + + + + + + + This type is extended by almost all schema types + to allow attributes from other namespaces to be + added to user schemas. + + + + + + + + + + + + + This type is extended by all types which allow annotation + other than <schema> itself + + + + + + + + + + + + + + + + This group is for the + elements which occur freely at the top level of schemas. + All of their types are based on the "annotated" type by extension. + + + + + + + + + + + + + This group is for the + elements which can self-redefine (see <redefine> below). + + + + + + + + + + + + + A utility type, not for public use + + + + + + + + + + + A utility type, not for public use + + + + + + + + + + + A utility type, not for public use + + #all or (possibly empty) subset of {extension, restriction} + + + + + + + + + + + + + + + + + A utility type, not for public use + + + + + + + + + + + + + A utility type, not for public use + + #all or (possibly empty) subset of {extension, restriction, list, union} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + for maxOccurs + + + + + + + + + + + + for all particles + + + + + + + for element, group and attributeGroup, + which both define and reference + + + + + + + + 'complexType' uses this + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This branch is short for + <complexContent> + <restriction base="xs:anyType"> + ... + </restriction> + </complexContent> + + + + + + + + + + + + + + + Will be restricted to required or forbidden + + + + + + Not allowed if simpleContent child is chosen. + May be overriden by setting on complexContent child. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This choice is added simply to + make this a valid restriction per the REC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Overrides any setting on complexType parent. + + + + + + + + + + + + + + + This choice is added simply to + make this a valid restriction per the REC + + + + + + + + + + + + + + + + + No typeDefParticle group reference + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A utility type, not for public use + + #all or (possibly empty) subset of {substitution, extension, + restriction} + + + + + + + + + + + + + + + + + + + + + + + + + The element element can be used either + at the top level to define an element-type binding globally, + or within a content model to either reference a globally-defined + element or type or declare an element-type binding locally. + The ref form is not allowed at the top level. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + group type for explicit groups, named top-level groups and + group references + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + group type for the three kinds of group + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This choice with min/max is here to + avoid a pblm with the Elt:All/Choice/Seq + Particle derivation constraint + + + + + + + + + + restricted max/min + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Only elements allowed inside + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + simple type for the value of the 'namespace' attr of + 'any' and 'anyAttribute' + + + + Value is + ##any - - any non-conflicting WFXML/attribute at all + + ##other - - any non-conflicting WFXML/attribute from + namespace other than targetNS + + ##local - - any unqualified non-conflicting WFXML/attribute + + one or - - any non-conflicting WFXML/attribute from + more URI the listed namespaces + references + (space separated) + + ##targetNamespace or ##local may appear in the above list, to + refer to the targetNamespace of the enclosing + schema or an absent targetNamespace respectively + + + + + + A utility type, not for public use + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A subset of XPath expressions for use +in selectors + A utility type, not for public +use + + + + The following pattern is intended to allow XPath + expressions per the following EBNF: + Selector ::= Path ( '|' Path )* + Path ::= ('.//')? Step ( '/' Step )* + Step ::= '.' | NameTest + NameTest ::= QName | '*' | NCName ':' '*' + child:: is also allowed + + + + + + + + + + + + + + + + + + + + + + + A subset of XPath expressions for use +in fields + A utility type, not for public +use + + + + The following pattern is intended to allow XPath + expressions per the same EBNF as for selector, + with the following change: + Path ::= ('.//')? ( Step '/' )* ( Step | '@' NameTest ) + + + + + + + + + + + + + + + + + + + + + + + + + + + The three kinds of identity constraints, all with + type of or derived from 'keybase'. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A utility type, not for public use + + A public identifier, per ISO 8879 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + notations for use within XML Schema schemas + + + + + + + + + Not the real urType, but as close an approximation as we can + get in the XML representation + + + + + + + + + + First the built-in primitive datatypes. These definitions are for + information only, the real built-in definitions are magic. + + + + For each built-in datatype in this schema (both primitive and + derived) can be uniquely addressed via a URI constructed + as follows: + 1) the base URI is the URI of the XML Schema namespace + 2) the fragment identifier is the name of the datatype + + For example, to address the int datatype, the URI is: + + http://www.w3.org/2001/XMLSchema#int + + Additionally, each facet definition element can be uniquely + addressed via a URI constructed as follows: + 1) the base URI is the URI of the XML Schema namespace + 2) the fragment identifier is the name of the facet + + For example, to address the maxInclusive facet, the URI is: + + http://www.w3.org/2001/XMLSchema#maxInclusive + + Additionally, each facet usage in a built-in datatype definition + can be uniquely addressed via a URI constructed as follows: + 1) the base URI is the URI of the XML Schema namespace + 2) the fragment identifier is the name of the datatype, followed + by a period (".") followed by the name of the facet + + For example, to address the usage of the maxInclusive facet in + the definition of int, the URI is: + + http://www.w3.org/2001/XMLSchema#int.maxInclusive + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NOTATION cannot be used directly in a schema; rather a type + must be derived from it by specifying at least one enumeration + facet whose value is the name of a NOTATION declared in the + schema. + + + + + + + + + + Now the derived primitive types + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pattern specifies the content of section 2.12 of XML 1.0e2 + and RFC 3066 (Revised version of RFC 1766). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pattern matches production 7 from the XML spec + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + pattern matches production 5 from the XML spec + + + + + + + + + + + + + + + pattern matches production 4 from the Namespaces in XML spec + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A utility type, not for public use + + + + + + + + + + + + + + + + + + + + + + #all or (possibly empty) subset of {restriction, union, list} + + + A utility type, not for public use + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Can be restricted to required or forbidden + + + + + + + + + + + + + + + + + + Required at the top level + + + + + + + + + + + + + + + + + + + Forbidden when nested + + + + + + + + + + + + + + + + + + + We should use a substitution group for facets, but + that's ruled out because it would allow users to + add their own, which we're not ready for yet. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + base attribute and simpleType child are mutually + exclusive, but one or other is required + + + + + + + + + + + + + + + + itemType attribute and simpleType child are mutually + exclusive, but one or other is required + + + + + + + + + + + + + + + + + + memberTypes attribute must be non-empty or there must be + at least one simpleType child + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/XML/element.registry.php b/src/XML/element.registry.php new file mode 100644 index 0000000..ff665c7 --- /dev/null +++ b/src/XML/element.registry.php @@ -0,0 +1,12 @@ + [ + 'annotation' => '\SimpleSAML\XML\xsd\Annotation', + 'appinfo' => '\SimpleSAML\XML\xsd\Appinfo', + 'documentation' => '\SimpleSAML\XML\xsd\Documentation', + 'import' => '\SimpleSAML\XML\xsd\Import', + ], +]; diff --git a/src/XML/xsd/AbstractAnnotated.php b/src/XML/xsd/AbstractAnnotated.php new file mode 100644 index 0000000..2da564c --- /dev/null +++ b/src/XML/xsd/AbstractAnnotated.php @@ -0,0 +1,92 @@ + $namespacedAttributes + */ + public function __construct( + protected ?Annotation $annotation = null, + protected ?string $id, + array $namespacedAttributes = [], + ) { + Assert::nullOrValidNCName($id, SchemaViolationException::class); + + parent::__construct($namespacedAttributes); + } + + + /** + * Collect the value of the annotation-property + * + * @return \SimpleSAML\XML\xsd\Annotation|null + */ + public function getAnnotation(): ?Annotation + { + return $this->annotation; + } + + + /** + * Collect the value of the id-property + * + * @return string|null + */ + public function getId(): ?string + { + return $this->id; + } + + + /** + * Test if an object, at the state it's in, would produce an empty XML-element + * + * @return bool + */ + public function isEmptyElement(): bool + { + return parent::isEmptyElement() && + empty($this->getAnnotation()) && + empty($this->id); + } + + + /** + * Add this Annotated to an XML element. + * + * @param \DOMElement $parent The element we should append this Annotated to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = parent::toXML($parent); + + if ($this->getId() !== null) { + $e->setAttribute('id', $this->getId()); + } + + if ($this->getAnnotation() !== null) { + $annotation->toXML($e); + } + + return $e; + } +} diff --git a/src/XML/xsd/AbstractOpenAttrs.php b/src/XML/xsd/AbstractOpenAttrs.php new file mode 100644 index 0000000..9f40111 --- /dev/null +++ b/src/XML/xsd/AbstractOpenAttrs.php @@ -0,0 +1,63 @@ + $namespacedAttributes + */ + public function __construct( + array $namespacedAttributes = [], + ) { + $this->setAttributesNS($namespacedAttributes); + } + + + /** + * Test if an object, at the state it's in, would produce an empty XML-element + * + * @return bool + */ + public function isEmptyElement(): bool + { + return empty($this->getAttributesNS()); + } + + + /** + * Add this OpenAttrs to an XML element. + * + * @param \DOMElement $parent The element we should append this OpenAttrs to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = parent::instantiateParentElement($parent); + + foreach ($this->getAttributesNS() as $attr) { + $attr->toXML($e); + } + + return $e; + } +} diff --git a/src/XML/xsd/AbstractXsdElement.php b/src/XML/xsd/AbstractXsdElement.php new file mode 100644 index 0000000..25a2f80 --- /dev/null +++ b/src/XML/xsd/AbstractXsdElement.php @@ -0,0 +1,22 @@ + $appinfo + * @param array<\SimpleSAML\XML\xsd\Documentation> $documentation + * @param string|null $id + * @param array<\SimpleSAML\XML\Attribute> $namespacedAttributes + */ + public function __construct( + protected array $appinfo, + protected array $documentation, + protected ?string $id, + array $namespacedAttributes = [], + ) { + Assert::allIsInstanceOf($appinfo, Appinfo::class, SchemaViolationException::class); + Assert::allIsInstanceOf($documentation, Documentation::class, SchemaViolationException::class); + Assert::nullOrValidNCName($id, SchemaViolationException::class); + + parent::__construct($namespacedAttributes); + } + + + /** + * Collect the value of the appinfo-property + * + * @return \SimpleSAML\XML\xsd\Appinfo[] + */ + public function getAppinfo(): array + { + return $this->appinfo; + } + + + /** + * Collect the value of the documentation-property + * + * @return \SimpleSAML\XML\xsd\Documentation[] + */ + public function getDocumentation(): array + { + return $this->documentation; + } + + + /** + * Collect the value of the id-property + * + * @return string|null + */ + public function getId(): ?string + { + return $this->id; + } + + + /** + * Test if an object, at the state it's in, would produce an empty XML-element + * + * @return bool + */ + public function isEmptyElement(): bool + { + return parent::isEmptyElement() && + empty($this->getAppinfo()) && + empty($this->getDocumentation()) && + empty($this->id); + } + + + /** + * Create a class from XML + * + * @param \DOMElement $xml + * @return static + */ + public static function fromXML(DOMElement $xml): static + { + Assert::same($xml->localName, static::getLocalName(), InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); + + return new static( + Appinfo::getChildrenOfClass($xml), + Documentation::getChildrenOfClass($xml), + self::getOptionalAttribute($xml, 'id', null), + self::getAttributesNSFromXML($xml), + ); + } + + + /** + * Add this Annotation to an XML element. + * + * @param \DOMElement $parent The element we should append this Annotation to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = parent::toXML($parent); + + if ($this->getId() !== null) { + $e->setAttribute('id', $this->getId()); + } + + foreach ($this->getAppinfo() as $appinfo) { + $appinfo->toXML($e); + } + + foreach ($this->getDocumentation() as $documentation) { + $documentation->toXML($e); + } + + return $e; + } +} diff --git a/src/XML/xsd/Appinfo.php b/src/XML/xsd/Appinfo.php new file mode 100644 index 0000000..cba778e --- /dev/null +++ b/src/XML/xsd/Appinfo.php @@ -0,0 +1,128 @@ + $namespacedAttributes + */ + final public function __construct( + protected DOMNodeList $content, + protected ?string $source = null, + array $namespacedAttributes = [], + ) { + Assert::nullOrValidURI($source); + $this->setAttributesNS($namespacedAttributes); + } + + + /** + * Get the content property. + * + * @return \DOMNodeList + */ + public function getContent(): DOMNodeList + { + return $this->content; + } + + + /** + * Get the source property. + * + * @return string|null + */ + public function getSource(): ?string + { + return $this->source; + } + + + /** + * Test if an object, at the state it's in, would produce an empty XML-element + * + * @return bool + */ + public function isEmptyElement(): bool + { + return empty($this->getContent()) + && empty($this->getSource()) + && empty($this->getAttributesNS()); + } + + + /** + * Create an instance of this object from its XML representation. + * + * @param \DOMElement $xml + * @return static + * + * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * if the qualified name of the supplied element is wrong + */ + public static function fromXML(DOMElement $xml): static + { + Assert::same($xml->localName, static::getLocalName(), InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); + + return new static( + $xml->childNodes, + self::getOptionalAttribute($xml, 'source', null), + self::getAttributesNSFromXML($xml), + ); + } + + + /** + * Add this Appinfo to an XML element. + * + * @param \DOMElement $parent The element we should append this Appinfo to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = parent::instantiateParentElement($parent); + + if ($this->getSource() !== null) { + $e->setAttribute('source', $this->getSource()); + } + + foreach ($this->getAttributesNS() as $attr) { + $attr->toXML($e); + } + + foreach ($this->getContent() as $i) { + $e->appendChild($e->ownerDocument->importNode($i, true)); + } + + return $e; + } +} diff --git a/src/XML/xsd/Documentation.php b/src/XML/xsd/Documentation.php new file mode 100644 index 0000000..829be48 --- /dev/null +++ b/src/XML/xsd/Documentation.php @@ -0,0 +1,158 @@ + $namespacedAttributes + */ + final public function __construct( + protected DOMNodeList $content, + protected ?string $lang = null, + protected ?string $source = null, + array $namespacedAttributes = [], + ) { + Assert::nullOrValidURI($source); + $this->setAttributesNS($namespacedAttributes); + } + + + /** + * Get the content property. + * + * @return \DOMNodeList + */ + public function getContent(): DOMNodeList + { + return $this->content; + } + + + /** + * Get the lang property. + * + * @return string|null + */ + public function getLang(): ?string + { + return $this->lang; + } + + + /** + * Get the source property. + * + * @return string|null + */ + public function getSource(): ?string + { + return $this->source; + } + + + /** + * Test if an object, at the state it's in, would produce an empty XML-element + * + * @return bool + */ + public function isEmptyElement(): bool + { + return empty($this->getContent()) + && empty($this->getLang()) + && empty($this->getSource()) + && empty($this->getAttributesNS()); + } + + + /** + * Create an instance of this object from its XML representation. + * + * @param \DOMElement $xml + * @return static + * + * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException + * if the qualified name of the supplied element is wrong + */ + public static function fromXML(DOMElement $xml): static + { + Assert::same($xml->localName, static::getLocalName(), InvalidDOMElementException::class); + Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class); + + $lang = null; + if ($xml->hasAttributeNS(C::NS_XML, 'lang')) { + $lang = $xml->getAttributeNS(C::NS_XML, 'lang'); + } + + return new static( + $xml->childNodes, + $lang, + self::getOptionalAttribute($xml, 'source', null), + self::getAttributesNSFromXML($xml), + ); + } + + + /** + * Add this Documentation to an XML element. + * + * @param \DOMElement $parent The element we should append this Documentation to. + * @return \DOMElement + */ + public function toXML(DOMElement $parent = null): DOMElement + { + $e = parent::instantiateParentElement($parent); + + if ($this->getSource() !== null) { + $e->setAttribute('source', $this->getSource()); + } + + if ($this->getLang() !== null) { + $e->setAttributeNS(C::NS_XML, 'xml:lang', $this->getLang()); + } + + foreach ($this->getAttributesNS() as $attr) { + $attr->toXML($e); + } + + foreach ($this->getContent() as $i) { + $e->appendChild($e->ownerDocument->importNode($i, true)); + } + + return $e; + } +} diff --git a/src/XML/xsd/FormChoiceTrait.php b/src/XML/xsd/FormChoiceTrait.php new file mode 100644 index 0000000..7f65e50 --- /dev/null +++ b/src/XML/xsd/FormChoiceTrait.php @@ -0,0 +1,43 @@ +formChoice; + } + + + /** + * Set the value of the formChoice-property + * + * @param string $formChoice + */ + protected function setFormChoice(string $formChoice): void + { + Assert::regex($formChoice, '/\c+/', SchemaViolationException::class); + $this->formChoice = $formChoice; + } +} diff --git a/tests/XML/xsd/AnnotationTest.php b/tests/XML/xsd/AnnotationTest.php new file mode 100644 index 0000000..41c6564 --- /dev/null +++ b/tests/XML/xsd/AnnotationTest.php @@ -0,0 +1,108 @@ +appendChild($text); + + $otherAppinfoDocument = DOMDocumentFactory::create(); + $otherText = new DOMText('Other Application Information'); + $otherAppinfoDocument->appendChild($otherText); + + $documentationDocument = DOMDocumentFactory::create(); + $text = new DOMText('Some Documentation'); + $documentationDocument->appendChild($text); + + $otherDocumentationDocument = DOMDocumentFactory::create(); + $text = new DOMText('Other Documentation'); + $otherDocumentationDocument->appendChild($text); + + $attr1 = new XMLAttribute('urn:x-simplesamlphp:namespace', 'ssp', 'attr1', 'value1'); + $attr2 = new XMLAttribute('urn:x-simplesamlphp:namespace', 'ssp', 'attr2', 'value2'); + $attr3 = new XMLAttribute('urn:x-simplesamlphp:namespace', 'ssp', 'attr3', 'value3'); + + $appinfo1 = new Appinfo($appinfoDocument->childNodes, 'urn:x-simplesamlphp:source', [$attr1]); + $appinfo2 = new Appinfo($otherAppinfoDocument->childNodes, 'urn:x-simplesamlphp:source', [$attr2]); + + $documentation1 = new Documentation( + $documentationDocument->childNodes, + 'nl', + 'urn:x-simplesamlphp:source', + [$attr1], + ); + $documentation2 = new Documentation( + $otherDocumentationDocument->childNodes, + 'nl', + 'urn:x-simplesamlphp:source', + [$attr2], + ); + + $annotation = new Annotation( + [$appinfo1, $appinfo2], + [$documentation1, $documentation2], + 'phpunit', + [$attr3], + ); + + $this->assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($annotation), + ); + } +} diff --git a/tests/XML/xsd/AppinfoTest.php b/tests/XML/xsd/AppinfoTest.php new file mode 100644 index 0000000..30315c0 --- /dev/null +++ b/tests/XML/xsd/AppinfoTest.php @@ -0,0 +1,69 @@ +appendChild($text); + + $attr1 = new XMLAttribute('urn:x-simplesamlphp:namespace', 'ssp', 'attr1', 'value1'); + $appinfo = new Appinfo($document->childNodes, 'urn:x-simplesamlphp:source', [$attr1]); + + $this->assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($appinfo), + ); + } +} diff --git a/tests/XML/xsd/DocumentationTest.php b/tests/XML/xsd/DocumentationTest.php new file mode 100644 index 0000000..a28676d --- /dev/null +++ b/tests/XML/xsd/DocumentationTest.php @@ -0,0 +1,69 @@ +appendChild($text); + + $attr1 = new XMLAttribute('urn:x-simplesamlphp:namespace', 'ssp', 'attr1', 'value1'); + $documentation = new Documentation($document->childNodes, 'nl', 'urn:x-simplesamlphp:source', [$attr1]); + + $this->assertEquals( + self::$xmlRepresentation->saveXML(self::$xmlRepresentation->documentElement), + strval($documentation), + ); + } +} diff --git a/tests/resources/xml/xsd/annotation.xml b/tests/resources/xml/xsd/annotation.xml new file mode 100644 index 0000000..9ec533b --- /dev/null +++ b/tests/resources/xml/xsd/annotation.xml @@ -0,0 +1,6 @@ + + Application Information + Other Application Information + Some Documentation + Other Documentation + diff --git a/tests/resources/xml/xsd/appinfo.xml b/tests/resources/xml/xsd/appinfo.xml new file mode 100644 index 0000000..48d1523 --- /dev/null +++ b/tests/resources/xml/xsd/appinfo.xml @@ -0,0 +1 @@ +Application Information diff --git a/tests/resources/xml/xsd/documentation.xml b/tests/resources/xml/xsd/documentation.xml new file mode 100644 index 0000000..dc0c01a --- /dev/null +++ b/tests/resources/xml/xsd/documentation.xml @@ -0,0 +1 @@ +Some Documentation