@@ -85,22 +85,39 @@ private function includeSchema(DOMElement $include): ?DOMElement
8585 }
8686
8787 /*
88- * Currently we do not validate the namespace of includes - we assume the provided imports are valid!
88+ * Target namespace rules:
8989 *
9090 * @see https://docs.microsoft.com/en-us/previous-versions/dotnet/netframework-4.0/ms256198(v=vs.100)
9191 * The included schema document must meet one of the following conditions.
92- - It must have the same target namespace as the containing schema document.
93- - It must not have a target namespace specified (no targetNamespace attribute).
92+ - It must have the same target namespace as the containing schema document.
93+ - It must not have a target namespace specified (no targetNamespace attribute).
94+ In that case, the including schema document provides the target namespace for the new one.
9495 */
9596
97+ // Detect namespaces from both the current schema and the import
98+ $ parentSchema = $ this ->detectParentSchemaNode ($ include );
99+ $ parentTns = $ parentSchema ->getAttribute ('targetNamespace ' );
100+
96101 $ schema = $ this ->loadSchema ($ location );
102+ if ($ schema ) {
103+ // If the included schema has no targetNamespace, it will inherit the parent schema's namespace.
104+ if (!$ schema ->hasAttribute ('targetNamespace ' )) {
105+ $ schema ->setAttribute ('targetNamespace ' , $ parentTns );
106+ }
107+
108+ // Validate if the namespaces of the included document match the parent schema.
109+ $ schemaTns = $ schema ->getAttribute ('targetNamespace ' );
110+ if ($ schemaTns !== $ parentTns ) {
111+ throw FlattenException::invalidIncludeTargetNamespace ($ parentTns , $ schemaTns );
112+ }
97113
98- // Redefines overwrite tags from includes.
99- // The children of redefine elements are appended to the newly loaded schema.
100- if ($ schema && $ include ->localName === 'redefine ' ) {
101- children ($ include )->map (
102- static fn (DOMNode $ node ) => append_external_node ($ schema , $ node )
103- );
114+ // Redefines overwrite tags from includes.
115+ // The children of redefine elements are appended to the newly loaded schema.
116+ if ($ include ->localName === 'redefine ' ) {
117+ children ($ include )->map (
118+ static fn (DOMNode $ node ) => append_external_node ($ schema , $ node )
119+ );
120+ }
104121 }
105122
106123 // Include tags can be removed, since the schema will be made available in the types
@@ -123,19 +140,14 @@ private function importSchema(DOMElement $import): ?DOMElement
123140 return null ;
124141 }
125142
126- // Find the schema that wants to import the new schema:
127- $ doc = Document::fromUnsafeDocument ($ import ->ownerDocument );
128- $ xpath = $ doc ->xpath (new WsdlPreset ($ doc ));
129- /** @var DOMElement $schema */
130- $ schema = $ xpath ->querySingle ('ancestor::schema:schema ' , $ import );
131-
132143 // Detect namespaces from both the current schema and the import
133144 $ namespace = $ import ->getAttribute ('namespace ' );
134- $ tns = $ schema ->getAttribute ('targetNamespace ' );
145+ $ parentSchema = $ this ->detectParentSchemaNode ($ import );
146+ $ parentTns = $ parentSchema ->getAttribute ('targetNamespace ' );
135147
136148 // Imports can only deal with different namespaces.
137149 // You'll need to use "include" if you want to inject something in the same namespace.
138- if ($ tns && $ namespace && $ tns === $ namespace ) {
150+ if ($ parentTns && $ namespace && $ parentTns === $ namespace ) {
139151 throw FlattenException::unableToImportXsd ($ location );
140152 }
141153
@@ -147,6 +159,20 @@ private function importSchema(DOMElement $import): ?DOMElement
147159 return $ schema ;
148160 }
149161
162+ /**
163+ * This function will return the parent declaring <schema /> tag for elements like import | include, ...
164+ *
165+ * @throws RuntimeException
166+ */
167+ private function detectParentSchemaNode (DOMElement $ element ): DOMElement
168+ {
169+ $ parent = Document::fromUnsafeDocument ($ element ->ownerDocument );
170+ $ xpath = $ parent ->xpath (new WsdlPreset ($ parent ));
171+
172+ /** @var DOMElement */
173+ return $ xpath ->querySingle ('ancestor::schema:schema ' , $ element );
174+ }
175+
150176 /**
151177 * @throws RuntimeException
152178 * @throws UnloadableWsdlException
0 commit comments