You are viewing a plain text version of this content. The canonical link for it is here.
Posted to j-users@xalan.apache.org by bp...@sneakemail.com on 2006/01/06 18:58:00 UTC
Xalan ignores DocumentFragment returned by extension function
Hello,
I'm currently working on an extension class for use in an XSL file.
The transformation I want to perform is the following:
Input fragment:
<floatlist>0 1 2 3 4 5 6 7 8</floatlist>
Output fragment:
<vec3 value="0 1 2"/>
<vec3 value="3 4 5"/>
<vec3 value="6 7 8"/>
As to my knowledge there is no way to get this working in XSLT directly
(and because for the project behind it there is some more processing
required than shown above anyway), I wrote an extension function to do
this, and invoke it with this XSL fragment:
<xsl:for-each select="floatlist">
<xsl:value-of value="ext:makevec3s(.)"/>
</xsl:for-each>
So the extension function is called for each <floatlist/> element, takes
it's contents as a string, and creates a number of <vec3/> elements in a
DocumentFragment instance.
However, although the function itself seems works fine, it appears as if
Xalan simply discards the returned DocumentFragment.
I've included the source code and XML/XSL files at the end of this email
I'd be gratetful for any clues :)
Cheers,
Uwe
---- input.xml ----
<?xml version="1.0" encoding="UTF-8"?>
<root>
<floatlist>0 1 2 3 4 5 6 7 8</floatlist>
<floatlist>9 10 11 12 13 14</floatlist>
</root>
---- exttest.xsl ----
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="xalanexttest.Ext" version="1.0">
<xsl:template match="/">
<vectors>
<xsl:for-each select="root/floatlist">
<xsl:value-of select="ext:makevec3s(.)"/>
</xsl:for-each>
</vectors>
</xsl:template>
</xsl:stylesheet>
---- Ext.java ----
package xalanexttest;
import org.w3c.dom.*;
import org.w3c.dom.bootstrap.*;
public class Ext {
static DOMImplementation domImpl;
static Document doc;
static {
try{
DOMImplementationRegistry reg =
DOMImplementationRegistry.newInstance();
domImpl = reg.getDOMImplementation("XML 1.0");
doc =
domImpl.createDocument("http://pachler.name/sibengine", "foo", null);
} catch(ClassNotFoundException ex){
} catch(InstantiationException ex){
} catch(IllegalAccessException ex){
}
}
/** Creates a new instance of Ext */
public Ext() {
}
/**
* @param args the command line arguments
*/
public static void main(String[] argv){
org.apache.xalan.xslt.Process.main(argv);
}
public DocumentFragment makevec3s(String in){
DocumentFragment dfrag = doc.createDocumentFragment();
// test float array, no need to show parsing code here
float[] floats = {0, 1, 2, 3, 4, 5, 6, 7, 8};
for(int i=2; i<floats.length; i+=3){
Element v3Element = doc.createElement("vec3");
String value = ""+floats[i-2]+' '+floats[i-1]+' '+floats[i];
v3Element.setAttribute("value", value);
dfrag.appendChild(v3Element);
}
return dfrag;
}
}
---- output.xml - the output that is produced by Xalan-J ----
<?xml version="1.0" encoding="UTF-8"?>
<vectors xmlns:ext="xalanexttest.Ext"/>
Re: Xalan ignores DocumentFragment returned by extension function
Posted by David Bertoni <db...@apache.org>.
bpezpn502@sneakemail.com wrote:
> Hello,
>
> I'm currently working on an extension class for use in an XSL file.
>
> The transformation I want to perform is the following:
>
> Input fragment:
> <floatlist>0 1 2 3 4 5 6 7 8</floatlist>
>
> Output fragment:
> <vec3 value="0 1 2"/>
> <vec3 value="3 4 5"/>
> <vec3 value="6 7 8"/>
>
> As to my knowledge there is no way to get this working in XSLT directly
> (and because for the project behind it there is some more processing
> required than shown above anyway), I wrote an extension function to do
> this, and invoke it with this XSL fragment:
>
> <xsl:for-each select="floatlist">
> <xsl:value-of value="ext:makevec3s(.)"/>
> </xsl:for-each>
>
First, you need to understand what xsl:value-of does:
http://www.w3.org/TR/xslt#value-of
"The xsl:value-of element is instantiated to create a text node in the
result tree. The required select attribute is an expression; this
expression is evaluated and the resulting object is converted to a
string as if by a call to the string function."
Next, the string function:
http://www.w3.org/TR/xpath#section-String-Functions
"A node-set is converted to a string by returning the string-value of
the node in the node-set that is first in document order. If the
node-set is empty, an empty string is returned."
Next, the string-value of a root node:
http://www.w3.org/TR/xpath#root-node
"The string-value of the root node is the concatenation of the
string-values of all text node descendants of the root node in document
order."
Since your extension function doesn't create any text nodes, the
string-value of the document fragment is an empty string.
However, looking at your expected output, you probably want to use
xsl:copy-of, since you want to copy the structure of the document
fragment to the result tree.
...
> public DocumentFragment makevec3s(String in){
> DocumentFragment dfrag = doc.createDocumentFragment();
> // test float array, no need to show parsing code here
> float[] floats = {0, 1, 2, 3, 4, 5, 6, 7, 8};
> for(int i=2; i<floats.length; i+=3){
> Element v3Element = doc.createElement("vec3");
You should be creating a namespace-aware DOM, by using createElementNS()
and setAttributeNS().
Dave
Re: Xalan ignores DocumentFragment returned by extension function
Posted by Henry Zongaro <zo...@ca.ibm.com>.
Henry Zongaro/Toronto/IBM@IBMCA wrote on 2006-01-06 02:03:25 PM:
> I think you really want something like this, which worked for me:
>
> <xsl:for-each select="ext:makevec3s(.)/vec3">
> <xsl:value-of select="@value"/>
> </xsl:for-each>
Whoops! I was thinking you were only interested in the string values
returned in the attributes. Of course xsl:copy-of is the right
instruction to use instead of xsl:value-of, as David Marston and Dave
Bertoni have already pointed out.
Thanks,
Henry
------------------------------------------------------------------
Henry Zongaro Xalan development
IBM SWS Toronto Lab T/L 969-6044; Phone +1 905 413-6044
mailto:zongaro@ca.ibm.com
Re: Xalan ignores DocumentFragment returned by extension function
Posted by Henry Zongaro <zo...@ca.ibm.com>.
Hi, Uwe.
bpezpn502@sneakemail.com wrote on 2006-01-06 12:58:00 PM:
> Input fragment:
> <floatlist>0 1 2 3 4 5 6 7 8</floatlist>
>
> Output fragment:
> <vec3 value="0 1 2"/>
> <vec3 value="3 4 5"/>
> <vec3 value="6 7 8"/>
>
> As to my knowledge there is no way to get this working in XSLT directly
It might be slightly complicated, but not impossible - but who knows with
the additional processing you mention below.
> (and because for the project behind it there is some more processing
> required than shown above anyway), I wrote an extension function to do
> this, and invoke it with this XSL fragment:
>
> <xsl:for-each select="floatlist">
> <xsl:value-of value="ext:makevec3s(.)"/>
> </xsl:for-each>
The xsl:value-of will print the string value of the first node in the node
set returned by ext:makevec3s(.), which is an empty string in this case. I
think you really want something like this, which worked for me:
<xsl:for-each select="ext:makevec3s(.)/vec3">
<xsl:value-of select="@value"/>
</xsl:for-each>
Thanks,
Henry
------------------------------------------------------------------
Henry Zongaro Xalan development
IBM SWS Toronto Lab T/L 969-6044; Phone +1 905 413-6044
mailto:zongaro@ca.ibm.com
Re: Xalan ignores DocumentFragment returned by extension function
Posted by da...@us.ibm.com.
Uwe wrote:
>Output fragment:
><vec3 value="0 1 2"/>
>
>...I wrote an extension function to do
>this, and invoke it with this XSL fragment:
><xsl:value-of value="ext:makevec3s(.)"/>
>...So the extension function...
>creates a number of <vec3/> elements...
The first step is to try xsl:copy-of instead of value-of.
Value-of is designed to emit a text node. Copy-of will emit
a whole sequence of nodes with attributes and children.
.................David Marston