diff --git a/lcov_cobertura/lcov_cobertura.py b/lcov_cobertura/lcov_cobertura.py index 15783b3..c0f1e3b 100755 --- a/lcov_cobertura/lcov_cobertura.py +++ b/lcov_cobertura/lcov_cobertura.py @@ -14,8 +14,7 @@ import os import time import subprocess # nosec - not for untrusted input - -from xml.dom import minidom # nosec - not for untrusted input +from xml.etree import cElementTree from optparse import OptionParser from distutils.spawn import find_executable @@ -238,13 +237,8 @@ def generate_cobertura_xml(self, coverage_data, **kwargs): :type coverage_data: dict """ - dom_impl = minidom.getDOMImplementation() - doctype = dom_impl.createDocumentType("coverage", None, - "http://cobertura.sourceforge.net/xml/coverage-04.dtd") - document = dom_impl.createDocument(None, "coverage", doctype) - root = document.documentElement summary = coverage_data['summary'] - self._attrs(root, { + root = cElementTree.Element('coverage', { 'branch-rate': self._percent(summary['branches-total'], summary['branches-covered']), 'branches-covered': str(summary['branches-covered']), @@ -258,26 +252,23 @@ def generate_cobertura_xml(self, coverage_data, **kwargs): 'version': '2.0.3' }) - sources = self._el(document, 'sources', {}) - source = self._el(document, 'source', {}) - source.appendChild(document.createTextNode(self.base_dir)) - sources.appendChild(source) - - root.appendChild(sources) + sources = cElementTree.SubElement(root, 'sources') + source = cElementTree.SubElement(sources, 'source') + source.text = self.base_dir - packages_el = self._el(document, 'packages', {}) + packages_el = cElementTree.SubElement(root, 'packages') packages = coverage_data['packages'] for package_name, package_data in list(packages.items()): - package_el = self._el(document, 'package', { + package_el = cElementTree.SubElement(packages_el, 'package', { 'line-rate': package_data['line-rate'], 'branch-rate': package_data['branch-rate'], 'name': package_name, 'complexity': '0', }) - classes_el = self._el(document, 'classes', {}) + classes_el = cElementTree.SubElement(package_el, 'classes') for class_name, class_data in list(package_data['classes'].items()): - class_el = self._el(document, 'class', { + class_el = cElementTree.SubElement(classes_el, 'class', { 'branch-rate': self._percent(class_data['branches-total'], class_data['branches-covered']), 'complexity': '0', @@ -288,78 +279,66 @@ def generate_cobertura_xml(self, coverage_data, **kwargs): }) # Process methods - methods_el = self._el(document, 'methods', {}) + methods_el = cElementTree.SubElement(class_el, 'methods') for method_name, (line, hits) in list(class_data['methods'].items()): - method_el = self._el(document, 'method', { + method_el = cElementTree.SubElement(methods_el, 'method', { 'name': self.format(method_name), 'signature': '', 'line-rate': '1.0' if int(hits) > 0 else '0.0', 'branch-rate': '1.0' if int(hits) > 0 else '0.0', }) - method_lines_el = self._el(document, 'lines', {}) - method_line_el = self._el(document, 'line', { + method_lines_el = cElementTree.SubElement(method_el, 'lines') + cElementTree.SubElement(method_lines_el, 'line', { 'hits': hits, 'number': line, 'branch': 'false', }) - method_lines_el.appendChild(method_line_el) - method_el.appendChild(method_lines_el) - methods_el.appendChild(method_el) # Process lines - lines_el = self._el(document, 'lines', {}) + lines_el = cElementTree.SubElement(class_el, 'lines') lines = list(class_data['lines'].keys()) lines.sort() for line_number in lines: - line_el = self._el(document, 'line', { - 'branch': class_data['lines'][line_number]['branch'], - 'hits': str(class_data['lines'][line_number]['hits']), - 'number': str(line_number) - }) if class_data['lines'][line_number]['branch'] == 'true': total = int(class_data['lines'][line_number]['branches-total']) covered = int(class_data['lines'][line_number]['branches-covered']) percentage = int((covered * 100.0) / total) - line_el.setAttribute('condition-coverage', - '{0}% ({1}/{2})'.format( - percentage, covered, total)) - lines_el.appendChild(line_el) - - class_el.appendChild(methods_el) - class_el.appendChild(lines_el) - classes_el.appendChild(class_el) - package_el.appendChild(classes_el) - packages_el.appendChild(package_el) - root.appendChild(packages_el) - - return document.toprettyxml(**kwargs) - - def _el(self, document, name, attrs): + attr = { + 'branch': class_data['lines'][line_number]['branch'], + 'condition-coverage': '{0}% ({1}/{2})'.format(percentage, covered, total), + 'hits': str(class_data['lines'][line_number]['hits']), + 'number': str(line_number) + } + else: + attr = { + 'branch': class_data['lines'][line_number]['branch'], + 'hits': str(class_data['lines'][line_number]['hits']), + 'number': str(line_number) + } + cElementTree.SubElement(lines_el, 'line', attr) + + return self._tostring(root) + + def _tostring(self, document): """ - Create an element within document with given name and attributes. - - :param document: Document element - :type document: Document - :param name: Element name - :type name: string - :param attrs: Attributes for element - :type attrs: dict - """ - return self._attrs(document.createElement(name), attrs) + Convert xml element to a string. - def _attrs(self, element, attrs): - """ - Set attributes on given element. + :param document: Object of cElementTree.Element to be converted + """ - :param element: DOM Element - :type element: Element - :param attrs: Attributes for element - :type attrs: dict - """ - for attr, val in list(attrs.items()): - element.setAttribute(attr, val) - return element + header = """ + +""" + import sys + if sys.version_info[0] == 2: + xml_string = cElementTree.tostring(document) + return header + xml_string + else: + xml_string = cElementTree.tostring(document, encoding='unicode') + return header + xml_string + def _percent(self, lines_total, lines_covered): """ Get the percentage of lines covered in the total, with formatting.