@@ -85,22 +85,39 @@ private function includeSchema(DOMElement $include): ?DOMElement
85
85
}
86
86
87
87
/*
88
- * Currently we do not validate the namespace of includes - we assume the provided imports are valid!
88
+ * Target namespace rules:
89
89
*
90
90
* @see https://docs.microsoft.com/en-us/previous-versions/dotnet/netframework-4.0/ms256198(v=vs.100)
91
91
* 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.
94
95
*/
95
96
97
+ // Detect namespaces from both the current schema and the import
98
+ $ parentSchema = $ this ->detectParentSchemaNode ($ include );
99
+ $ parentTns = $ parentSchema ->getAttribute ('targetNamespace ' );
100
+
96
101
$ 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
+ }
97
113
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
+ }
104
121
}
105
122
106
123
// 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
123
140
return null ;
124
141
}
125
142
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
-
132
143
// Detect namespaces from both the current schema and the import
133
144
$ namespace = $ import ->getAttribute ('namespace ' );
134
- $ tns = $ schema ->getAttribute ('targetNamespace ' );
145
+ $ parentSchema = $ this ->detectParentSchemaNode ($ import );
146
+ $ parentTns = $ parentSchema ->getAttribute ('targetNamespace ' );
135
147
136
148
// Imports can only deal with different namespaces.
137
149
// 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 ) {
139
151
throw FlattenException::unableToImportXsd ($ location );
140
152
}
141
153
@@ -147,6 +159,20 @@ private function importSchema(DOMElement $import): ?DOMElement
147
159
return $ schema ;
148
160
}
149
161
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
+
150
176
/**
151
177
* @throws RuntimeException
152
178
* @throws UnloadableWsdlException
0 commit comments