Source code for tools.printers.xmlPrinter

"""
.. module:: xmlPrinter
   :synopsis: Class for describing a printer in XML format

.. moduleauthor:: Andre Lessa <lessa.a.p@gmail.com>

"""

from __future__ import print_function
import sys
import os
from smodels.decomposition.topologyDict import TopologyDict
from smodels.matching.theoryPrediction import TheoryPredictionList,TheoryPrediction,TheoryPredictionsCombiner
from smodels.tools.ioObjects import OutputStatus
from smodels.tools.coverage import Uncovered
from smodels.base.smodelsLogging import logger
from smodels.tools.printers.pythonPrinter import PyPrinter
from xml.dom import minidom
from xml.etree import ElementTree


[docs]class XmlPrinter(PyPrinter): """ Printer class to handle the printing of one single XML output """ def __init__(self, output='stdout', filename=None, outputFormat='version3'): PyPrinter.__init__(self, output, filename, outputFormat) self.name = "xml" self.printingOrder = [OutputStatus, TopologyDict, TheoryPredictionList, TheoryPredictionsCombiner, TheoryPrediction, Uncovered] self.toPrint = [None]*len(self.printingOrder)
[docs] def setOutPutFile(self, filename, overwrite=True, silent=False): """ Set the basename for the text printer. The output filename will be filename.xml. :param filename: Base filename :param overwrite: If True and the file already exists, it will be removed. :param silent: dont comment removing old files """ self.filename = filename + '.xml' if overwrite and os.path.isfile(self.filename): if not silent: logger.warning("Removing old output file " + self.filename) os.remove(self.filename)
[docs] def convertToElement(self, pyObj, parent, tag=""): """ Convert a python object (list,dict,string,...) to a nested XML element tree. :param pyObj: python object (list,dict,string...) :param parent: XML Element parent :param tag: tag for the daughter element """ tag = tag.replace(" ", "_").replace("(", "").replace(")", "") if not isinstance(pyObj, list) and not isinstance(pyObj, dict): parent.text = str(pyObj).lstrip().rstrip() elif isinstance(pyObj, dict): for key, val in sorted(pyObj.items()): key = key.replace(" ", "_").replace("(", "").replace(")", "") newElement = ElementTree.Element(key) self.convertToElement(val, newElement, tag=key) parent.append(newElement) elif isinstance(pyObj, list): parent.tag += '_List' for val in pyObj: newElement = ElementTree.Element(tag) self.convertToElement(val, newElement, tag) parent.append(newElement)
[docs] def flush(self): """ Get the python dictionaries generated by the object formatting to the defined output and convert to XML """ outputDict = {} for obj in self.toPrint: if obj is None: continue output = self._formatObj(obj) # Convert to python dictionaries if not output: continue # Skip empty output outputDict.update(output) root = None # Convert from python dictionaries to xml: if outputDict: root = ElementTree.Element('smodelsOutput') self.convertToElement(outputDict, root) rough_xml = ElementTree.tostring(root, 'utf-8') nice_xml = minidom.parseString( rough_xml).toprettyxml(indent=" ") if self.output == 'stdout': sys.stdout.write(nice_xml) elif self.output == 'file': if not self.filename: logger.error('Filename not defined for printer') return False with open(self.filename, "a") as outfile: outfile.write(nice_xml) outfile.close() self.toPrint = [None]*len(self.printingOrder) return root