Skip to content

Commit

Permalink
basic redefine support
Browse files Browse the repository at this point in the history
based on goetas-webservices#17
by @kstasik

ported code to latest version/rebased on master.

implements `<xsd:redefine ...>` https://www.w3.org/TR/xmlschema11-1/#modify-schema
  • Loading branch information
Kacper Stasik authored and cebe committed Apr 2, 2019
1 parent 3f6526d commit c7c8758
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 0 deletions.
25 changes: 25 additions & 0 deletions src/SchemaReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,9 @@ function (
case 'import':
$callback = $this->loadImport($schema, $childNode);
break;
case 'redefine':
$callback = $this->loadRedefine($schema, $childNode);
break;
case 'element':
$callback = $this->loadElementDef($schema, $childNode);
break;
Expand Down Expand Up @@ -1144,6 +1147,28 @@ private function loadImport(
return $this->loadImportFresh($namespace, $schema, $file);
}

private function loadRedefine(Schema $schema, DOMElement $node)
{
$base = urldecode($node->ownerDocument->documentURI);
$file = UrlUtils::resolveRelativeUrl($base, $node->getAttribute('schemaLocation'));

if (isset($this->loadedFiles[$file])) {
/* @var $redefined Schema */
$redefined = clone $this->loadedFiles[$file];

if($schema->getTargetNamespace() !== $redefined->getTargetNamespace()){
$redefined->setTargetNamespace($schema->getTargetNamespace());
}

$schema->addSchema($redefined);

return function (): void {
};
}

return $this->loadImportFresh($schema->getTargetNamespace(), $schema, $file);
}

private function createOrUseSchemaForNs(
Schema $schema,
string $namespace
Expand Down
66 changes: 66 additions & 0 deletions tests/RedefineTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php
namespace GoetasWebservices\XML\XSDReader\Tests;

class RedefineTest extends BaseTest
{
public function testBase()
{
$remoteSchema = $this->reader->readString(
'
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="personName">
<xs:sequence>
<xs:element name="title" minOccurs="0"/>
<xs:element name="forename" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:element name="addressee" type="personName"/>
</xs:schema>', 'http://www.example.com/xsd.xsd');


$schema = $this->reader->readString(
'
<xs:schema targetNamespace="http://www.user.com" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ex="http://www.example.com">
<xs:redefine schemaLocation="http://www.example.com/xsd.xsd">
<xs:complexType name="personName">
<xs:complexContent>
<xs:extension base="personName">
<xs:sequence>
<xs:element name="generation" minOccurs="0"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:redefine>
<xs:element name="author" type="personName"/>
</xs:schema>');

// check if schema is not included
// we don't want to redefine original schema
$this->assertNotContains($remoteSchema, $schema->getSchemas(), '', true);

/* @var $localAttr \GoetasWebservices\XML\XSDReader\Schema\Element\ElementDef */

// it should inherit namespace of main schema
$localAttr = $schema->findElement("addressee", "http://www.user.com");
$this->assertNotNull($localAttr);

// find author element
$localAttr = $schema->findElement("author", "http://www.user.com");
$this->assertNotNull($localAttr);

/* @var $type \GoetasWebservices\XML\XSDReader\Schema\Type\ComplexType */
$type = $localAttr->getType();

$this->assertInstanceOf('\GoetasWebservices\XML\XSDReader\Schema\Type\ComplexType', $type);

$children = array();
foreach($type->getElements() as $element){
$children[] = $element->getName();
}

$this->assertContains('generation', $children);
}
}

0 comments on commit c7c8758

Please sign in to comment.