Michael,

Ok that clarifies a few things. I'm not just trying to wrap at the outer most level I'm trying to inject trace information at every level of the output from the XSLT. The general idea is to complete a debugging tool which tells the developer which template led to a given section of output within the output XML/HTML. 

I guess the point that is still confusing after this is how I would go about reconstructing the result in an expression "or constructing a new expression (which will typically produce the same result as the original, but perhaps with side-effects like outputting trace information or checking for a debugging breakpoint)". Is there a piece of code I can use as an example, or a description out how the expression types interact with each other?

So for example lets say as I'm moving through the system I have a document like

<document id="1">
<element>some text</element>
<document>

and I'm using just an identity template.
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="*|@*"/>
</xsl:copy>
</xsl:template>

 My goal is to inject information at each template run into the output of the xslt template expression such that the output document might look something like 

<document xmlns:trace="tracenamespace" id="1">
<trace:enter>
<trace:path>/document[1]</trace:path>
<trace:template>
<trace:firstline>&lt;xsl:template match="node()"&gt;</trace:firstline>
<trace:linenumber>55</trace:linenumber>
</trace:template>
<trace:templatelocation>/path/to/templatefile</trace:templatelocation>
<trace:enter>
<trace:enterattr>
<trace:path>/document[1]/@id</trace:path>
<trace:template>
<trace:firstline>&lt;xsl:template match="node()"&gt;</trace:firstline>
<trace:linenumber>55</trace:linenumber>
</trace:template>
<trace:templatelocation>/path/to/templatefile</trace:templatelocation>
<trace:enterattr>
<element>
<trace:enter>
<trace:path>/document[1]/element[1]</trace:path>
<trace:template>
<trace:firstline>&lt;xsl:template match="node()"&gt;</trace:firstline>
<trace:linenumber>55</trace:linenumber>
</trace:template>
<trace:templatelocation>/path/to/templatefile</trace:templatelocation>
<trace:enter>
some text
</element>
</document>

I have and am already displaying to the users all the information that is in these trace:enter elements so I'm not worried about obtaining the information (I showed you this at balisage last year) the remaining problem is that it is not associated with the output so the developer must try to figure out which one of and ordered set would have called each logged trace statement.

Does this clarify my objectives? Does your recommendation of my creating my own CodeInjector still stand with this clarification?

Again thank you much for the help,

-- Paul Ryan

On Aug 9, 2012, at 11:29 AM, Michael Kay wrote:


The idea of the CodeInjector interface is that you supply a CodeInjector, and the XPath parser calls the inject() method to process each expression on the expression tree; your CodeInjector then has the option of returning the original expression unchanged, or constructing a new expression (which will typically produce the same result as the original, but perhaps with side-effects like outputting trace information or checking for a debugging breakpoint). You should not be calling the inject() method yourself from the application level.

There isn't any direct way of supplying a CodeInjector when you are using the JAXP XPath interface (or, for that matter, when using the s9api interface). I think the only way to do it is to call the static method ExpressionTool.make(), which is a rather low-level interface.

The XSLTTraceCodeInjector isn't much use to you because it only injects code at the level of XSLT instructions, not within an XPath expression. Using the class TraceCodeInjector would make more sense; but I suspect a better approach would be write your own implementation of CodeInjector (you could use TraceCodeInjector as a model).

If you only want to wrap the parsed expression by some construct of your own at the outermost level, then you don't need the code injector at all. You could simply wrap the Expression returned by the XPath parser inside a TraceExpression.

Michael Kay
Saxonica