From 5022ff9715d6a3c94844e2b69421f4c889704d01 Mon Sep 17 00:00:00 2001 From: mkoehler Date: Mon, 18 Nov 2024 09:48:09 +0100 Subject: [PATCH 1/4] Fixed default namespace not being implemented correctly. --- src/SchemaReader.php | 43 ++++++++++++++----------------------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/src/SchemaReader.php b/src/SchemaReader.php index fe70157..0f91522 100644 --- a/src/SchemaReader.php +++ b/src/SchemaReader.php @@ -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 && $prefix !== null) { + 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' ); } From 42994611947bb798d05354e3f4f420a7d7868325 Mon Sep 17 00:00:00 2001 From: mkoehler Date: Mon, 18 Nov 2024 09:48:39 +0100 Subject: [PATCH 2/4] Updated tests to work with new way of dealing with default namespace --- tests/AttributesTest.php | 10 +++--- tests/ChoiceTest.php | 60 ++++++++++++++++----------------- tests/ElementsTest.php | 22 ++++++------ tests/RestrictionsTest.php | 24 ++++++------- tests/SchemaTest.php | 22 ++++++------ tests/SubstitutionGroupTest.php | 36 ++++++++++---------- tests/TypeInheritanceTest.php | 8 ++--- tests/TypesTest.php | 6 ++-- tests/foo bar/referenced.xsd | 4 +-- 9 files changed, 96 insertions(+), 96 deletions(-) diff --git a/tests/AttributesTest.php b/tests/AttributesTest.php index b303c0c..c2ea0a2 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 0572e06..bf47901 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 990d207..fc8b5eb 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 32e817a..d2dec2f 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 824de43..376a324 100644 --- a/tests/SchemaTest.php +++ b/tests/SchemaTest.php @@ -97,9 +97,9 @@ public function testBase(): void { $schema = $this->reader->readString( ' - + - + @@ -131,9 +131,9 @@ public function testMultipleSchemasInSameFile(): void $file = 'schema.xsd'; $schema1 = $this->reader->readString( ' - + - + @@ -171,9 +171,9 @@ public function testMultipleSchemasInSameFileWithSameTargetNamespace(): void $file = 'schema.xsd'; $schema1 = $this->reader->readString( ' - + - + ', $file ); @@ -187,9 +187,9 @@ public function testMultipleSchemasInSameFileWithSameTargetNamespace(): void // Now use a second schema which uses the same targetNamespace $schema2 = $this->reader->readString( ' - + - + ', $file ); @@ -201,7 +201,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 +209,10 @@ public function testGroupRefInType(): void { $schema1 = $this->reader->readString( ' - + - + diff --git a/tests/SubstitutionGroupTest.php b/tests/SubstitutionGroupTest.php index f7908d9..d2fa80c 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 ba32a36..10a751f 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 b4173ab..030fcd8 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 f83292f..036718c 100644 --- a/tests/foo bar/referenced.xsd +++ b/tests/foo bar/referenced.xsd @@ -1,6 +1,6 @@ - + - + From ebdc3b0c651867f1394dc1e8305e37ca4ff87552 Mon Sep 17 00:00:00 2001 From: mkoehler Date: Mon, 18 Nov 2024 11:24:58 +0100 Subject: [PATCH 3/4] Added new tests for testing default namespace and unknown namespace --- tests/SchemaTest.php | 64 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/tests/SchemaTest.php b/tests/SchemaTest.php index 376a324..0e24744 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; @@ -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( + ' + + + + + + + + + + + + + ' + ); + } } From 868afd16002e49e1972eb8a4cd4bba3cda7c963a Mon Sep 17 00:00:00 2001 From: mkoehler Date: Fri, 22 Nov 2024 22:29:17 +0100 Subject: [PATCH 4/4] Applied cs fixer rules --- src/Schema/CustomAttribute.php | 2 +- src/Schema/Schema.php | 4 ++-- src/SchemaReader.php | 44 +++++++++++++++++----------------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/Schema/CustomAttribute.php b/src/Schema/CustomAttribute.php index b04833f..453edc8 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 de4b4e0..1c6d22a 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 0f91522..791518c 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, @@ -1039,7 +1039,7 @@ private static function splitParts(\DOMElement $node, string $typeName): array // 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 && $prefix !== null) { + 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)); } @@ -1199,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'); @@ -1253,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( @@ -1539,7 +1539,7 @@ private function addAttributeFromAttributeOrRef( BaseComplexType $type, \DOMElement $childNode, Schema $schema, - \DOMElement $node + \DOMElement $node, ): void { $attribute = $this->getAttributeFromAttributeOrRef( $childNode, @@ -1554,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); @@ -1585,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));