From 2775941e455067d537c6774345ad25b823dd82e1 Mon Sep 17 00:00:00 2001 From: Damien Marchal Date: Wed, 22 May 2024 20:03:51 +0200 Subject: [PATCH] Add a loadXML function to load an sofa scene from xml in python. (#123) * Add a loadXML function to load an sofa scene from xml in python with an example. --- python3/src/splib3/loaders/__init__.py | 5 ++- python3/src/splib3/loaders/xmlloader.py | 55 +++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 python3/src/splib3/loaders/xmlloader.py diff --git a/python3/src/splib3/loaders/__init__.py b/python3/src/splib3/loaders/__init__.py index d812ebe..ef1c62e 100644 --- a/python3/src/splib3/loaders/__init__.py +++ b/python3/src/splib3/loaders/__init__.py @@ -13,9 +13,8 @@ .. autofunction:: getLoadingLocation """ -__all__=[] +__all__=["xmlloader"] -import os def getLoadingLocation(filename , source=None): """Compute a loading path for the provided filename relative to a given source location @@ -28,6 +27,8 @@ def getLoadingLocation(filename , source=None): The latter is really usefull to make get the path for a file relative to the 'current' python source. """ + import os + if source == None: return filename diff --git a/python3/src/splib3/loaders/xmlloader.py b/python3/src/splib3/loaders/xmlloader.py new file mode 100644 index 0000000..7da4f24 --- /dev/null +++ b/python3/src/splib3/loaders/xmlloader.py @@ -0,0 +1,55 @@ +import Sofa +import SofaRuntime +import xml.etree.ElementTree as ET + +def _processNode(xmlNode, sofaNode, context={}): + # set the value of the data field of the sofaNode from the attributes of the xmlNode + for name, value in xmlNode.attrib.items(): + if name in sofaNode.__data__: + sofaNode.findData(name).read(value) + + # for each child of the xmlNode + for child in xmlNode: + # if it is a special one "include" + if child.tag == "include": + # load the corresponding file + filename = SofaRuntime.DataRepository.getFile(child.attrib["href"]) + n = sofaNode.addChild("Unnamed") + + # create a specific context + local_context = context.copy() + for name, value in child.attrib.items(): + if name not in ["name", "href"]: + local_context[name] = value + + # recursively load the file + loadXML(filename, n, local_context) + # if it is a node then load and recursively process it + elif child.tag == "Node": + sofaChild = sofaNode.addChild(child.attrib["name"]) + _processNode(child, sofaChild, context) + + # otherwise, it is treated as an object + else: + # override the child attributes from the value from the context + for name, value in context.items(): + if name in child.attrib: + child.attrib[name] = value + sofaNode.addObject(child.tag, **(child.attrib)) + +def loadXML(filename, sofaNode, context={}): + """Load a sofa scene from an xml file and adds it to the provided sofaNode + + Example of use: + from splib3.loaders.xmlloader import loadXML + + def createScene(root): + loadXML("Caduceus.xml", root) + """ + tree = ET.parse(filename) + xmlNode = tree.getroot() + _processNode(xmlNode, sofaNode, context) + return sofaNode + +def createScene(root): + loadXML(SofaRuntime.DataRepository.getFile("Demos/caduceus.scn"), root)