XML report with line level info for Sonar integration.
diff --git a/org.jacoco.doc/buildhook.xml b/org.jacoco.doc/buildhook.xml
index 27ba72f..50aebbf 100644
--- a/org.jacoco.doc/buildhook.xml
+++ b/org.jacoco.doc/buildhook.xml
@@ -91,6 +91,10 @@
 			<csv destfile="${result.dist.coverage.dir}/coverage.csv"/>

 			<xml destfile="${result.dist.coverage.dir}/coverage.xml"/>

 		</jacoco:report>

+

+		<copy todir="${result.dist.coverage.dir}">

+			<fileset dir="${source.org.jacoco.report.dir}/src/org/jacoco/report/xml" includes="report.dtd"/>

+		</copy>

 	</target>

 	

 	

diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html
index 0531576..0584d9d 100644
--- a/org.jacoco.doc/docroot/doc/changes.html
+++ b/org.jacoco.doc/docroot/doc/changes.html
@@ -23,6 +23,7 @@
 <ul>

   <li>Support for different archives (jar, war, ear etc.) and nested archives

   (Trac #78).</li>

+  <li>XML report with line level coverage information (requested for Sonar).</li>

 </ul>

 

 <h2>Release 0.3.2 (2010/04/01)</h2>

diff --git a/org.jacoco.report/src/org/jacoco/report/xml/XMLReportNodeHandler.java b/org.jacoco.report/src/org/jacoco/report/xml/XMLReportNodeHandler.java
index 5dc7cd8..7c42131 100644
--- a/org.jacoco.report/src/org/jacoco/report/xml/XMLReportNodeHandler.java
+++ b/org.jacoco.report/src/org/jacoco/report/xml/XMLReportNodeHandler.java
@@ -7,7 +7,7 @@
  *

  * Contributors:

  *    Brock Janiczak - initial API and implementation

- *    Marc R. Hoffmann - generalized structure 

+ *    Marc R. Hoffmann - generalized structure, line info

  *    

  * $Id: $

  *******************************************************************************/

@@ -15,9 +15,9 @@
 

 import java.io.IOException;

 

-import org.jacoco.core.analysis.ClassCoverage;

 import org.jacoco.core.analysis.ICounter;

 import org.jacoco.core.analysis.ICoverageNode;

+import org.jacoco.core.analysis.ILines;

 import org.jacoco.core.analysis.MethodCoverage;

 import org.jacoco.core.analysis.ICoverageNode.CounterEntity;

 import org.jacoco.core.analysis.ICoverageNode.ElementType;

@@ -64,13 +64,21 @@
 		case PACKAGE:

 			return new XMLReportNodeHandler(element.element("package"), node);

 		case CLASS:

-			final XMLElement classChild = element.element("class");

-			addClassAttributes(classChild, (ClassCoverage) node);

-			return new XMLReportNodeHandler(classChild, node);

+			return new XMLReportNodeHandler(element.element("class"), node);

 		case METHOD:

 			final XMLElement methodChild = element.element("method");

-			addMethodAttributes(methodChild, (MethodCoverage) node);

+			methodChild.attr("desc", ((MethodCoverage) node).getDesc());

 			return new XMLReportNodeHandler(methodChild, node);

+		case SOURCEFILE:

+			return new XMLReportNodeHandler(element.element("sourcefile"), node) {

+				@Override

+				public void visitEnd(final ISourceFileLocator sourceFileLocator)

+						throws IOException {

+					writeLines(node.getLines(), element);

+					super.visitEnd(sourceFileLocator);

+				}

+

+			};

 		}

 		return IReportVisitor.NOP;

 	}

@@ -95,35 +103,26 @@
 		}

 	}

 

-	private static void addClassAttributes(final XMLElement element,

-			final ClassCoverage node) throws IOException {

-		if (node.getSignature() != null) {

-			element.attr("signature", node.getSignature());

-		}

-		if (node.getSuperName() != null) {

-			element.attr("superclass", node.getSuperName());

-		}

-		if (node.getInterfaceNames() != null) {

-			boolean first = true;

-			final StringBuilder builder = new StringBuilder();

-			for (final String iface : node.getInterfaceNames()) {

-				if (first) {

-					first = false;

-				} else {

-					builder.append(' ');

+	private void writeLines(final ILines lines, final XMLElement parent)

+			throws IOException {

+		final int last = lines.getLastLine();

+		for (int nr = lines.getFirstLine(); nr <= last; nr++) {

+			final byte status = lines.getStatus(nr);

+			if (status != ILines.NO_CODE) {

+				final XMLElement line = parent.element("line");

+				line.attr("nr", nr);

+				switch (status) {

+				case ILines.NOT_COVERED:

+					line.attr("status", "N");

+					break;

+				case ILines.PARTLY_COVERED:

+					line.attr("status", "P");

+					break;

+				case ILines.FULLY_COVERED:

+					line.attr("status", "F");

+					break;

 				}

-				builder.append(iface);

 			}

-			element.attr("interfaces", builder.toString());

-		}

-	}

-

-	private static void addMethodAttributes(final XMLElement element,

-			final MethodCoverage node) throws IOException {

-		element.attr("desc", node.getDesc());

-		final String signature = node.getSignature();

-		if (signature != null) {

-			element.attr("signature", signature);

 		}

 	}

 

diff --git a/org.jacoco.report/src/org/jacoco/report/xml/report.dtd b/org.jacoco.report/src/org/jacoco/report/xml/report.dtd
index 11164d9..2264242 100644
--- a/org.jacoco.report/src/org/jacoco/report/xml/report.dtd
+++ b/org.jacoco.report/src/org/jacoco/report/xml/report.dtd
@@ -7,35 +7,40 @@
   

    Contributors:

       Brock Janiczak - initial API and implementation

-      Marc R. Hoffmann - generalized report structure

+      Marc R. Hoffmann - generalized report structure, line info

       

    $Id: $

 -->

 

-<!ELEMENT report ((group* , package*) , counter*)>

+<!ELEMENT report (group* , package* , counter*)>

 <!ATTLIST report

   name CDATA #REQUIRED>

 

-<!ELEMENT group ((group* , package*) , counter*)>

+<!ELEMENT group (group* , package* , counter*)>

 <!ATTLIST group

   name CDATA #REQUIRED>

 

-<!ELEMENT package ((class*) , counter*)>

+<!ELEMENT package ((class | sourcefile)* , counter*)>

 <!ATTLIST package

   name CDATA #REQUIRED>

 

-<!ELEMENT class ((method*), counter*)>

+<!ELEMENT class (method*, counter*)>

 <!ATTLIST class

-  name CDATA #REQUIRED

-  signature CDATA #IMPLIED

-  superclass CDATA #IMPLIED

-  interfaces CDATA #IMPLIED>

+  name CDATA #REQUIRED>

 

 <!ELEMENT method (counter*)>

 <!ATTLIST method

   name CDATA #REQUIRED

-  desc CDATA #REQUIRED

-  signature CDATA #IMPLIED>

+  desc CDATA #REQUIRED>

+  

+<!ELEMENT sourcefile (line*)>

+<!ATTLIST sourcefile

+  name CDATA #REQUIRED>

+

+<!ELEMENT line EMPTY>

+<!ATTLIST line

+  nr     CDATA #REQUIRED

+  status (N|P|F) #REQUIRED>

 

 <!ELEMENT counter EMPTY>

 <!ATTLIST counter