hi everyone!

if you are (like me) less than amazed with the output formatting of cocoon's XmlSerializer, attached is an xslt that will provide quite nice formatting and indenting.

it's especially useful during site design, but since i believe in clear and correct xhtml, i'm going to use it for production as well (i'm dreaming of people looking at the source going, "this is so nice, why render it at all" :-D).

for maximum beauty and readability, it modifies the whitespace, but it does the Right Thing(tm) for html mixed content. if you have other, more fragile whitespace semantics, don't use it.

the clever bits have been stolen from http://www.dpawson.co.uk/xsl/.

just put the attached file into <yourpub>/xslt/ and add this snippet to your pipeline:

<map:select type="resource-exists">
  <map:parameter name="prefix" value="fallback://"/>
  <map:when test="xslt/xml-prettyprint.xsl">
    <map:transform src="fallback://xslt/xml-prettyprint.xsl"/>
  </map:when>
</map:select>

(tested with lenya 1.4, 1.2 procedure may differ.)

known problem:

the script will produce suboptimal results in deeply nested mixed content, but then again there's no way to solve that generically without knowledge about block-level and inline elements (which only applies to document-centric markup anyways).



have fun,


jörn




--
"Open source takes the bullshit out of software."
        - Charles Ferguson on TechnologyReview.com

--
Jörn Nettingsmeier, EDV-Administrator
Institut für Politikwissenschaft
Universität Duisburg-Essen, Standort Duisburg
Mail: [EMAIL PROTECTED], Telefon: 0203/379-2736
<?xml version="1.0" encoding="utf-8"?>

<!-- 
   xml prettyprinter for apache cocoon/lenya, (c) 2006 jörn nettingsmeier <[EMAIL PROTECTED]>
   everything that is non-trivial in this script has been borrowed from somewhere. this script is in the public domain.
-->

<xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
   <xsl:output method="xml"/>

   <xsl:param name="indent-increment" select="'  '" />

  <!-- 
    indentation
    thanks to John Mongan, taken from http://www.dpawson.co.uk/xsl/sect2/pretty.html
  -->

  <xsl:template match="*">
    <xsl:param name="indent" select="'&#xA;'"/>

    <xsl:value-of select="$indent"/>

    <xsl:copy>
      <xsl:copy-of select="@*" />
      <xsl:apply-templates>
        <xsl:with-param name="indent" select="concat($indent, $indent-increment)"/>
      </xsl:apply-templates>
      <!-- add a trailing newline if the node has children and is not a mixed content node -->
      <xsl:if test="* and not(*[../text()[normalize-space(.) != '']])">
        <xsl:value-of select="$indent"/>
      </xsl:if>
    </xsl:copy>
   </xsl:template>

   <xsl:template match="comment()|processing-instruction()">
      <xsl:copy />
   </xsl:template>

  <!-- 
    mixed content detection and handling
    thanks to David Carlisle and Wendell Piez, taken from http://www.dpawson.co.uk/xsl/sect2/normalise.html#d7206e52 
  -->
  <xsl:template match="*[../text()[normalize-space(.) != '']]">
    <!-- but this template matches any element appearing in mixed content -->
    <xsl:variable name="textbefore"
         select="preceding-sibling::node()[1][self::text()]"/>
    <xsl:variable name="textafter"
         select="following-sibling::node()[1][self::text()]"/>
    <!-- Either of the preceding variables will be an empty node set 
         if the neighbor node is not text(), right? -->
    <xsl:variable name="prevchar"
         select="substring($textbefore, string-length($textbefore))"/>
    <xsl:variable name="nextchar"
         select="substring($textafter, 1, 1)"/>
  
    <!-- Now the action: -->
    <xsl:if test="$prevchar != normalize-space($prevchar)">
    <!-- If the original text had a space before, add one back -->
      <xsl:text> </xsl:text>
    </xsl:if>
  
    <xsl:copy>
    <!-- Copy the element over -->
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates/>
    </xsl:copy>
  
    <xsl:if test="$nextchar != normalize-space($nextchar)">
    <!-- If the original text had a space after, add one back -->
      <xsl:text> </xsl:text>
    </xsl:if>
  
  </xsl:template>

<!--
  normalize all whitespace in text nodes (i.e. those that don't get matched by the mixed content handler)
-->
  <xsl:template match="text()">
    <xsl:value-of select="normalize-space(.)"/>
  </xsl:template>

</xsl:stylesheet>

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to