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 Christoffer Dam Bruun <cd...@flyingpigs.dk> on 2009/06/24 10:29:00 UTC
Howto implement a node index extension to be shared across transform
invocations on the same source document (DOMSource)
Hi,
I have a webapplication where I hold a large XML tree in memory. On
this tree
I perform several transforms as response to user requests.
Each transform declares a <xsl:key> that serves as an index for
important nodes in the tree.
However, it is expensive to calculate this key and it should be possible
to reuse it since I know that the source tree has not been modified.
Since modifying the Xalan <xsl:key> implementation is difficult, I tried
my luck with a
Java extension approach where I simply store selected nodes in a
HashMap outside
the transform.
However, when I return a node from the extension then Xalan goes boom!
if the node
was added in a previous transform.
Does anyone know how to make this work ?
Best regards
Christoffer Dam Bruun
// The Java extension
public class ElementIndex {
public static Map<String, SingleIndex> indexes = new HashMap<String,
SingleIndex>();
public static Node key(String indexId, String key) {
NodeSet ns = new NodeSet();
SingleIndex idx = indexes.get(indexId);
if (null == idx) {
System.err.println("idx er null");
}
List<Node> nl = idx.get(key);
if (null == nl) {
return null;
}
return nl.get(0);
}
public static int add(ExpressionContext ec, String indexId, String
key, NodeList nodes) {
SingleIndex idx = indexes.get(indexId);
if (null == idx) {
idx = new SingleIndex();
indexes.put(indexId, idx);
}
for (int i = 0; i < nodes.getLength(); i++) {
Node tmp = nodes.item(i);
idx.put(key, tmp);
}
return 0;
}
public static int remove(String indexId) {
return 0;
}
public static int clear(String indexId) {
return 0;
}
public static class SingleIndex {
String idxName;
Map<String, ArrayList<Node>> idx = new HashMap<String,
ArrayList<Node>>();
public List<Node> get(String key) {
return idx.get(key);
}
public void put(String key, Node n) {
List<Node> nl = idx.get(key);
if (null == nl) {
nl = new ArrayList<Node>();
idx.put(key, (ArrayList<Node>) nl);
}
nl.add(n);
}
public void remove(String key, Node n) {
List<Node> nl = idx.get(key);
if (null == nl) {
return;
}
nl.remove(n);
}
}
}
// Adding to the index:
<xsl:value-of select="idx:add('nidkey', @nid,current())"/>
// Getting nodes from the index
<xsl:variable name="task" select="idx:key('nidkey',@nid)"></xsl:variable>
Re: Howto implement a node index extension to be shared across transform
invocations on the same source document (DOMSource)
Posted by Michael Ludwig <ml...@as-guides.com>.
Christoffer Dam Bruun schrieb:
> Michael Ludwig skrev:
>> Could XSLTC (which I don't have any experience with yet) be used to
>> make the <xsl:key> persist? Hmm, maybe the <xsl:key> would persist -
>> but that probably would still require its execution on a document
>> instance.
> I don't think XSLTC would make any difference since the XSLT processor
> cannot know that the XML document has not been modified since the key
> was last calculated- only I as the programmer knows that.
I see, you'd need the lookup table resulting from applyint the <xsl:key>
on the document, and that doesn't seem to be available.
>> Could you use the ID feature built into XML to achieve what you want?
> I have looked at it - the problem is that I also use an one-to-many
> reverse-id lookup e.g.:
> "All elements that refer to the element with this @id"
> and I don't think I can cram that into the builtin ID feature.
Can't think of a way to achieve that either. Sounds like you really need
<xsl:key>.
I've never used this, but if all else fails, you might want to take a
look at VTD-XML:
http://vtd-xml.sourceforge.net/
Michael Ludwig
Re: Howto implement a node index extension to be shared across transform
invocations on the same source document (DOMSource)
Posted by Christoffer Dam Bruun <cd...@flyingpigs.dk>.
Michael Ludwig skrev:
> Christoffer Dam Bruun schrieb:
>
>> I have a webapplication where I hold a large XML tree in memory. On
>> ...
>
> Could XSLTC (which I don't have any experience with yet) be used to make
> the <xsl:key> persist? Hmm, maybe the <xsl:key> would persist - but that
> probably would still require its execution on a document instance.
I don't think XSLTC would make any difference since the XSLT processor
cannot know that the
XML document has not been modified since the key was last calculated-
only I as the programmer knows that.
>
> Could you use the ID feature built into XML to achieve what you want?
I have looked at it - the problem is that I also use an one-to-many
reverse-id lookup e.g.:
"All elements that refer to the element with this @id"
and I don't think I can cram that into the builtin ID feature.
Christoffer Bruun
Re: Howto implement a node index extension to be shared across transform
invocations on the same source document (DOMSource)
Posted by Michael Ludwig <ml...@as-guides.com>.
Christoffer Dam Bruun schrieb:
> I have a webapplication where I hold a large XML tree in memory. On
> this tree I perform several transforms as response to user requests.
> Each transform declares a <xsl:key> that serves as an index for
> important nodes in the tree.
>
> However, it is expensive to calculate this key and it should be
> possible to reuse it since I know that the source tree has not been
> modified.
Could XSLTC (which I don't have any experience with yet) be used to make
the <xsl:key> persist? Hmm, maybe the <xsl:key> would persist - but that
probably would still require its execution on a document instance.
Could you use the ID feature built into XML to achieve what you want?
<!ATTLIST elm id ID #IMPLIED>
Wouldn't that persist between invocations?
That would make for efficient lookup; however, it would constrain the
values of elm/@id to what's valid for an ID type attribute.
Also, see the following thread related to an XSLT feature related to
ID-typed attributes:
Xalan-J 2.7.1: document() function disregards URI fragment identifier
http://markmail.org/thread/ept5ifkshhjoagf3
Lots of "could" and "would" here. One more: It would be great to get
input from the experts on this one.
Michael Ludwig