You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@xalan.apache.org by Adam Jenkins <ad...@yahoo.com.au> on 2009/11/13 07:53:57 UTC

Advanced Extension Element Question

Hi All,

I'm just wondering if there is a way to place a java object (not a tree fragment) into the context output results from an extension element, and have it stay as an object (and not have it turned into a Document node).

Here is the exact use case.  I have a custom extension that creates an object that is used later on throughout my xslt.  The use case I want is:

<xsl:variable name="somevarname">
   <custom:myobject>
      <custom:property name="blah" value="blah"/>
   </custom:myobject>
</xsl:variable>

The function myObject(XSLProcessorContext, ElemExtensionCall) on the object mapped to the prefix 'custom' creates a java object, and places it to the output tree thus:

context.outputToResultTree(context.getStylesheet(), myCreatedObject);

Now, when I try to reference that later, it's been turned into a text node on a Document object whos value is the value of the toString() method for 'myCreatedObject'.  So I think I'm using the wrong method here...and that perhaps there's a better method other than outputToResultTree??

So I'm guessing xalan <xsl:variable...> tag is creating a document fragment from my object as best it can.

So my question is...is there anyway, to pass myCreatedObject up to the previous <xsl:variable...> declaration without it being toStringed (another method somewhere).

My fallback is to declare a varName attribute on all my custom extension and put the object on the local variable stack myself, but that's a pain and looks ugly, I'd prefer to do it using xsl:variable.

This is for an open source (large) xalan extension library to be releases asap.

Cheers
Adam


      __________________________________________________________________________________
Win 1 of 4 Sony home entertainment packs thanks to Yahoo!7.
Enter now: http://au.docs.yahoo.com/homepageset/

---------------------------------------------------------------------
To unsubscribe, e-mail: xalan-dev-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-dev-help@xml.apache.org


Re: Advanced Extension Element Question

Posted by Martin von Gagern <Ma...@gmx.net>.
keshlam@us.ibm.com wrote:
> Conceptually the changes would all be local to xsl:variable. But  I find
> myself nervous about whether and how they would propagate through the
> rest of the system -- whether we might wind up relaxing typechecking
> elsewhere and losing some of the strength of error detection.

Allowing references to arbitrary objects to be stored in variables is a
powerful thing indeed. Should be possible even now through the use of
extension functions instead of extension elkements. There are some
issues though, e.g. https://issues.apache.org/jira/browse/XALANJ-1847

Greetings,
 Martin von Gagern


Re: Advanced Extension Element Question

Posted by ke...@us.ibm.com.
> Is it that big an ask to be able to set a variable from an extension 
element?

Specifically, to set a variable to something other than XPath-compatable 
data, since of course the syntax you show already works for result tree 
fragments... 

... I'm really not sure. Probably worth drafting a prototype to see just 
how much it affects.  Don't forget to consider both compiled and 
interpreted modes, and to make sure it's not going to adversely affect 
performance when the new feature is not in use.

Conceptually the changes would all be local to xsl:variable. But  I find 
myself nervous about whether and how they would propagate through the rest 
of the system -- whether we might wind up relaxing typechecking elsewhere 
and losing some of the strength of error detection.

Personally, I'm always nervous about extensions generally, given their 
inherent nonportability and the debugging hassles they can entail. With 
the exception of the EXSLT set -- much of which was folded into XSLT 2.0, 
and all of which was designed to be fairly cleanly 
isolatable/reimplementable -- I've seen them misused more often than I've 
seen them used well. If I were in your shoes, I would be thinking more in 
terms of creating a separate preprocessing stage (possibly taking 
advantage of Xalan's XPath support) than embedding the new language into 
the XSLT stylesheet; that would be a much more robust solution.

______________________________________
"... Three things see no end: A loop with exit code done wrong,
A semaphore untested, And the change that comes along. ..."
  -- "Threes" Rev 1.1 - Duane Elms / Leslie Fish (
http://www.ovff.org/pegasus/songs/threes-rev-11.html)

Re: Advanced Extension Element Question

Posted by Adam Jenkins <ad...@yahoo.com.au>.
nope, they can't...trust me :)

It's a very advanced extension library with significant nested structure...to represent it as a sequence of nested function calls would be too complex and difficult to read/maintain...if it could be done at all.

The example I gave was an extremely simple use case to get across what I want to do, rather than get bogged down in the particulars of each use case.  I understand the use of functions, my extension library has a whole bunch of extension functions (I think it's up to about 30)...but also has about 40 extension elements for structures that are just too complex to be represented as extension functions.  Some of these extension elements have return values that don't suit being turned into a node set.

Is it that big an ask to be able to set a variable from an extension element?  The patch submitted doesn't seem overly complex or have any impact on any other part of Xalan???

--- On Mon, 16/11/09, keshlam@us.ibm.com <ke...@us.ibm.com> wrote:

> From: keshlam@us.ibm.com <ke...@us.ibm.com>
> Subject: Re: Advanced Extension Element Question
> To: xalan-dev@xml.apache.org
> Received: Monday, 16 November, 2009, 3:43 PM
> I'm
> still not sure I understand why you
> feel you have to express this as extension elements, when
> extension functions
> can already do what you (appear to) need? 
> 
> 
> 
> ______________________________________
> 
> "... Three things see no end: A loop with exit code
> done wrong,
> 
> A semaphore untested, And the change that comes along.
> ..."
> 
>   -- "Threes" Rev 1.1 - Duane Elms / Leslie
> Fish (http://www.ovff.org/pegasus/songs/threes-rev-11.html)


      __________________________________________________________________________________
Win 1 of 4 Sony home entertainment packs thanks to Yahoo!7.
Enter now: http://au.docs.yahoo.com/homepageset/

---------------------------------------------------------------------
To unsubscribe, e-mail: xalan-dev-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-dev-help@xml.apache.org


Re: Advanced Extension Element Question

Posted by ke...@us.ibm.com.
I'm still not sure I understand why you feel you have to express this as 
extension elements, when extension functions can already do what you 
(appear to) need? 

______________________________________
"... Three things see no end: A loop with exit code done wrong,
A semaphore untested, And the change that comes along. ..."
  -- "Threes" Rev 1.1 - Duane Elms / Leslie Fish (
http://www.ovff.org/pegasus/songs/threes-rev-11.html)

Re: Advanced Extension Element Question

Posted by Adam Jenkins <ad...@yahoo.com.au>.
damn it...every single avenue I go down for adding a variable value from an extension element is a dead end (and I'm pullin' some crazy hacks at this stage).

this seems like a pretty big deficiency in the extension element framework...I have an open source library that does some pretty cool stuff scheduled for release, however the only limitation is that for two of the new elements, I can't add variables to the stack from an extension element.

Is there anyway we can get this into the next release of Xalan, I'm happy to code it up myself and submit a patch if someone can give architectural guidance?

My perfect world scenario would be for something like this:

<xsl:variable name="somename">
   <my:extensionElement someattr="value"/>
</xsl:variable>

And have the method of the extension element somehow supply an XObject back to the parent.

This may be a simple as adding a method to the ElemVariable class that is something like setChildDrivenSelect(XPath p) and modify the getValue() method so that if that method is called during child evaluation, it returns the evaluation of the supplied XPath rather than returning the XRTreeFrag from the child.

That way if we wanted to do this functionality we could code our extension elements thus:

public void extensionElement(XSLProcessorContext ctx, ElemExtensionCall elem){
   Object myValue = ...do some stuff...
   ElemVariable varElement = (ElemVariable)elem.getParent();
   varElement.setChildDrivenSelect(new XPath(new XObject(myValue)));
}

How does everyone feel about that change?  It's quick, easy and offers some pretty spectacular functionality for very little modification.  We'd just have to replace the line in ElemVariable.getValue() 

var = new XRTreeFrag(df, xctxt, this);

with

if(childPopulatedXPath == null) var = new XRTreeFrag(df, xctxt, this);
else var = childPopulatedXPath.execute(xctxt, sourceNode, this);

Thoughts/Comments?

Doing this allows for some pretty cool extension elements to be built which would really take Xalan to another level.

Cheers
Adam
--- On Sat, 14/11/09, keshlam@us.ibm.com <ke...@us.ibm.com> wrote:

> From: keshlam@us.ibm.com <ke...@us.ibm.com>
> Subject: Re: Advanced Extension Element Question
> To: 
> Cc: xalan-dev@xml.apache.org, xalan-j-users@xml.apache.org
> Received: Saturday, 14 November, 2009, 8:29 AM
> > Can anyone tell me
> if there's any way to add an
> object (not node or 
> 
> > tree fragment) variable to the variable stack from an
> extension element?
> 
> 
> 
> From an extension _element_... I
> don't think so.
> 
> 
> 
> 
> 
> From an extension _function_, yes. If
> the returned
> value is not an instanceof one of the types called out in
> the mapping table
> (http://xml.apache.org/xalan-j/extensions.html#ext-functions),
> it will be returned as an object reference. Generally you
> can't do much
> with those except store them in variables and/or pass them
> as parameters
> to other extensions.
> 
> 
> 
> If your returned value *is* an
> instanceof one of those
> types... The best suggestion I can give you is to set up a
> wrapper object
> which does not implement those types, return the wrapper,
> and have whoever
> is using the value unwrap it again before accessing
> it.


      __________________________________________________________________________________
Win 1 of 4 Sony home entertainment packs thanks to Yahoo!7.
Enter now: http://au.docs.yahoo.com/homepageset/

---------------------------------------------------------------------
To unsubscribe, e-mail: xalan-dev-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-dev-help@xml.apache.org


Re: Advanced Extension Element Question

Posted by ke...@us.ibm.com.
> Can anyone tell me if there's any way to add an object (not node or 
> tree fragment) variable to the variable stack from an extension element?

>From an extension _element_... I don't think so.


>From an extension _function_, yes. If the returned value is not an 
instanceof one of the types called out in the mapping table (
http://xml.apache.org/xalan-j/extensions.html#ext-functions), it will be 
returned as an object reference. Generally you can't do much with those 
except store them in variables and/or pass them as parameters to other 
extensions.

If your returned value *is* an instanceof one of those types... The best 
suggestion I can give you is to set up a wrapper object which does not 
implement those types, return the wrapper, and have whoever is using the 
value unwrap it again before accessing it.

Re: Advanced Extension Element Question

Posted by ke...@us.ibm.com.
> Can anyone tell me if there's any way to add an object (not node or 
> tree fragment) variable to the variable stack from an extension element?

>From an extension _element_... I don't think so.


>From an extension _function_, yes. If the returned value is not an 
instanceof one of the types called out in the mapping table (
http://xml.apache.org/xalan-j/extensions.html#ext-functions), it will be 
returned as an object reference. Generally you can't do much with those 
except store them in variables and/or pass them as parameters to other 
extensions.

If your returned value *is* an instanceof one of those types... The best 
suggestion I can give you is to set up a wrapper object which does not 
implement those types, return the wrapper, and have whoever is using the 
value unwrap it again before accessing it.

Re: Advanced Extension Element Question

Posted by Adam Jenkins <ad...@yahoo.com.au>.
Can anyone tell me if there's any way to add an object (not node or tree fragment) variable to the variable stack from an extension element?

I originally tried to use context.outputToResultTree(context.getStylesheet(), myCreatedObject) an put my extension element inside an <xsl:variable...>, however that turns my java object into a text node on a Document first (the text node has the value of the toString() from my object) rather than passing myCreatedObject to the ElemVariable element as a java object.

I'm now looking into doing a similar thing as in ElemVariable.java and adding the object to the stack directly from within my extension element method, from what I can see, this should work:

StylesheetRoot root = xslProcessorContext.getStylesheet().getStylesheetRoot();
StylesheetRoot.ComposeState cstate = sroot.getComposeState();
QName name = new QName(name);
XObject obj = new XObject(myCreatedObject);
int index = cstate.addVariableName(name) - cstate.getGlobalsSize();
xslProcessorContext.getTransformer().getXPathContext().getVarStack().setLocalVariable(index, obj);

Now this is similar to what ElemVariable.java does, however StylesheetRoot.ComposeState is package scoped!, so I can't use the above code either :(

If anyone knows of a way to put a java object variable onto the variable stack (as an XObject, not a XRTreeFrag) under a given name from within an extension element method I'd really appreciate any pointers you could give.

My goals is placing an object into the local variable stack under a given name so that I can reference it, for example in an <xsl:value-of select="java:someMethod($myPreviouslyAddedObject)"/>

--- On Fri, 13/11/09, Adam Jenkins <ad...@yahoo.com.au> wrote:

> From: Adam Jenkins <ad...@yahoo.com.au>
> Subject: Advanced Extension Element Question
> To: xalan-j-users@xml.apache.org, xalan-dev@xml.apache.org
> Received: Friday, 13 November, 2009, 5:53 PM
> Hi All,
> 
> I'm just wondering if there is a way to place a java object
> (not a tree fragment) into the context output results from
> an extension element, and have it stay as an object (and not
> have it turned into a Document node).
> 
> Here is the exact use case.  I have a custom extension
> that creates an object that is used later on throughout my
> xslt.  The use case I want is:
> 
> <xsl:variable name="somevarname">
>    <custom:myobject>
>       <custom:property name="blah"
> value="blah"/>
>    </custom:myobject>
> </xsl:variable>
> 
> The function myObject(XSLProcessorContext,
> ElemExtensionCall) on the object mapped to the prefix
> 'custom' creates a java object, and places it to the output
> tree thus:
> 
> context.outputToResultTree(context.getStylesheet(),
> myCreatedObject);
> 
> Now, when I try to reference that later, it's been turned
> into a text node on a Document object whos value is the
> value of the toString() method for 'myCreatedObject'. 
> So I think I'm using the wrong method here...and that
> perhaps there's a better method other than
> outputToResultTree??
> 
> So I'm guessing xalan <xsl:variable...> tag is
> creating a document fragment from my object as best it can.
> 
> So my question is...is there anyway, to pass
> myCreatedObject up to the previous <xsl:variable...>
> declaration without it being toStringed (another method
> somewhere).
> 
> My fallback is to declare a varName attribute on all my
> custom extension and put the object on the local variable
> stack myself, but that's a pain and looks ugly, I'd prefer
> to do it using xsl:variable.
> 
> This is for an open source (large) xalan extension library
> to be releases asap.
> 
> Cheers
> Adam
> 
> 
>      
> __________________________________________________________________________________
> Win 1 of 4 Sony home entertainment packs thanks to
> Yahoo!7.
> Enter now: http://au.docs.yahoo.com/homepageset/
> 


      __________________________________________________________________________________
Win 1 of 4 Sony home entertainment packs thanks to Yahoo!7.
Enter now: http://au.docs.yahoo.com/homepageset/

---------------------------------------------------------------------
To unsubscribe, e-mail: xalan-dev-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-dev-help@xml.apache.org


Re: Advanced Extension Element Question

Posted by Adam Jenkins <ad...@yahoo.com.au>.
Can anyone tell me if there's any way to add an object (not node or tree fragment) variable to the variable stack from an extension element?

I originally tried to use context.outputToResultTree(context.getStylesheet(), myCreatedObject) an put my extension element inside an <xsl:variable...>, however that turns my java object into a text node on a Document first (the text node has the value of the toString() from my object) rather than passing myCreatedObject to the ElemVariable element as a java object.

I'm now looking into doing a similar thing as in ElemVariable.java and adding the object to the stack directly from within my extension element method, from what I can see, this should work:

StylesheetRoot root = xslProcessorContext.getStylesheet().getStylesheetRoot();
StylesheetRoot.ComposeState cstate = sroot.getComposeState();
QName name = new QName(name);
XObject obj = new XObject(myCreatedObject);
int index = cstate.addVariableName(name) - cstate.getGlobalsSize();
xslProcessorContext.getTransformer().getXPathContext().getVarStack().setLocalVariable(index, obj);

Now this is similar to what ElemVariable.java does, however StylesheetRoot.ComposeState is package scoped!, so I can't use the above code either :(

If anyone knows of a way to put a java object variable onto the variable stack (as an XObject, not a XRTreeFrag) under a given name from within an extension element method I'd really appreciate any pointers you could give.

My goals is placing an object into the local variable stack under a given name so that I can reference it, for example in an <xsl:value-of select="java:someMethod($myPreviouslyAddedObject)"/>

--- On Fri, 13/11/09, Adam Jenkins <ad...@yahoo.com.au> wrote:

> From: Adam Jenkins <ad...@yahoo.com.au>
> Subject: Advanced Extension Element Question
> To: xalan-j-users@xml.apache.org, xalan-dev@xml.apache.org
> Received: Friday, 13 November, 2009, 5:53 PM
> Hi All,
> 
> I'm just wondering if there is a way to place a java object
> (not a tree fragment) into the context output results from
> an extension element, and have it stay as an object (and not
> have it turned into a Document node).
> 
> Here is the exact use case.  I have a custom extension
> that creates an object that is used later on throughout my
> xslt.  The use case I want is:
> 
> <xsl:variable name="somevarname">
>    <custom:myobject>
>       <custom:property name="blah"
> value="blah"/>
>    </custom:myobject>
> </xsl:variable>
> 
> The function myObject(XSLProcessorContext,
> ElemExtensionCall) on the object mapped to the prefix
> 'custom' creates a java object, and places it to the output
> tree thus:
> 
> context.outputToResultTree(context.getStylesheet(),
> myCreatedObject);
> 
> Now, when I try to reference that later, it's been turned
> into a text node on a Document object whos value is the
> value of the toString() method for 'myCreatedObject'. 
> So I think I'm using the wrong method here...and that
> perhaps there's a better method other than
> outputToResultTree??
> 
> So I'm guessing xalan <xsl:variable...> tag is
> creating a document fragment from my object as best it can.
> 
> So my question is...is there anyway, to pass
> myCreatedObject up to the previous <xsl:variable...>
> declaration without it being toStringed (another method
> somewhere).
> 
> My fallback is to declare a varName attribute on all my
> custom extension and put the object on the local variable
> stack myself, but that's a pain and looks ugly, I'd prefer
> to do it using xsl:variable.
> 
> This is for an open source (large) xalan extension library
> to be releases asap.
> 
> Cheers
> Adam
> 
> 
>      
> __________________________________________________________________________________
> Win 1 of 4 Sony home entertainment packs thanks to
> Yahoo!7.
> Enter now: http://au.docs.yahoo.com/homepageset/
> 


      __________________________________________________________________________________
Win 1 of 4 Sony home entertainment packs thanks to Yahoo!7.
Enter now: http://au.docs.yahoo.com/homepageset/