Project

Profile

Help

Support #6021

closed

I cannot combine XSLT instructions with actual XML output during tracing. The XML output is "too late".

Added by Gerben Abbink about 1 year ago. Updated 12 months ago.

Status:
Closed
Priority:
Low
Assignee:
-
Category:
-
Sprint/Milestone:
-
Start date:
2023-05-08
Due date:
% Done:

0%

Estimated time:
Legacy ID:
Applies to branch:
Fix Committed on Branch:
Fixed in Maintenance Release:
Platforms:

Description

I am trying to combine the output of an XSLT transformation during tracing with the actual XSLT instructions.

I have implemented a TraceListener and a Writer.

However, the output XML that is send to the Writer is always "too late".

In this example, TraceListener's enter() is called with a NamespaceConstructor, but no namespace is actually written to the XML output at that moment. The namespace is written later during FixedElement.

Am I doing something wrong?
...
enter instruction 21:34 net.sf.saxon.expr.instruct.ForEach 2:54
enter instruction 22:52 net.sf.saxon.expr.instruct.NamespaceConstructor 3:45 << **NamespaceConstructor**
leave instruction 22:52 net.sf.saxon.expr.instruct.NamespaceConstructor
...
enter instruction 102:69 net.sf.saxon.expr.instruct.FixedElement 5:107
        [<?xml version="]
        [1.0]
        [" ]
        [encoding="]
        [UTF-8]
        ["]
        [?>]
        [
]
        [<]
        [xsl:stylesheet]
        [ ]
        [xmlns:pre]
        [=]
        ["]
        [http://www.ibm.com] << **Actual namespace in the XML output** .
        ["]
        [

Actions #1

Updated by Michael Kay about 1 year ago

Yes, this is quite challenging to achieve. There's some buffering of events at various stages in the pipeline, even if no variables are involved.

Most of the buffering occurs in the ComplexContentOutputter which receives the start element event, attribute, and namespace events individually, assembles them, and then issues a single start element event with all the attributes and namespaces when the first child node or end element event is received.

The most obvious reason for this buffering is the XSLT rule that if two attributes with the same name are written, the last one wins. There are other reasons as well, for example choosing a namespace prefix for the element name may depend on what namespace nodes are written.

To resynchronise the events, you might want to make use of the location information passed down the pipeline. It's not easy, but I think this is what the debuggers in products like Oxygen do.

Actions #2

Updated by Michael Kay about 1 year ago

  • Description updated (diff)
  • Status changed from New to In Progress
Actions #3

Updated by Gerben Abbink about 1 year ago

I have found a solution.

I store TraceListener's enter()/leave() events (XSLT instructions and XML input) in an array and parse Writer's write() for typical XML tokens such as "<", "</", etc. When I find a token I add it to the array. In the end I have an array filled XSLT instructions, XML input and XML output, just what I wanted.

Actions #4

Updated by Michael Kay about 1 year ago

I'm not sure why you're intercepting the output at the level of a Writer. Surely you can intercept it pre-serialisation by sending output to a SAXDestination or similar?

Actions #5

Updated by Michael Kay 12 months ago

  • Status changed from In Progress to Closed

Please register to edit this issue

Also available in: Atom PDF