Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adapter.xml: improve error messages in case of incorrect namespace declarations #191

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions basyx/aas/adapter/xml/xml_deserialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,12 @@
import enum

from typing import Any, Callable, Dict, IO, Iterable, Optional, Set, Tuple, Type, TypeVar
from .._generic import XML_NS_AAS, MODELLING_KIND_INVERSE, ASSET_KIND_INVERSE, KEY_TYPES_INVERSE, \
from .._generic import XML_NS_MAP, XML_NS_AAS, MODELLING_KIND_INVERSE, ASSET_KIND_INVERSE, KEY_TYPES_INVERSE, \
ENTITY_TYPES_INVERSE, IEC61360_DATA_TYPES_INVERSE, IEC61360_LEVEL_TYPES_INVERSE, KEY_TYPES_CLASSES_INVERSE, \
REFERENCE_TYPES_INVERSE, DIRECTION_INVERSE, STATE_OF_EVENT_INVERSE, QUALIFIER_KIND_INVERSE

NS_AAS = XML_NS_AAS
REQUIRED_NAMESPACES: Set[str] = {XML_NS_MAP["aas"]}

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -97,7 +98,7 @@ def _element_pretty_identifier(element: etree.Element) -> str:
Returns a pretty element identifier for a given XML element.

If the prefix is known, the namespace in the element tag is replaced by the prefix.
If additionally also the sourceline is known, is is added as a suffix to name.
If additionally also the sourceline is known, it is added as a suffix to name.
For example, instead of "{https://admin-shell.io/aas/3/0}assetAdministrationShell" this function would return
"aas:assetAdministrationShell on line $line", if both, prefix and sourceline, are known.

Expand All @@ -106,7 +107,11 @@ def _element_pretty_identifier(element: etree.Element) -> str:
"""
identifier = element.tag
if element.prefix is not None:
identifier = element.prefix + ":" + element.tag.split("}")[1]
# Only replace the namespace by the prefix if it matches our known namespaces,
# so the replacement by the prefix doesn't mask errors such as incorrect namespaces.
namespace, tag = element.tag.split("}", 1)
if namespace[1:] in XML_NS_MAP.values():
identifier = element.prefix + ":" + tag
if element.sourceline is not None:
identifier += f" on line {element.sourceline}"
return identifier
Expand Down Expand Up @@ -1196,13 +1201,22 @@ def _parse_xml_document(file: IO, failsafe: bool = True, **parser_kwargs: Any) -
parser = etree.XMLParser(remove_blank_text=True, remove_comments=True, **parser_kwargs)

try:
return etree.parse(file, parser).getroot()
root = etree.parse(file, parser).getroot()
except etree.XMLSyntaxError as e:
if failsafe:
logger.error(e)
return None
raise e

missing_namespaces: Set[str] = REQUIRED_NAMESPACES - set(root.nsmap.values())
if missing_namespaces:
error_message = f"The following required namespaces are not declared: {' | '.join(missing_namespaces)}" \
+ " - Is the input document of an older version?"
if not failsafe:
raise KeyError(error_message)
logger.error(error_message)
return root


def _select_decoder(failsafe: bool, stripped: bool, decoder: Optional[Type[AASFromXmlDecoder]]) \
-> Type[AASFromXmlDecoder]:
Expand Down
Loading