# PlmXmlParser # *************************************************************************** # * Copyright (c) 2015 Juergen Riegel * # * * # * This file is part of the FreeCAD CAx development system. * # * * # * This program is free software; you can redistribute it and/or modify * # * it under the terms of the GNU Lesser General Public License (LGPL) * # * as published by the Free Software Foundation; either version 2 of * # * the License, or (at your option) any later version. * # * for detail see the LICENCE text file. * # * * # * FreeCAD is distributed in the hope that it will be useful, * # * but WITHOUT ANY WARRANTY; without even the implied warranty of * # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * # * GNU Lesser General Public License for more details. * # * * # * You should have received a copy of the GNU Library General Public * # * License along with FreeCAD; if not, write to the Free Software * # * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * # * USA * # * * # ***************************************************************************/ import xml.etree.ElementTree as ET FreeCAD_On = False FreeCAD_Doc = None FreeCAD_ObjList = [] def ParseUserData(element): res = {} for i in element.findall("{http://www.plmxml.org/Schemas/PLMXMLSchema}UserData"): for value in i.findall("{http://www.plmxml.org/Schemas/PLMXMLSchema}UserValue"): res[value.attrib["title"]] = value.attrib["value"] return res def addPart(partElement): global FreeCAD_On, FreeCAD_Doc, FreeCAD_ObjList print("=== Part ======================================================") name = partElement.attrib["name"] id = partElement.attrib["id"] userData = ParseUserData(partElement) bound = partElement.find("{http://www.plmxml.org/Schemas/PLMXMLSchema}Bound") print(bound.attrib["values"]) representation = partElement.find("{http://www.plmxml.org/Schemas/PLMXMLSchema}Representation") format = representation.attrib["format"] location = representation.attrib["location"] print(id, name, userData, format, location) if FreeCAD_On: import FreeCAD, Assembly print("Create Reference") partObject = FreeCAD_Doc.addObject("App::Part", id) FreeCAD_ObjList.append(partObject) partObject.Label = name partObject.Meta = userData def addAssembly(asmElement): global FreeCAD_On, FreeCAD_Doc, FreeCAD_ObjList print("=== Assembly ======================================================") userData = ParseUserData(asmElement) name = asmElement.attrib["name"] id = asmElement.attrib["id"] instanceRefs = asmElement.attrib["instanceRefs"] userData["instanceRefs"] = instanceRefs print(id, name, instanceRefs, userData) if FreeCAD_On: import FreeCAD, Assembly print("Create Reference") admObject = FreeCAD_Doc.addObject("Assembly::Product", id) FreeCAD_ObjList.append(admObject) admObject.Label = name admObject.Meta = userData def addReference(refElement): global FreeCAD_On, FreeCAD_Doc, FreeCAD_ObjList print("=== Reference ======================================================") userData = ParseUserData(refElement) partRef = refElement.attrib["partRef"][1:] userData["partRef"] = partRef id = refElement.attrib["id"] name = refElement.attrib["name"] transform = refElement.find("{http://www.plmxml.org/Schemas/PLMXMLSchema}Transform") mtrx = [float(i) for i in transform.text.split(" ")] print(mtrx) print(id, name, partRef) if FreeCAD_On: import FreeCAD, Assembly print("Create Reference") refObject = FreeCAD_Doc.addObject("Assembly::ProductRef", id) FreeCAD_ObjList.append(refObject) refObject.Label = name refObject.Meta = userData def resolveRefs(): global FreeCAD_On, FreeCAD_Doc, FreeCAD_ObjList print("=== Resolve References ======================================================") if FreeCAD_On: for i in FreeCAD_ObjList: if i.TypeId == "Assembly::Product": objectList = [] for l in i.Meta["instanceRefs"].split(" "): objectList.append(FreeCAD_Doc.getObject(l)) i.Items = objectList if i.TypeId == "Assembly::ProductRef": i.Item = FreeCAD_Doc.getObject(i.Meta["partRef"]) def open(fileName): """called when freecad opens an PlmXml file""" global FreeCAD_On, FreeCAD_Doc import FreeCAD, os docname = os.path.splitext(os.path.basename(fileName))[0] doc = FreeCAD.newDocument(docname) message = 'Started with opening of "' + fileName + '" file\n' FreeCAD.Console.PrintMessage(message) FreeCAD_Doc = doc FreeCAD_On = True parse(fileName) resolveRefs() def insert(filename, docname): """called when freecad imports an PlmXml file""" global FreeCAD_On, FreeCAD_Doc import FreeCAD FreeCAD.setActiveDocument(docname) doc = FreeCAD.getDocument(docname) FreeCAD.Console.PrintMessage('Started import of "' + filename + '" file') FreeCAD_Doc = doc FreeCAD_On = True parse(fileName) resolveRefs() def main(): parse("../../../../data/tests/Jt/Engine/2_Cylinder_Engine3.plmxml") def parse(fileName): tree = ET.parse(fileName) root = tree.getroot() ProductDef = root.find("{http://www.plmxml.org/Schemas/PLMXMLSchema}ProductDef") res = ParseUserData(ProductDef.find("{http://www.plmxml.org/Schemas/PLMXMLSchema}UserData")) InstanceGraph = ProductDef.find("{http://www.plmxml.org/Schemas/PLMXMLSchema}InstanceGraph") # get all the special elements we can read Instances = InstanceGraph.findall("{http://www.plmxml.org/Schemas/PLMXMLSchema}Instance") Parts = InstanceGraph.findall("{http://www.plmxml.org/Schemas/PLMXMLSchema}Part") ProductInstances = InstanceGraph.findall( "{http://www.plmxml.org/Schemas/PLMXMLSchema}ProductInstance" ) ProductRevisionViews = InstanceGraph.findall( "{http://www.plmxml.org/Schemas/PLMXMLSchema}ProductRevisionView" ) instanceTypesSet = set() for child in InstanceGraph: instanceTypesSet.add(child.tag) print("All types below the InstanceGraph:") for i in instanceTypesSet: print(i) print("") print(len(Instances), "\t{http://www.plmxml.org/Schemas/PLMXMLSchema}Instance") print(len(Parts), "\t{http://www.plmxml.org/Schemas/PLMXMLSchema}Part") print(len(ProductInstances), "\t{http://www.plmxml.org/Schemas/PLMXMLSchema}ProductInstance") print( len(ProductRevisionViews), "\t{http://www.plmxml.org/Schemas/PLMXMLSchema}ProductRevisionView", ) # handle all instances for child in Instances: addReference(child) # handle the parts and assemblies for child in Parts: if "type" in child.attrib: if child.attrib["type"] == "solid": addPart(child) continue if child.attrib["type"] == "assembly": addAssembly(child) continue print("Unknown Part type:", child) else: print("not Type in Part", child) if __name__ == "__main__": main()