# Buggy code
def on_file(self, tree: MypyFile, type_map: Dict[Node, Type]) -> None:
    import lxml.etree as etree

    self.last_xml = None
    path = os.path.relpath(tree.path)
    if stats.is_special_module(path):
        return
    if path.startswith(".."):
        return
    if "stubs" in path.split("/"):
        return

    visitor = stats.StatisticsVisitor(inferred=True, typemap=type_map, all_nodes=True)
    tree.accept(visitor)

    root = etree.Element("mypy-report-file", name=path, module=tree._fullname)
    doc = etree.ElementTree(root)
    file_info = FileInfo(path, tree._fullname)

    with open(path) as input_file:
        for lineno, line_text in enumerate(input_file, 1):
            status = visitor.line_map.get(lineno, stats.TYPE_EMPTY)
            file_info.counts[status] += 1
            etree.SubElement(
                root,
                "line",
                number=str(lineno),
                precision=stats.precision_names[status],
                content=line_text[:-1],
            )
    # Assumes a layout similar to what XmlReporter uses.
    xslt_path = os.path.relpath("mypy-html.xslt", path)
    xml_pi = etree.ProcessingInstruction("xml", 'version="1.0" encoding="utf-8"')
    transform_pi = etree.ProcessingInstruction(
        "xml-stylesheet", 'type="text/xsl" href="%s"' % cgi.escape(xslt_path, True)
    )
    root.addprevious(xml_pi)
    root.addprevious(transform_pi)
    self.schema.assertValid(doc)

    self.last_xml = doc
    self.files.append(file_info)


# Traceback (ValueError)
$ mypy --html-report mypy_dir defaultdict_example.py
Traceback (most recent call last):
File "/Users/rwilliams/src/oss/mypy/.venv/bin/mypy", line 6, in <module>
main(__file__)
File "/Users/rwilliams/src/oss/mypy/.venv/lib/python3.5/site-packages/mypy_lang-0.2.0.dev0-py3.5.egg/mypy/main.py", line 91, in main
type_check_only(sources, bin_dir, options)
File "/Users/rwilliams/src/oss/mypy/.venv/lib/python3.5/site-packages/mypy_lang-0.2.0.dev0-py3.5.egg/mypy/main.py", line 134, in type_check_only
python_path=options.python_path)
File "/Users/rwilliams/src/oss/mypy/.venv/lib/python3.5/site-packages/mypy_lang-0.2.0.dev0-py3.5.egg/mypy/build.py", line 197, in build
result = manager.process(initial_states)
File "/Users/rwilliams/src/oss/mypy/.venv/lib/python3.5/site-packages/mypy_lang-0.2.0.dev0-py3.5.egg/mypy/build.py", line 383, in process
next.process()
File "/Users/rwilliams/src/oss/mypy/.venv/lib/python3.5/site-packages/mypy_lang-0.2.0.dev0-py3.5.egg/mypy/build.py", line 857, in process
self.manager.reports.file(self.tree, type_map=self.manager.type_checker.type_map)
File "/Users/rwilliams/src/oss/mypy/.venv/lib/python3.5/site-packages/mypy_lang-0.2.0.dev0-py3.5.egg/mypy/report.py", line 41, in file
reporter.on_file(tree, type_map)
File "/Users/rwilliams/src/oss/mypy/.venv/lib/python3.5/site-packages/mypy_lang-0.2.0.dev0-py3.5.egg/mypy/report.py", line 138, in on_file
xml_pi = etree.ProcessingInstruction('xml', 'version="1.0" encoding="utf-8"')
File "src/lxml/lxml.etree.pyx", line 3039, in lxml.etree.ProcessingInstruction (src/lxml/lxml.etree.c:81073)
ValueError: Invalid PI name 'b'xml''

# Fixed code
def on_file(self, tree: MypyFile, type_map: Dict[Node, Type]) -> None:
    import lxml.etree as etree

    self.last_xml = None
    path = os.path.relpath(tree.path)
    if stats.is_special_module(path):
        return
    if path.startswith(".."):
        return
    if "stubs" in path.split("/"):
        return

    visitor = stats.StatisticsVisitor(inferred=True, typemap=type_map, all_nodes=True)
    tree.accept(visitor)

    root = etree.Element("mypy-report-file", name=path, module=tree._fullname)
    doc = etree.ElementTree(root)
    file_info = FileInfo(path, tree._fullname)

    with open(path) as input_file:
        for lineno, line_text in enumerate(input_file, 1):
            status = visitor.line_map.get(lineno, stats.TYPE_EMPTY)
            file_info.counts[status] += 1
            etree.SubElement(
                root,
                "line",
                number=str(lineno),
                precision=stats.precision_names[status],
                content=line_text[:-1],
            )
    # Assumes a layout similar to what XmlReporter uses.
    xslt_path = os.path.relpath("mypy-html.xslt", path)
    transform_pi = etree.ProcessingInstruction(
        "xml-stylesheet", 'type="text/xsl" href="%s"' % cgi.escape(xslt_path, True)
    )
    root.addprevious(transform_pi)
    self.schema.assertValid(doc)

    self.last_xml = doc
    self.files.append(file_info)