Index: releaseNotes.xml
===================================================================
--- releaseNotes.xml	(revision 322)
+++ releaseNotes.xml	(working copy)
@@ -16,5 +16,6 @@
         <note module="admin" type="fix">AMRUN-201 : In user information window, an &gt;Enumeration&lt; parameter creates a combo with an empty value (the value is displayed next to the label)</note>
     	<note module="kernel" type="fix">AMRUN-203 : Loading JS with bad encoding</note>
     	<note module="kernel" type="fix">AMRUN-205 : Kernel i18n not working</note>
+        <note module="kernel" type="add">AMRUN-200 : Added a new XHTML serializer, based on cocoon's XHTMLSerializer, which doesn't collapse most of the tags. New jars were added to the kernel and to the application template, so make sure to add them to your project.</note>
     </release>
 </releases>
\ No newline at end of file
Index: main/kernel/src/org/ametys/runtime/cocoon/XHTMLSerializer.java
===================================================================
--- main/kernel/src/org/ametys/runtime/cocoon/XHTMLSerializer.java	(revision 0)
+++ main/kernel/src/org/ametys/runtime/cocoon/XHTMLSerializer.java	(revision 0)
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2007 Anyware Technologies and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/eclipse-1.0.php
+ * 
+ * Contributors:
+ *     Anyware Technologies - initial API and implementation
+ */
+package org.ametys.runtime.cocoon;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.xml.sax.SAXException;
+
+/**
+ * Inherits from cocoon's serializers block XHTMLSerializer.
+ * Does not collapse most of the tags, except those specified by the _COLLAPSE_TAGS attribute.
+ */
+public class XHTMLSerializer extends org.apache.cocoon.components.serializers.XHTMLSerializer
+{
+
+    /** List of the tags to collapse. */
+    protected static final List<String> _COLLAPSE_TAGS = Arrays.asList(new String[] {"input", "img", "meta", "link"});
+
+    /** Buffer to store script tag content. */
+    protected StringBuffer _bufferedScriptChars;
+
+    /** Script context : greater than 0 if in a script tag. */
+    private int _isScript;
+
+    /** Meta http-equiv="Content-Type" context. True if in a meta "content-type" tag.*/
+    private boolean _isMetaContentType;
+
+    /** Define whether to put XML declaration in the head of the document. */
+    private boolean _omitXmlDeclaration;
+
+    @Override
+    public void configure(Configuration conf) throws ConfigurationException
+    {
+        super.configure(conf);
+        String omitXmlDeclaration = conf.getChild("omit-xml-declaration").getValue(null);
+        // Default false (don't omit).
+        this._omitXmlDeclaration = "yes".equals(omitXmlDeclaration);
+    }
+
+    @Override
+    public void startDocument() throws SAXException
+    {
+        super.startDocument();
+        _isScript = 0;
+        _isMetaContentType = false;
+        _bufferedScriptChars = new StringBuffer();
+    }
+
+    @Override
+    public void charactersImpl(char[] data, int start, int length) throws SAXException
+    {
+        if (_isScript > 0)
+        {
+            _bufferedScriptChars.append(data, start, length);
+        }
+        else
+        {
+            super.charactersImpl(data, start, length);
+        }
+    }
+
+    @Override
+    public void startElementImpl(String uri, String local, String qual, String[][] namespaces, String[][] attributes) throws SAXException
+    {
+        if (local.equalsIgnoreCase("script"))
+        {
+            _isScript++;
+        }
+
+        // Ignore the content-type meta tag if xml declaration is present
+        _isMetaContentType = isMetaContentType(local, attributes);
+        if (!_isMetaContentType || _omitXmlDeclaration)
+        {
+            super.startElementImpl(uri, local, qual, namespaces, attributes);
+        }
+    }
+
+    @Override
+    public void endElementImpl(String uri, String local, String qual) throws SAXException
+    {
+        String namespaceUri = uri;
+        if (uri.length() == 0)
+        {
+            namespaceUri = XHTML1_NAMESPACE;
+        }
+
+        if (local.equalsIgnoreCase("script"))
+        {
+            _isScript--;
+            String scriptContent = _bufferedScriptChars.toString();
+            _bufferedScriptChars = new StringBuffer();
+            super.comment(scriptContent.toCharArray(), 0, scriptContent.length());
+        }
+
+        if (XHTML1_NAMESPACE.equals(namespaceUri))
+        {
+            // If the element is not in the list of the tags to collapse, close it without collapsing
+            if (!_COLLAPSE_TAGS.contains(local))
+            {
+                this.closeElement(false);
+            }
+        }
+        
+        // Ignore the content-type meta tag if xml declaration is present
+        if (!_isMetaContentType || _omitXmlDeclaration)
+        {
+            super.endElementImpl(namespaceUri, local, qual);
+        }
+        else
+        {
+            _isMetaContentType = false;
+        }
+    }
+
+    @Override
+    public void comment(char[] data, int start, int length) throws SAXException
+    {
+        if (_isScript > 0)
+        {
+            _bufferedScriptChars.append(data, start, length);
+        }
+        else
+        {
+            super.comment(data, start, length);
+        }
+    }
+
+    private boolean isMetaContentType(String local, String[][] attributes)
+    {
+        if (local.equalsIgnoreCase("meta"))
+        {
+            for (String[] attr : attributes)
+            {
+                if (attr[ATTRIBUTE_LOCAL].equalsIgnoreCase("http-equiv") && attr[ATTRIBUTE_VALUE].equalsIgnoreCase("Content-Type"))
+                {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+}
