On 3/12/23 23:24, Bederov, Sergey wrote:

Eric, thank you for your interest in this subject.

The issue tracker appears to be inactive since 2011, and it’s not possible to register an account there.

Your XSLT files didn’t work for me with an error “An attempt was made to insert a node where it is not permitted”, apparently because they are attempting to create multiple elements “first”, “emitted”, “Output” and “last” at the root level. I added a new wrapping element to the “Root” template and it started working a bit better.

While the multiple top-level elements of output is not OK for an XML document, I don't think anything stops you from emitted such with XSL, and my test with org.apache.xalan.xslt.Process did work. Did it not work for you because of what you were doing with the output or the Transform simply refuse to run with these xslt files?

For the “TestNotOK.xsl” file, all three XSLT engines (JDK-Xalan, Xalan 2.7.2, Saxon) give the same result:

<OutputRoot xmlns:exslt="http://exslt.org/common"; xmlns:str="http://exslt.org/strings";>

 <first>foo</first>

 <emitted>foo</emitted>

 <Output>

   <Display></Display>

   <Usage></Usage>

   <Display></Display>

 </Output>

 <emitted>foo</emitted>

  <last>foo</last>

</OutputRoot>

The parameter isn’t being passed to the “Created” template.

For the “TestOK.xsl” file, Xalan 2.7.2 gives the same result,

This is peculiar because my version of testOK run with xalan 2.7.2 (or 2.7.3 RC) did not give the same result, it contained <Display>foo</Display> like your JDK-Xalan and Saxon runs. (And adding an OutputRoot wrapper did not change that for me. I suppose it's possible that the way org.apache.xalan.xslt.Process instantiates the Transformer it's getting a JDK Transformer, but that seems unlikely.)

but JDK-Xalan and Saxon work better:

<OutputRoot xmlns:exslt="http://exslt.org/common"; xmlns:str="http://exslt.org/strings";>

 <first>foo</first>

 <emitted>foo</emitted>

 <Output>

   <Display>foo</Display>

   <Usage></Usage>

   <Display>foo</Display>

 </Output>

 <emitted>foo</emitted>

  <last>foo</last>

</OutputRoot>

Here the parameter is being passed successfully. What’s the difference? “TestNotOK” and “TestOK” differ in having the “/” template.

Probably there is something to do with calling “apply-templates” on a result-tree-fragment. I have read somewhere that in such cases the result-tree-fragment is being treated as a separate document with its own “document element”, and the templates should be called on that document element first, but, since I don’t have a dedicated template for that element, a “default template” is being called, and at this moment the parameter is being forgotten. Probably the “/” template changes this behavior in some way. But I can’t understand why because your “/” template also ignores the parameter, and anyway it appears identical to the “default template” so I can’t see why it can make any difference.

I can't either. One can see how the "/" could be relevant to getting the param passed down through a hidden root element (if somehow it passed it), but I'm almost sure I saw the problem come and go with other changes less easy to rationalize, and your original case of it not working with the key usage but working without the key usage seem to be a case of that. So I still think there is an unexplained "stirring the pot" effect going on, even if you have found a way to stir the pot to where it works for your purposes. I would worry that some future code change would stir your pot again and cause things to break again.

These kinds of irrational seeming "stirring the pot" bugs can occur, say, when code changes cause data to be overwritten. I've seen this in C code, but it is harder to imagine in Java, except that in this case the data of your "created" variable is in the same Document structure as the xslt templates, and while I can't explain how that would work, it does point in the direction of something that might make sense, perhaps with inadvertent changes to the nodes in that variable. (I am also doing these tests on Unix, and your line breaks indicate Windows, and while I think I cleaned that up before my most recent tests, one could imagine something hidden going on with an editor silently introducing or eliminating what xalan counts as additional nodes.)

(I do have a version of your XSL that works without any "/" template, BTW.)

I have modified your “/” template by adding a “prm” parameter to it and passing this parameter to “apply-templates”. Please find attached “TestDocTemplatePrm.xsl”. Now it works! The parameter is being passed in all three engines including Xalan 2.7.2:

<OutputRoot xmlns:exslt="http://exslt.org/common"; xmlns:str="http://exslt.org/strings";>

  <first>foo</first>

 <emitted>foo</emitted>

 <Output>

   <Display>foo</Display>

   <Usage></Usage>

   <Display>foo</Display>

 </Output>

 <emitted>foo</emitted>

 <last>foo</last>

</OutputRoot>

So indeed the result-tree-fragment is being processed starting with an imaginary “document element”, and if I supply a suitable template which passes the parameter through, it is being passed to the next “Created” template I actually need.

Then I uncommented the “key” stuff and finally got working what I initially needed. I had to make another modification. Apparently at some stage of these nested templates the context is lost and the “key” function can’t find the required key. To restore the context, I have added a DOCUMENT_ROOT variable and wrapped the “key” invocation inside a “for-each”. Also I modified the key and the source XML file so that it could find something meaningful. And it finally worked! Please find attached “TestEverythingWorks.xml” and “TestEverythingWorks.xsl”. Xalan 2.7.2 and Saxon give the correct result:

<OutputRoot xmlns:exslt="http://exslt.org/common"; xmlns:str="http://exslt.org/strings";>

  <first>foo</first>

 <emitted>foo</emitted>

 <Output>

   <Display>foo</Display>

   <Usage>bar</Usage>

   <Display>foo</Display>

 </Output>

 <emitted>foo</emitted>

 <last>foo</last>

</OutputRoot>

The element is being found in the key and from it the value “bar” is being read. Hooray!

I still don’t know why so many twists are required to pass the parameter. Is it correct anyway? Probably it’s all towards the stringent implementation of the XSLT standard. In the JDK-Xalan the parameter was being passed even in the absence of the “/” template, probably that was a bug which has been fixed since then. On the other hand, the JDK-Xalan was losing the parameter which was an obvious bug; now I see that it has been fixed in Xalan 2.7.2. Thank you!

*Sergey Bederov
*Senior Developer
*Cortona3D**
*www.cortona3D.com <http://www.cortona3d.com/>

*From:*Eric J. Schwarzenbach [mailto:[email protected]]
*Sent:* Saturday, March 11, 2023 11:28 PM
*To:* Bederov, Sergey <[email protected]>
*Cc:* [email protected]
*Subject:* Re: Xalan bug: key( ) clears variable

The issue tracker is here: https://issues.apache.org/jira/projects/XALANJ/issues/XALANJ-2357?filter=allopenissues

However, I'm seeing even more weirdness with this xsl. It seems I can make it work by making changes that have no reason to make a difference. I'd made a number of changes to my copy of your xsl, to try to make it work, and to test that certain things were working property and were not the cause of the problem. I started to clean that up in case it might be useful for the bug submission. But some change I made caused the variable to be passed and make <Display>foo</Display> appear in the output. Trying to backtrack I  saw the problem come and go unexpectedly.

I isolated one change that causes the problem to go away. My attached testOK.xsl works properly. testNotOK.xsl exhibits the problem. The only difference is testNotOK.xsl having a "/" template (which was not even in your version and should not be having any effect). I've also gotten other changes that should be unrelated to cause the problem to come and go. It is as if various changes "stir the pot" and activate or deactivate the problem. I realize this makes no sense and makes me sound like a crazy person, but I urge you to try my two attached versions of the stylesheet.

I suspect that issue you had with the key usage using the JDK version was this same "stir the pot" issue and nothing particularly to do with keys, and it probably behaves the same way in both xalan and the JDK version of it.

Reply via email to