This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: xsl self-documentation on the fly (Perl?)


John,

>I am trying to create xsl transformation templates with a feature that
>documents that they have been applied (on an xml file) and where they have
>been applied (either node or line number in the text).  It would be ideal if
>this documentation could be in a seperate file that is a log of all changes
>in the original xml files.  

This sounds like an interesting challenge! :)  I'm going to assume that
when you talk about logging changes in the original xml files, you're
talking about logging the transformations that were applied to them by the
XSLT stylesheet (as per your first sentence) and not trying to compare such
a log with a previous log to identify where an XML document had been
changed (externally).  I'm also going to assume that you want to create an
XML log file rather than plain text.

The first thing I thought of was using saxon:output or xt:document to
create your log, but the problem is that whenever you direct output to a
file, it overwrites that file (you can't just append to it), which ruins
that option as far as I can make out.

The second option is to use xsl:message to create your log.  Unfortunately
the messages go to stderr rather than stdout - perhaps there's a way of
capturing them, but I'm not sure what it is (and it'll depend on what
processor you're using and on what operating system).

So, the final thing I can think of would be to have the log become the
output of your stylesheet, either mixed up in your actual output (and then
postprocessed to separate it), or not.  What may be big disadavantages of
this method is that the log will not reflect the order of activation of the
templates, nor will it work if there is something wrong in your stylesheet.
 If you want to go this route I'd set up a stylesheet parameter:

  <xsl:param name="log" select="'false'" />

When you want to create a log on a particular XML document, run the
stylesheet with the parameter 'log' set to 'true' instead.

Then, within the template to be logged, have:

  <xsl:template match="foo">
    <xsl:if test="$log = 'true'">
      <xsl:call-template name="log-template">
        <xsl:with-param name="match" select="'foo'" />
      </xsl:call-template>
    </xsl:if>
    <!-- rest of the body of the template -->
  </xsl:template>

The template that actually does the logging could be used within
xsl:message if you went that route, as well as in this solution:

  <xsl:template name="log-template">
    <xsl:param name="match" />
    <xsl:param name="mode" />
    <xsl:param name="name" />
    <log:template>
      <log:node>
        <!-- this cribbed and slightly modified for 
             human-readability in the log from a
             David Carlisle contribution             -->
        <xsl:for-each select="ancestor-or-self::*">
          <xsl:variable name="nodename" select="name()" />
          <xsl:text>/</xsl:text>
          <xsl:value-of select="$nodename" />
          <xsl:text>[</xsl:text>
          <xsl:value-of
            select="1 + count(preceding-sibling::*[name() = $nodename])"/>
          <xsl:text>]</xsl:text>
        </xsl:for-each>
      </log:node>
      <xsl:if test="$match">
        <log:match><xsl:value-of select="$match" /></log:match>
      </xsl:if>
      <xsl:if test="$mode">
        <log:match><xsl:value-of select="$mode" /></log:match>
      </xsl:if>
      <xsl:if test="$name">
        <log:match><xsl:value-of select="$name" /></log:match>
      </xsl:if>
    </log:template>
  </xsl:template>

This produces a log that looks like:

  <log:template xmlns:log="lognamespace">
    <log:node>/classes[1]/class[1]</log:node>
    <log:match>class</log:match>
  </log:template>

Of course you may have your own format in mind for the log.

Note that you have to set the parameter by hand within each template, which
is a bit tedious.  It would be better if you could grab those directly,
along with the values for any parameters, which you probably could with a
bit of jiggery-pokery, but I'm not going to go down that route right now
just in case I've completely missed the point of what you're after.

As far as postprocessing to get this into a file on its own: you could then
run over the output from the stylesheet with another stylesheet that copied
only the elements within the 'log' namespace.

Actually, the very best solution would be to find an XSLT processor that
generated a log itself, then you wouldn't have to fill your stylesheet with
this gumph.  I don't know that any of them do, though.

I hope this helps, anyway.

Cheers,

Jeni

Dr Jeni Tennison
Epistemics Ltd, Strelley Hall, Nottingham, NG8 6PE
Telephone 0115 9061301 • Fax 0115 9061304 • Email
jeni.tennison@epistemics.co.uk



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]