diff --git a/aas/adapter/aasx.py b/aas/adapter/aasx.py
index b9fdd4aca7f38a335a45f40d2ad89ce43bcb1bfa..31857223182eb9877b37e1c16660ac1fd5e13f94 100644
--- a/aas/adapter/aasx.py
+++ b/aas/adapter/aasx.py
@@ -30,7 +30,7 @@ import os
import re
from typing import Dict, Tuple, IO, Union, List, Set, Optional
-from .xml import read_aas_xml_file
+from .xml import read_aas_xml_file, write_aas_xml_file
from .. import model
from .json import read_aas_json_file, write_aas_json_file
import pyecma376_2
@@ -293,11 +293,11 @@ class AASXWriter:
p.close()
# TODO allow to specify, which supplementary parts (submodels, conceptDescriptions) should be added to the package
- # TODO allow to select JSON/XML serialization
def write_aas(self,
aas_id: model.Identifier,
object_store: model.AbstractObjectStore,
- file_store: "AbstractSupplementaryFileContainer") -> None:
+ file_store: "AbstractSupplementaryFileContainer",
+ write_json: bool = False) -> None:
"""
Add an Asset Administration Shell with all included and referenced objects to the AASX package.
@@ -312,9 +312,11 @@ class AASXWriter:
Submodels) from
:param file_store: SupplementaryFileContainer to retrieve supplementary files from, which are referenced by File
objects
+ :param write_json: If True, JSON parts are created for the AAS and each submodel in the AASX package file
+ instead of XML parts. Defaults to False.
"""
aas_friendly_name = self._aas_name_friendlyfier.get_friendly_name(aas_id)
- aas_part_name = "/aasx/{0}/{0}.aas.json".format(aas_friendly_name)
+ aas_part_name = "/aasx/{0}/{0}.aas.{1}".format(aas_friendly_name, "json" if write_json else "xml")
self._aas_part_names.append(aas_part_name)
aas_friendlyfier = NameFriendlyfier()
@@ -347,8 +349,11 @@ class AASXWriter:
# Write AAS part
logger.debug("Writing AAS {} to part {} in AASX package ...".format(aas.identification, aas_part_name))
- with self.writer.open_part(aas_part_name, "application/json") as p:
- write_aas_json_file(io.TextIOWrapper(p, encoding='utf-8'), objects_to_be_written)
+ with self.writer.open_part(aas_part_name, "application/json" if write_json else "application/xml") as p:
+ if write_json:
+ write_aas_json_file(io.TextIOWrapper(p, encoding='utf-8'), objects_to_be_written)
+ else:
+ write_aas_xml_file(p, objects_to_be_written)
# Create a AAS split part for each (available) submodel of the AAS
aas_split_part_names: List[str] = []
@@ -359,8 +364,9 @@ class AASXWriter:
logger.warning("Skipping Submodel, since {} could not be resolved: {}".format(submodel_ref, e))
continue
submodel_friendly_name = aas_friendlyfier.get_friendly_name(submodel.identification)
- submodel_part_name = "/aasx/{0}/{1}/{1}.submodel.json".format(aas_friendly_name, submodel_friendly_name)
- self._write_submodel_part(file_store, submodel, submodel_part_name)
+ submodel_part_name = "/aasx/{0}/{1}/{1}.submodel.{2}".format(aas_friendly_name, submodel_friendly_name,
+ "json" if write_json else "xml")
+ self._write_submodel_part(file_store, submodel, submodel_part_name, write_json)
aas_split_part_names.append(submodel_part_name)
# Add relationships from AAS part to (submodel) split parts
@@ -375,7 +381,7 @@ class AASXWriter:
aas_part_name)
def _write_submodel_part(self, file_store: "AbstractSupplementaryFileContainer",
- submodel: model.Submodel, submodel_part_name: str) -> None:
+ submodel: model.Submodel, submodel_part_name: str, write_json: bool = False) -> None:
"""
Helper function for `write_aas()` to write an aas-spec-split part for a Submodel object and add the relevant
supplementary files.
@@ -383,14 +389,19 @@ class AASXWriter:
:param file_store: The SupplementaryFileContainer to retrieve supplementary files from
:param submodel: The submodel to be written into the AASX package
:param submodel_part_name: OPC part name of the aas-spec-split part for this Submodel
+ :param write_json: If True, the submodel is written as a JSON file instead of an XML file to the given OPC
+ part. Defaults to False.
"""
logger.debug("Writing Submodel {} to part {} in AASX package ..."
.format(submodel.identification, submodel_part_name))
submodel_file_objects: model.DictObjectStore[model.Identifiable] = model.DictObjectStore()
submodel_file_objects.add(submodel)
- with self.writer.open_part(submodel_part_name, "application/json") as p:
- write_aas_json_file(io.TextIOWrapper(p, encoding='utf-8'), submodel_file_objects)
+ with self.writer.open_part(submodel_part_name, "application/json" if write_json else "application/xml") as p:
+ if write_json:
+ write_aas_json_file(io.TextIOWrapper(p, encoding='utf-8'), submodel_file_objects)
+ else:
+ write_aas_xml_file(p, submodel_file_objects)
# Write submodel's supplementary files to AASX file
submodel_file_names = []
diff --git a/test/adapter/aasx/test_aasx.py b/test/adapter/aasx/test_aasx.py
index d7bb6e368e7eaa1c132037edd3811499ba5151de..7ac5b3ddfb156689014223e7362a1ede4718e131 100644
--- a/test/adapter/aasx/test_aasx.py
+++ b/test/adapter/aasx/test_aasx.py
@@ -73,37 +73,40 @@ class AASXWriterTest(unittest.TestCase):
cp.creator = "PyI40AAS Testing Framework"
# Write AASX file
- fd, filename = tempfile.mkstemp(suffix=".aasx")
- os.close(fd)
- with aasx.AASXWriter(filename) as writer:
- writer.write_aas(model.Identifier(id_='https://acplt.org/Test_AssetAdministrationShell',
- id_type=model.IdentifierType.IRI),
- data, files)
- writer.write_core_properties(cp)
-
- # Read AASX file
- new_data: model.DictObjectStore[model.Identifiable] = model.DictObjectStore()
- new_files = aasx.DictSupplementaryFileContainer()
- with aasx.AASXReader(filename) as reader:
- reader.read_into(new_data, new_files)
- new_cp = reader.get_core_properties()
-
- # Check AAS objects
- checker = _helper.AASDataChecker(raise_immediately=True)
- example_aas.check_full_example(checker, new_data)
-
- # Check core properties
- assert(isinstance(cp.created, datetime.datetime)) # to make mypy happy
- self.assertIsInstance(new_cp.created, datetime.datetime)
- assert(isinstance(new_cp.created, datetime.datetime)) # to make mypy happy
- self.assertAlmostEqual(new_cp.created, cp.created, delta=datetime.timedelta(milliseconds=20))
- self.assertEqual(new_cp.creator, "PyI40AAS Testing Framework")
- self.assertIsNone(new_cp.lastModifiedBy)
-
- # Check files
- self.assertEqual(new_files.get_content_type("/TestFile.pdf"), "application/pdf")
- file_content = io.BytesIO()
- new_files.write_file("/TestFile.pdf", file_content)
- self.assertEqual(hashlib.sha1(file_content.getvalue()).hexdigest(), "78450a66f59d74c073bf6858db340090ea72a8b1")
-
- os.unlink(filename)
+ for write_json in (False, True):
+ with self.subTest(write_json=write_json):
+ fd, filename = tempfile.mkstemp(suffix=".aasx")
+ os.close(fd)
+ with aasx.AASXWriter(filename) as writer:
+ writer.write_aas(model.Identifier(id_='https://acplt.org/Test_AssetAdministrationShell',
+ id_type=model.IdentifierType.IRI),
+ data, files, write_json=write_json)
+ writer.write_core_properties(cp)
+
+ # Read AASX file
+ new_data: model.DictObjectStore[model.Identifiable] = model.DictObjectStore()
+ new_files = aasx.DictSupplementaryFileContainer()
+ with aasx.AASXReader(filename) as reader:
+ reader.read_into(new_data, new_files)
+ new_cp = reader.get_core_properties()
+
+ # Check AAS objects
+ checker = _helper.AASDataChecker(raise_immediately=True)
+ example_aas.check_full_example(checker, new_data)
+
+ # Check core properties
+ assert(isinstance(cp.created, datetime.datetime)) # to make mypy happy
+ self.assertIsInstance(new_cp.created, datetime.datetime)
+ assert(isinstance(new_cp.created, datetime.datetime)) # to make mypy happy
+ self.assertAlmostEqual(new_cp.created, cp.created, delta=datetime.timedelta(milliseconds=20))
+ self.assertEqual(new_cp.creator, "PyI40AAS Testing Framework")
+ self.assertIsNone(new_cp.lastModifiedBy)
+
+ # Check files
+ self.assertEqual(new_files.get_content_type("/TestFile.pdf"), "application/pdf")
+ file_content = io.BytesIO()
+ new_files.write_file("/TestFile.pdf", file_content)
+ self.assertEqual(hashlib.sha1(file_content.getvalue()).hexdigest(),
+ "78450a66f59d74c073bf6858db340090ea72a8b1")
+
+ os.unlink(filename)