Skip to content

Commit 1ccae4d

Browse files
author
Kacper Stasik
committed
1 parent 91f838b commit 1ccae4d

File tree

2 files changed

+106
-2
lines changed

2 files changed

+106
-2
lines changed

src/SchemaReader.php

+40-2
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,9 @@ private function schemaNode(Schema $schema, DOMElement $node, Schema $parent = n
164164
case 'import':
165165
$functions[] = $this->loadImport($schema, $childNode);
166166
break;
167+
case 'redefine':
168+
$functions[] = $this->loadRedefine($schema, $childNode);
169+
break;
167170
case 'element':
168171
$functions[] = $this->loadElementDef($schema, $childNode);
169172
break;
@@ -204,7 +207,7 @@ private function loadElement(Schema $schema, DOMElement $node)
204207

205208
$xp = new \DOMXPath($node->ownerDocument);
206209
$xp->registerNamespace('xs', 'http://www.w3.org/2001/XMLSchema');
207-
210+
208211
if ($xp->query('ancestor::xs:choice', $node)->length) {
209212
$element->setMin(0);
210213
}
@@ -639,6 +642,41 @@ private function fillItem(Item $element, DOMElement $node)
639642
}
640643
}
641644

645+
private function loadRedefine(Schema $schema, DOMElement $node)
646+
{
647+
$base = urldecode($node->ownerDocument->documentURI);
648+
$file = UrlUtils::resolveRelativeUrl($base, $node->getAttribute("schemaLocation"));
649+
650+
if (isset($this->loadedFiles[$file])) {
651+
/* @var $redefined Schema */
652+
$redefined = clone $this->loadedFiles[$file];
653+
654+
if($schema->getTargetNamespace() != $redefined->getTargetNamespace()){
655+
$redefined->setTargetNamespace($schema->getTargetNamespace());
656+
}
657+
658+
$schema->addSchema($redefined);
659+
660+
$callbacks = $this->schemaNode($redefined, $node, $schema);
661+
}
662+
else{
663+
$redefined = new Schema();
664+
$redefined->addSchema($this->getGlobalSchema());
665+
666+
$xml = $this->getDOM(isset($this->knownLocationSchemas[$file]) ? $this->knownLocationSchemas[$file] : $file);
667+
668+
$callbacks = $this->schemaNode($redefined, $xml->documentElement, $schema);
669+
670+
$schema->addSchema($redefined);
671+
}
672+
673+
return function () use ($callbacks) {
674+
foreach ($callbacks as $callback) {
675+
call_user_func($callback);
676+
}
677+
};
678+
}
679+
642680
private function loadImport(Schema $schema, DOMElement $node)
643681
{
644682
$base = urldecode($node->ownerDocument->documentURI);
@@ -722,7 +760,7 @@ public function getGlobalSchema()
722760
/**
723761
* @param DOMNode $node
724762
* @param string $file
725-
*
763+
*
726764
* @return Schema
727765
*/
728766
public function readNode(DOMNode $node, $file = 'schema.xsd')

tests/RedefineTest.php

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
namespace GoetasWebservices\XML\XSDReader\Tests;
3+
4+
class RedefineTest extends BaseTest
5+
{
6+
public function testBase()
7+
{
8+
$remoteSchema = $this->reader->readString(
9+
'
10+
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
11+
<xs:complexType name="personName">
12+
<xs:sequence>
13+
<xs:element name="title" minOccurs="0"/>
14+
<xs:element name="forename" minOccurs="0" maxOccurs="unbounded"/>
15+
</xs:sequence>
16+
</xs:complexType>
17+
18+
<xs:element name="addressee" type="personName"/>
19+
</xs:schema>', 'http://www.example.com/xsd.xsd');
20+
21+
22+
$schema = $this->reader->readString(
23+
'
24+
<xs:schema targetNamespace="http://www.user.com" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ex="http://www.example.com">
25+
<xs:redefine schemaLocation="http://www.example.com/xsd.xsd">
26+
<xs:complexType name="personName">
27+
<xs:complexContent>
28+
<xs:extension base="personName">
29+
<xs:sequence>
30+
<xs:element name="generation" minOccurs="0"/>
31+
</xs:sequence>
32+
</xs:extension>
33+
</xs:complexContent>
34+
</xs:complexType>
35+
</xs:redefine>
36+
37+
<xs:element name="author" type="personName"/>
38+
</xs:schema>');
39+
40+
// check if schema is not included
41+
// we don't want to redefine original schema
42+
$this->assertNotContains($remoteSchema, $schema->getSchemas(), '', true);
43+
44+
/* @var $localAttr \GoetasWebservices\XML\XSDReader\Schema\Element\ElementDef */
45+
46+
// it should inherit namespace of main schema
47+
$localAttr = $schema->findElement("addressee", "http://www.user.com");
48+
$this->assertNotNull($localAttr);
49+
50+
// find author element
51+
$localAttr = $schema->findElement("author", "http://www.user.com");
52+
$this->assertNotNull($localAttr);
53+
54+
/* @var $type \GoetasWebservices\XML\XSDReader\Schema\Type\ComplexType */
55+
$type = $localAttr->getType();
56+
57+
$this->assertInstanceOf('\GoetasWebservices\XML\XSDReader\Schema\Type\ComplexType', $type);
58+
59+
$children = array();
60+
foreach($type->getElements() as $element){
61+
$children[] = $element->getName();
62+
}
63+
64+
$this->assertContains('generation', $children);
65+
}
66+
}

0 commit comments

Comments
 (0)