diff --git a/src/Schema/CustomAttribute.php b/src/Schema/CustomAttribute.php index b04833fb..453edc88 100644 --- a/src/Schema/CustomAttribute.php +++ b/src/Schema/CustomAttribute.php @@ -21,7 +21,7 @@ class CustomAttribute public function __construct( string $namespaceURI, string $name, - string $value + string $value, ) { $this->namespaceURI = $namespaceURI; $this->name = $name; diff --git a/src/Schema/Schema.php b/src/Schema/Schema.php index de4b4e04..1c6d22a2 100644 --- a/src/Schema/Schema.php +++ b/src/Schema/Schema.php @@ -23,7 +23,7 @@ protected function findSomethingNoThrow( string $getter, string $name, ?string $namespace = null, - array &$calling = [] + array &$calling = [], ): ?SchemaItem { $calling[spl_object_hash($this)] = true; $cid = "$getter, $name, $namespace"; @@ -62,7 +62,7 @@ protected function findSomethingNoThrowSchemas( string $getter, string $name, ?string $namespace = null, - array &$calling = [] + array &$calling = [], ): ?SchemaItem { foreach ($schemas as $childSchema) { if (!isset($calling[spl_object_hash($childSchema)])) { diff --git a/src/SchemaReader.php b/src/SchemaReader.php index fe70157d..791518ce 100644 --- a/src/SchemaReader.php +++ b/src/SchemaReader.php @@ -151,7 +151,7 @@ public function addKnownNamespaceSchemaLocation(string $namespace, string $locat private function loadAttributeGroup( Schema $schema, - \DOMElement $node + \DOMElement $node, ): \Closure { $attGroup = new AttributeGroup($schema, $node->getAttribute('name')); $attGroup->setDoc($this->getDocumentation($node)); @@ -187,7 +187,7 @@ function (\DOMElement $node, \DOMElement $childNode) use ($schema, $attGroup): v private function getAttributeFromAttributeOrRef( \DOMElement $childNode, Schema $schema, - \DOMElement $node + \DOMElement $node, ): AttributeItem { if ($childNode->hasAttribute('ref')) { $attributeDef = $this->findAttributeItem($schema, $node, $childNode->getAttribute('ref')); @@ -270,7 +270,7 @@ private function loadAttributeOrElementDef( Schema $schema, \DOMElement $node, \DOMElement $childNode, - bool $isAttribute + bool $isAttribute, ): \Closure { $name = $childNode->getAttribute('name'); if ($isAttribute) { @@ -463,7 +463,7 @@ private function loadSequenceChildNode( \DOMElement $node, \DOMElement $childNode, ?int $max, - ?int $min = null + ?int $min = null, ): void { switch ($childNode->localName) { case 'sequence': @@ -518,7 +518,7 @@ private function loadSequenceChildNodeLoadElement( \DOMElement $node, \DOMElement $childNode, ?int $max, - ?int $min + ?int $min, ): void { $schema = $elementContainer->getSchema(); if ($childNode->hasAttribute('ref')) { @@ -551,7 +551,7 @@ private function loadSequenceChildNodeLoadAny( \DOMElement $node, \DOMElement $childNode, ?int $max, - ?int $min + ?int $min, ): void { $schema = $elementContainer->getSchema(); $element = $this->createAnyElement($schema, $childNode); @@ -570,7 +570,7 @@ private function resolveSubstitutionGroup( Schema $schema, \DOMElement $node, \DOMElement $childNode, - AbstractElementSingle $element + AbstractElementSingle $element, ): void { if ($childNode->hasAttribute('substitutionGroup')) { $substitutionGroup = $childNode->getAttribute('substitutionGroup'); @@ -583,7 +583,7 @@ private function addGroupAsElement( Schema $schema, \DOMElement $node, \DOMElement $childNode, - ElementContainer $elementContainer + ElementContainer $elementContainer, ): void { $referencedGroup = $this->findGroup( $schema, @@ -598,7 +598,7 @@ private function addGroupAsElement( private function loadChoiceWithChildren( Schema $schema, \DOMElement $node, - ElementContainer $elementContainer + ElementContainer $elementContainer, ): void { $choice = $this->createChoice($schema, $node); $elementContainer->addElement($choice); @@ -732,7 +732,7 @@ private function loadComplexTypeFromChildNode( BaseComplexType $type, \DOMElement $node, \DOMElement $childNode, - Schema $schema + Schema $schema, ): void { switch ($childNode->localName) { case 'sequence': @@ -818,7 +818,7 @@ function (SimpleType $list) use ($type): void { private function findSomeType( SchemaItem $fromThis, \DOMElement $node, - string $attributeName + string $attributeName, ): SchemaItem { return $this->findSomeTypeFromAttribute( $fromThis, @@ -830,7 +830,7 @@ private function findSomeType( private function findSomeTypeFromAttribute( SchemaItem $fromThis, \DOMElement $node, - string $attributeName + string $attributeName, ): SchemaItem { return $this->findType( $fromThis->getSchema(), @@ -919,7 +919,7 @@ private function findAndSetSomeBase(Type $type, Base $setBaseOnThis, \DOMElement private function loadExtensionChildNodes( BaseComplexType $type, - \DOMElement $node + \DOMElement $node, ): void { self::againstDOMNodeList( $node, @@ -941,7 +941,7 @@ function (\DOMElement $node, \DOMElement $childNode) use ($type): void { private function loadChildAttributesAndAttributeGroups( BaseComplexType $type, \DOMElement $node, - \DOMElement $childNode + \DOMElement $childNode, ): void { switch ($childNode->localName) { case 'attribute': @@ -974,7 +974,7 @@ private function loadRestriction(Type $type, \DOMElement $node): void $node, function ( \DOMElement $node, - \DOMElement $childNode + \DOMElement $childNode, ) use ( $type, $restriction @@ -995,7 +995,7 @@ function (Type $restType) use ($restriction): void { private function loadRestrictionChildNodes( Type $type, Restriction $restriction, - \DOMElement $node + \DOMElement $node, ): void { self::againstDOMNodeList( $node, @@ -1032,11 +1032,17 @@ private static function splitParts(\DOMElement $node, string $typeName): array [$prefix, $name] = explode(':', $typeName); } - /** - * @psalm-suppress PossiblyNullArgument - */ + // Get namespace URI for prefix. If prefix is null, it will return the default namespace $namespace = $node->lookupNamespaceUri($prefix); + // If no namespace is found, throw an exception only if a prefix was provided. + // If no prefix was provided and the above lookup failed, this means that there + // was no defalut namespace defined, making the element part of no namespace. + // In this case, we should not throw an exception since this is valid xml. + if (!$namespace && null !== $prefix) { + throw new TypeException(sprintf("Can't find namespace for prefix '%s', at line %d in %s ", $prefix, $node->getLineNo(), $node->ownerDocument->documentURI)); + } + return [ $name, $namespace, @@ -1048,11 +1054,6 @@ private function findAttributeItem(Schema $schema, \DOMElement $node, string $ty { [$name, $namespace] = self::splitParts($node, $typeName); - /** - * @var string|null $namespace - */ - $namespace = $namespace ?: $schema->getTargetNamespace(); - try { /** * @var AttributeItem $out @@ -1069,11 +1070,6 @@ private function findAttributeGroup(Schema $schema, \DOMElement $node, string $t { [$name, $namespace] = self::splitParts($node, $typeName); - /** - * @var string|null $namespace - */ - $namespace = $namespace ?: $schema->getTargetNamespace(); - try { /** * @var AttributeGroup $out @@ -1090,11 +1086,6 @@ private function findElement(Schema $schema, \DOMElement $node, string $typeName { [$name, $namespace] = self::splitParts($node, $typeName); - /** - * @var string|null $namespace - */ - $namespace = $namespace ?: $schema->getTargetNamespace(); - try { return $schema->findElement((string) $name, $namespace); } catch (TypeNotFoundException $e) { @@ -1106,11 +1097,6 @@ private function findGroup(Schema $schema, \DOMElement $node, string $typeName): { [$name, $namespace] = self::splitParts($node, $typeName); - /** - * @var string|null $namespace - */ - $namespace = $namespace ?: $schema->getTargetNamespace(); - try { /** * @var Group $out @@ -1127,11 +1113,6 @@ private function findType(Schema $schema, \DOMElement $node, string $typeName): { [$name, $namespace] = self::splitParts($node, $typeName); - /** - * @var string|null $namespace - */ - $namespace = $namespace ?: $schema->getTargetNamespace(); - $tryFindType = static function (Schema $schema, string $name, ?string $namespace): ?SchemaItem { try { return $schema->findType($name, $namespace); @@ -1199,13 +1180,17 @@ private function fillItemNonLocalType(Item $element, \DOMElement $node): void */ $type = $this->findSomeType($element, $node, 'type'); } else { + $prefix = $node->lookupPrefix(self::XSD_NS); + if ($prefix) { + $prefix .= ':'; + } /** * @var Type */ $type = $this->findSomeTypeFromAttribute( $element, $node, - $node->lookupPrefix(self::XSD_NS) . ':anyType' + $prefix . 'anyType' ); } @@ -1214,7 +1199,7 @@ private function fillItemNonLocalType(Item $element, \DOMElement $node): void private function loadImport( Schema $schema, - \DOMElement $node + \DOMElement $node, ): \Closure { $namespace = $node->getAttribute('namespace'); $schemaLocation = $node->getAttribute('schemaLocation'); @@ -1268,7 +1253,7 @@ private function createOrUseSchemaForNs(Schema $schema, string $namespace): Sche private function loadImportFresh( string $namespace, Schema $schema, - string $file + string $file, ): \Closure { return function () use ($namespace, $schema, $file): void { $dom = $this->getDOM( @@ -1554,7 +1539,7 @@ private function addAttributeFromAttributeOrRef( BaseComplexType $type, \DOMElement $childNode, Schema $schema, - \DOMElement $node + \DOMElement $node, ): void { $attribute = $this->getAttributeFromAttributeOrRef( $childNode, @@ -1569,7 +1554,7 @@ private function findSomethingLikeAttributeGroup( Schema $schema, \DOMElement $node, \DOMElement $childNode, - AttributeContainer $addToThis + AttributeContainer $addToThis, ): void { $attribute = $this->findAttributeGroup($schema, $node, $childNode->getAttribute('ref')); $addToThis->addAttribute($attribute); @@ -1600,7 +1585,7 @@ private function setLoadedSchema(string $namespace, Schema $schema): void private function setSchemaThingsFromNode( Schema $schema, \DOMElement $node, - ?Schema $parent = null + ?Schema $parent = null, ): void { $schema->setDoc($this->getDocumentation($node)); diff --git a/tests/AttributesTest.php b/tests/AttributesTest.php index b303c0c1..c2ea0a22 100644 --- a/tests/AttributesTest.php +++ b/tests/AttributesTest.php @@ -18,7 +18,7 @@ public function testBase(): void { $schema = $this->reader->readString( ' - + @@ -101,22 +101,22 @@ public function testAttributeUseOverriding(): void { $schema = $this->reader->readString( ' - + - + - + - + diff --git a/tests/ChoiceTest.php b/tests/ChoiceTest.php index 0572e06e..bf479011 100644 --- a/tests/ChoiceTest.php +++ b/tests/ChoiceTest.php @@ -15,14 +15,14 @@ public function testChoiceSimple(): void { $schema = $this->reader->readString( ' - + - - - + + + @@ -33,7 +33,7 @@ public function testChoiceSimple(): void - + @@ -61,14 +61,14 @@ public function testChoiceOptional(): void { $schema = $this->reader->readString( ' - + - - - + + + @@ -79,7 +79,7 @@ public function testChoiceOptional(): void - + @@ -107,14 +107,14 @@ public function testChoiceOptionalElement(): void { $schema = $this->reader->readString( ' - + - - - + + + @@ -125,7 +125,7 @@ public function testChoiceOptionalElement(): void - + @@ -154,14 +154,14 @@ public function testChoiceUnbounded(): void { $schema = $this->reader->readString( ' - + - - - + + + @@ -172,7 +172,7 @@ public function testChoiceUnbounded(): void - + @@ -200,28 +200,28 @@ public function testChoiceNested(): void { $schema = $this->reader->readString( ' - + - + - - + + - + - - + + - - + + @@ -238,7 +238,7 @@ public function testChoiceNested(): void - + diff --git a/tests/ElementsTest.php b/tests/ElementsTest.php index 990d2078..fc8b5eb1 100644 --- a/tests/ElementsTest.php +++ b/tests/ElementsTest.php @@ -19,7 +19,7 @@ public function testBase(): void { $schema = $this->reader->readString( ' - + @@ -67,19 +67,19 @@ public function testGroupOccurrences($item, $min, $max): void { $schema = $this->reader->readString( ' - + - - + + - - + + - - + + - + @@ -201,10 +201,10 @@ public function testGroupRefOccurrences(): void { $schema = $this->reader->readString( ' - + - + diff --git a/tests/RestrictionsTest.php b/tests/RestrictionsTest.php index 32e817a8..d2dec2f4 100644 --- a/tests/RestrictionsTest.php +++ b/tests/RestrictionsTest.php @@ -401,7 +401,7 @@ public function testRestrictionOverridingAttribute(): void { $schema = $this->reader->readString( ' - + @@ -416,7 +416,7 @@ public function testRestrictionOverridingAttribute(): void - + @@ -426,7 +426,7 @@ public function testRestrictionOverridingAttribute(): void - + @@ -458,7 +458,7 @@ public function testRestrictionInRestrictionOverridingAttribute(): void { $schema = $this->reader->readString( ' - + @@ -473,7 +473,7 @@ public function testRestrictionInRestrictionOverridingAttribute(): void - + @@ -482,14 +482,14 @@ public function testRestrictionInRestrictionOverridingAttribute(): void - + - + @@ -523,7 +523,7 @@ public function testAttributeInExtensionInRestriction(): void { $schema = $this->reader->readString( ' - + @@ -535,20 +535,20 @@ public function testAttributeInExtensionInRestriction(): void - + - + - + @@ -583,7 +583,7 @@ public function testElementOverrideInRestriction(): void { $schema = $this->reader->readString( ' - + diff --git a/tests/SchemaTest.php b/tests/SchemaTest.php index 824de435..0e247440 100644 --- a/tests/SchemaTest.php +++ b/tests/SchemaTest.php @@ -5,6 +5,7 @@ namespace GoetasWebservices\XML\XSDReader\Tests; use GoetasWebservices\XML\XSDReader\Exception\IOException; +use GoetasWebservices\XML\XSDReader\Exception\TypeException; use GoetasWebservices\XML\XSDReader\Schema\Attribute\AttributeDef; use GoetasWebservices\XML\XSDReader\Schema\Attribute\Group as AttributeGroup; use GoetasWebservices\XML\XSDReader\Schema\Element\ElementDef; @@ -97,9 +98,9 @@ public function testBase(): void { $schema = $this->reader->readString( ' - + - + @@ -131,9 +132,9 @@ public function testMultipleSchemasInSameFile(): void $file = 'schema.xsd'; $schema1 = $this->reader->readString( ' - + - + @@ -171,9 +172,9 @@ public function testMultipleSchemasInSameFileWithSameTargetNamespace(): void $file = 'schema.xsd'; $schema1 = $this->reader->readString( ' - + - + ', $file ); @@ -187,9 +188,9 @@ public function testMultipleSchemasInSameFileWithSameTargetNamespace(): void // Now use a second schema which uses the same targetNamespace $schema2 = $this->reader->readString( ' - + - + ', $file ); @@ -201,7 +202,7 @@ public function testMultipleSchemasInSameFileWithSameTargetNamespace(): void self::assertInstanceOf(ElementDef::class, $schema2->findElement('myElement2', 'http://www.example.com')); self::assertCount(1, $schema1->getTypes()); - self::assertCount(1, $schema2->getElements()); + self::assertCount(1, $schema1->getElements()); self::assertInstanceOf(ElementDef::class, $schema1->findElement('myElement2', 'http://www.example.com')); } @@ -209,10 +210,10 @@ public function testGroupRefInType(): void { $schema1 = $this->reader->readString( ' - + - + @@ -267,4 +268,67 @@ public function testDependentReferencingSchemes(): void self::assertInstanceOf(ElementDef::class, $schema->findElement('CategoryList', 'http://tempuri.org/2')); self::assertInstanceOf(ComplexType::class, $schema->findType('Categories', 'http://tempuri.org/1')); } + + public function testDefaultNamespaceForSchema(): void + { + // Default namespace is provided. Validation does not fail. + $schema1 = $this->reader->readString( + ' + + + + + + + + + + + + + ' + ); + + // Default namespace is provided but does not provide the myGroup component. Validation fails. + $this->expectException(TypeException::class); + $this->expectExceptionMessage("Can't find group named {http://www.example2.com}#myGroup, at line 4 in schema.xsd "); + $schema1 = $this->reader->readString( + ' + + + + + + + + + + + + + ' + ); + } + + public function testUnknownNamespaceForSchema(): void + { + $this->expectException(TypeException::class); + $this->expectExceptionMessage("Can't find namespace for prefix 'ex2', at line 4 in schema.xsd "); + $schema1 = $this->reader->readString( + ' + + + + + + + + + + + + + ' + ); + } } diff --git a/tests/SubstitutionGroupTest.php b/tests/SubstitutionGroupTest.php index f7908d96..d2fa80cc 100644 --- a/tests/SubstitutionGroupTest.php +++ b/tests/SubstitutionGroupTest.php @@ -12,22 +12,22 @@ public function testSubstitutionGroup(): void { $schema = $this->reader->readString( ' - + - - - + + + - + - + @@ -58,22 +58,22 @@ public function testSubstitutionGroupChangedOrder(): void { $schema = $this->reader->readString( ' - + - - - + + + - + - + @@ -104,25 +104,25 @@ public function testSubstitutionGroup2(): void { $schema = $this->reader->readString( ' - + - + - - + + - + - + diff --git a/tests/TypeInheritanceTest.php b/tests/TypeInheritanceTest.php index ba32a36f..10a751f8 100644 --- a/tests/TypeInheritanceTest.php +++ b/tests/TypeInheritanceTest.php @@ -54,24 +54,24 @@ public function testBase(): void { $schema = $this->reader->readString( ' - + - + - + - + ' diff --git a/tests/TypesTest.php b/tests/TypesTest.php index b4173ab9..030fcd87 100644 --- a/tests/TypesTest.php +++ b/tests/TypesTest.php @@ -278,14 +278,14 @@ public function testComplex(): void { $schema = $this->reader->readString( ' - + - + @@ -365,7 +365,7 @@ public function testComplexSimpleContent(): void { $schema = $this->reader->readString( ' - + diff --git a/tests/foo bar/referenced.xsd b/tests/foo bar/referenced.xsd index f83292f3..036718c9 100644 --- a/tests/foo bar/referenced.xsd +++ b/tests/foo bar/referenced.xsd @@ -1,6 +1,6 @@ - + - +