Import XML formations: filtre caractères de contrôles erronés

This commit is contained in:
Emmanuel Viennet 2024-09-27 22:37:54 +02:00
parent 00efa7bcad
commit 8e932a8e0b
3 changed files with 22 additions and 7 deletions

View File

@ -222,6 +222,8 @@ def formation_export(
"""Get a formation, with UE, matieres, modules """Get a formation, with UE, matieres, modules
in desired format in desired format
""" """
if fmt not in ("xml", "json"):
raise ScoValueError("Format invalide")
formation = Formation.get_formation(formation_id) formation = Formation.get_formation(formation_id)
f_dict = formation_export_dict( f_dict = formation_export_dict(
formation, formation,
@ -296,7 +298,7 @@ def _formation_retreive_apc_niveau(
return niveau.id if niveau is not None else None return niveau.id if niveau is not None else None
def formation_import_xml(doc: str, import_tags=True, use_local_refcomp=False): def formation_import_xml(doc: str | bytes, import_tags=True, use_local_refcomp=False):
"""Create a formation from XML representation """Create a formation from XML representation
(format dumped by formation_export( fmt='xml' )) (format dumped by formation_export( fmt='xml' ))
XML may contain object (UE, modules) ids: this function returns two XML may contain object (UE, modules) ids: this function returns two
@ -311,11 +313,13 @@ def formation_import_xml(doc: str, import_tags=True, use_local_refcomp=False):
""" """
from app.scodoc import sco_edit_formation from app.scodoc import sco_edit_formation
if isinstance(doc, bytes):
doc = doc.decode(scu.SCO_ENCODING)
try: try:
dom = xml.dom.minidom.parseString(doc) dom = xml.dom.minidom.parseString(sco_xml.remove_control_characters(doc))
except Exception as exc: except Exception as exc:
log("formation_import_xml: invalid XML data") log(f"formation_import_xml: invalid XML data:\n{exc}")
raise ScoValueError("Fichier XML invalide") from exc raise ScoValueError(f"Fichier XML invalide {exc}") from exc
try: try:
f = dom.getElementsByTagName("formation")[0] # or dom.documentElement f = dom.getElementsByTagName("formation")[0] # or dom.documentElement

View File

@ -1117,8 +1117,9 @@ def sendXML(
attached=False, attached=False,
quote=False, quote=False,
filename=None, filename=None,
): ) -> Response:
if type(data) != list: "Réponse XML: data est une liste d'objets"
if not isinstance(data, list):
data = [data] # always list-of-dicts data = [data] # always list-of-dicts
if force_outer_xml_tag: if force_outer_xml_tag:
data = [{tagname: data}] data = [{tagname: data}]

View File

@ -39,6 +39,16 @@ from app.scodoc.sco_vdi import ApoEtapeVDI
XML_HEADER = """<?xml version="1.0" encoding="utf-8"?>""" XML_HEADER = """<?xml version="1.0" encoding="utf-8"?>"""
def remove_control_characters(s: str) -> str:
"""supprime tous les caractères de contrôle (code < 32)
sauf les tabs (9), les retours chariot (10 et les sauts de ligne (13).
"""
if not hasattr(remove_control_characters, "control_chars"):
control_chars = dict.fromkeys(i for i in range(32) if i not in (9, 10, 13))
remove_control_characters.control_chars = control_chars
return s.translate(remove_control_characters.control_chars)
def quote_xml_attr(data): def quote_xml_attr(data):
"""Escape &, <, >, quotes and double quotes""" """Escape &, <, >, quotes and double quotes"""
return xml.sax.saxutils.escape(str(data), {"'": "&apos;", '"': "&quot;"}) return xml.sax.saxutils.escape(str(data), {"'": "&apos;", '"': "&quot;"})
@ -93,7 +103,7 @@ def _dictlist2xml(dictlist, root=None, tagname=None, quote=False):
for d in dictlist: for d in dictlist:
elem = ElementTree.Element(tagname) elem = ElementTree.Element(tagname)
root.append(elem) root.append(elem)
if isinstance(d, scalar_types) or isinstance(d, ApoEtapeVDI): if isinstance(d, (scalar_types, ApoEtapeVDI)):
elem.set("code", _repr_as_xml(d)) elem.set("code", _repr_as_xml(d))
else: else:
if quote: if quote: