6363import java .util .zip .GZIPInputStream ;
6464import java .util .zip .GZIPOutputStream ;
6565
66+ import static com .powsybl .commons .xml .XmlUtil .getXMLInputFactory ;
6667import static com .powsybl .iidm .serde .AbstractTreeDataImporter .SUFFIX_MAPPING ;
6768import static com .powsybl .iidm .serde .IidmSerDeConstants .IIDM_PREFIX ;
6869import static com .powsybl .iidm .serde .IidmSerDeConstants .INDENT ;
@@ -163,6 +164,16 @@ private static void validate(InputStream is, IidmVersion version, ExtensionsSupp
163164 Objects .requireNonNull (is );
164165 Objects .requireNonNull (version );
165166 Objects .requireNonNull (extensionsSupplier );
167+
168+ // check version namespace
169+ byte [] xmlBytes ;
170+ try {
171+ xmlBytes = is .readAllBytes ();
172+ checkNamespace (xmlBytes , version );
173+ } catch (IOException e ) {
174+ throw new UncheckedIOException (e );
175+ }
176+ // XSD validation
166177 Schema schema ;
167178 if (extensionsSupplier == DefaultExtensionsSupplier .getInstance ()) {
168179 schema = DEFAULT_SCHEMAS_SUPPLIER .get ().get (version );
@@ -173,7 +184,7 @@ private static void validate(InputStream is, IidmVersion version, ExtensionsSupp
173184 schema = createSchema (extensionsSupplier , version );
174185 }
175186 try {
176- schema .newValidator ().validate (new StreamSource (is ));
187+ schema .newValidator ().validate (new StreamSource (new ByteArrayInputStream ( xmlBytes ) ));
177188 } catch (IOException e ) {
178189 throw new UncheckedIOException (e );
179190 } catch (SAXException e ) {
@@ -254,8 +265,17 @@ private static List<Source> getExtensionSources(ExtensionsSupplier extensionsSup
254265 return extensions ;
255266 }
256267
268+ private static void checkNamespace (byte [] xmlBytes , IidmVersion validationVersion ) {
269+ String actualNs = readRootNamespace (xmlBytes );
270+ boolean matches = actualNs .equals (validationVersion .getNamespaceURI ())
271+ || validationVersion .supportEquipmentValidationLevel () && actualNs .equals (validationVersion .getNamespaceURI (false ));
272+ if (!matches ) {
273+ throw new PowsyblException ("Namespace mismatch: expected validation version " + validationVersion .toString ("." ) + ", found namespace " + actualNs );
274+ }
275+ }
276+
257277 /**
258- * Extract {@code xs:import/@schemaLocation} in an XSD document
278+ * Extract {@code xs:import/@schemaLocation} from XSD document
259279 *
260280 * <p>XSD document snippet:</p>
261281 * <pre>{@code
@@ -271,9 +291,7 @@ private static List<Source> getExtensionSources(ExtensionsSupplier extensionsSup
271291 */
272292 private static List <String > extractSchemaLocations (byte [] xsdBytes ) {
273293 List <String > locations = new ArrayList <>();
274- XMLInputFactory xif = XMLInputFactory .newFactory ();
275- xif .setProperty (XMLInputFactory .SUPPORT_DTD , false );
276- xif .setProperty (XMLInputFactory .IS_SUPPORTING_EXTERNAL_ENTITIES , false );
294+ XMLInputFactory xif = getXMLInputFactory ();
277295 try {
278296 XMLStreamReader reader = xif .createXMLStreamReader (new ByteArrayInputStream (xsdBytes ));
279297 while (reader .hasNext ()) {
@@ -294,6 +312,33 @@ private static List<String> extractSchemaLocations(byte[] xsdBytes) {
294312 return locations ;
295313 }
296314
315+ /**
316+ * Read the namespace declared on {@code <network>} element
317+ *
318+ * @param xmlBytes XML document content as bytes
319+ * @return Namespace URI
320+ */
321+ private static String readRootNamespace (byte [] xmlBytes ) {
322+ XMLInputFactory xif = getXMLInputFactory ();
323+ try {
324+ XMLStreamReader reader = xif .createXMLStreamReader (new ByteArrayInputStream (xmlBytes ));
325+ while (reader .hasNext ()) {
326+ if (reader .next () == XMLStreamConstants .START_ELEMENT ) {
327+ if (!NETWORK_ROOT_ELEMENT_NAME .equals (reader .getLocalName ())) {
328+ throw new PowsyblException ("Unexpected root element: " + reader .getLocalName ());
329+ }
330+ String ns = reader .getNamespaceURI ();
331+ reader .close ();
332+ return ns ;
333+ }
334+ }
335+ reader .close ();
336+ throw new PowsyblException ("No root element found" );
337+ } catch (XMLStreamException e ) {
338+ throw new RuntimeException (e );
339+ }
340+ }
341+
297342 private static void throwExceptionIfOption (AbstractOptions <?> options , String message ) {
298343 if (options .isThrowExceptionIfExtensionNotFound ()) {
299344 throw new PowsyblException (message );
0 commit comments