/**
  * @param Pyrus\Developer\CodeCoverage\SourceFile $source
  * @param string $istest path to test file this is covering, or false for aggregate
  */
 function render(SourceFile $source, $istest = false)
 {
     $output = new \XMLWriter();
     if (!$output->openUri($this->manglePath($source->name(), $istest))) {
         throw new Exception('Cannot render ' . $source->name() . ', opening XML failed');
     }
     $output->setIndent(false);
     $output->startElement('html');
     $output->text("\n ");
     $output->startElement('head');
     $output->text("\n  ");
     if ($istest) {
         $output->writeElement('title', 'Code Coverage for ' . $source->shortName() . ' in ' . $istest);
     } else {
         $output->writeElement('title', 'Code Coverage for ' . $source->shortName());
     }
     $output->text("\n  ");
     $output->startElement('link');
     $output->writeAttribute('href', 'cover.css');
     $output->writeAttribute('rel', 'stylesheet');
     $output->writeAttribute('type', 'text/css');
     $output->endElement();
     $output->text("\n  ");
     $output->endElement();
     $output->text("\n ");
     $output->startElement('body');
     $output->text("\n ");
     if ($istest) {
         $output->writeElement('h2', 'Code Coverage for ' . $source->shortName() . ' in ' . $istest);
     } else {
         $output->writeElement('h2', 'Code Coverage for ' . $source->shortName());
     }
     $output->text("\n ");
     $output->writeElement('h3', 'Coverage: ' . $source->coveragePercentage() . '%');
     $output->text("\n ");
     $output->startElement('p');
     $output->startElement('a');
     $output->writeAttribute('href', 'index.html');
     $output->text('Aggregate Code Coverage for all tests');
     $output->endElement();
     $output->endElement();
     $output->startElement('pre');
     foreach ($source->source() as $num => $line) {
         $coverage = $source->coverage($num);
         $output->startElement('span');
         $output->writeAttribute('class', 'ln');
         $output->text(str_pad($num, 8, ' ', STR_PAD_LEFT));
         $output->endElement();
         if ($coverage === false) {
             $output->text(str_pad(': ', 13, ' ', STR_PAD_LEFT) . $line);
             continue;
         }
         $output->startElement('span');
         if ($coverage < 1) {
             $output->writeAttribute('class', 'nc');
             $output->text('           ');
         } else {
             $output->writeAttribute('class', 'cv');
             if (!$istest) {
                 $output->startElement('a');
                 $output->writeAttribute('href', $this->getLineLink($source->name(), $num));
             }
             $output->text(str_pad($coverage, 10, ' ', STR_PAD_LEFT) . ' ');
             if (!$istest) {
                 $output->endElement();
                 $this->renderLineSummary($source->name(), $num, $source->testpath(), $source->getLineLinks($num));
             }
         }
         $output->text(': ' . $line);
         $output->endElement();
     }
     $output->endElement();
     $output->text("\n ");
     $output->endElement();
     $output->text("\n ");
     $output->endElement();
     $output->endDocument();
 }