Search code examples
cssxmlxsltmozilla

XSLT trying to locally reference default Mozilla styles


I would like to understand more how the default Mozilla XSLT works as I like the way in which an XML document is displayed by default and the various nodes can be expanded / minimised.

I obtained copies of the following:

I couldn't find the following ones in the same way and instead got them through the Mozilla browser, saving them locally. ie.

chrome://global/locale/xml/prettyprint.dtd
  • prettyprint.dtd
  • global.dtd

All four files are saved into the same folder.

Some simple XML is prepared and saved in the same folder:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="XMLPrettyPrint.xsl"?>
<breakfast_menu>
    <food>
        <name>Belgian Waffles</name>
        <price>$5.95</price>
    </food>
    <food>
        <name>Strawberry Belgian Waffles</name>
        <price>$7.95</price>
    </food>
</breakfast_menu>

In XMLPrettyPrint.xsl I edit the following:

<xsl:template match="/">
  <link href="chrome://global/content/xml/XMLPrettyPrint.css" type="text/css" rel="stylesheet"/>
  <link title="Monospace" href="chrome://global/content/xml/XMLMonoPrint.css" type="text/css" rel="alternate stylesheet"/>
  ...
</xsl:template>

to

<xsl:template match="/">
  <link href="XMLPrettyPrint.css" type="text/css" rel="stylesheet"/>
  <link title="Monospace" href="XMLMonoPrint.css" type="text/css" rel="alternate stylesheet"/>
  ...
</xsl:template>

If I open the XML file Mozilla it only partly works. The document looks to be formatted correctly but the colours aren't present nor do the nodes collapse.

What else do I need to change?

Edit 2016.03.29 @ 16:00

<xsl:template match="/">
<html>
<head>
  <link href="XMLPrettyPrint.css" type="text/css" rel="stylesheet"/>
  <link title="Monospace" href="XMLMonoPrint.css" type="text/css" rel="alternate stylesheet"/>
  <div id="header" dir="&locale.dir;">
    <p>
      &xml.nostylesheet;
    </p>
  </div>
</head>
<body>
  <xsl:apply-templates/>
</body>
</html>
</xsl:template>

Update to @import url

/*@import url("resource://gre-resources/viewsource.css");*/
@import url("viewsource.css");

Solution

  • The syntax highlighting (coloring) CSS rules are defined in the viewsource.css file, but they only apply to elements that have an ancestor in the highlight class.

    The XMLPrettyPrint.xsl file doesn't produce anything with a highlight class, so you can remedy this by wrapping the <xsl:apply-templates/> from the first xsl:template in a div that has this class:

    <div class="highlight">
      <xsl:apply-templates/>
    </div>
    

    Now the results render in color, but they are too close to the left side and the on the root element is missing. This is because Mozilla's pretty print renderer seems to surround the results with some padding and that is in a div with the expander class, which has a left margin of -16px.

    You can remedy this by giving your wrapper div 16px of padding on the left:

    <div class="highlight" style="padding-left: 16px">
      <xsl:apply-templates/>
    </div>
    

    You need some JavaScript in order to make the expand/collapse functionality work. The XMLPrettyPrint.xml file defines the code for this. You can include it in your XSLT by putting it in a <script> element.

    In order to attach the event, you can give the wrapper div an ID and select it to attach the event:

    <div id="content" class="highlight" style="padding-left: 16px">
      <xsl:apply-templates/>
    </div>
    <script>
        <![CDATA[
        document.getElementById('content').addEventListener('click', function (event) {
            try {
                var par = event.target;
                if (par.nodeName == 'div' && par.className == 'expander') {
                    if (par.parentNode.className == 'expander-closed') {
                        par.parentNode.className = 'expander-open';
                        par.firstChild.data = '\u2212';
                    }
                    else {
                        par.parentNode.className = 'expander-closed';
                        par.firstChild.data = '+';
                    }
                }
            } catch (e) {
            }
        });
        ]]>
    </script>
    

    Once you've got that, the rendered HTML should behave just like Mozilla's default renderer.