Project

Profile

Help

value translation using saxon:evaluate?

Added by Anonymous about 16 years ago

Legacy ID: #5292907 Legacy Poster: David (pagod)

Hi, i'm working with documents containing tags whose name might change (e.g. depending on the language), but the documents always contain a translation table allowing to refer to the "canonical" names of the tags, which never change. so for instance, i have the following two documents: <?xml version="1.0" encoding="UTF-8"?> <doc> <trans> <tag name="a"> <real name="aa"/> </tag> </trans> <chapter name="a"> foo </chapter> </doc> <?xml version="1.0" encoding="UTF-8"?> <doc> <trans> <tag name="b"> <real name="aa"/> </tag> </trans> <chapter name="b"> bar </chapter> </doc> in order to get the content of an 'aa' <chapter>, i need to use not its @name, but the value of the /doc/trans/tag/real/@name corresponding to it (so in the first document that would be /doc/trans/tag[name='a']/real/@name, and in the second document that would be /doc/trans/tag[name='b']/real/@name) i tried the following: <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:saxon="http://saxon.sf.net/" version="2.0"> <xsl:output method="xml"/> <xsl:variable name="path"><xsl:text>/doc/trans/tag[@name=&apos;a&apos;]/real/@name</xsl:text></xsl:variable> <xsl:template match="/"> <xsl:apply-templates/> </xsl:template> <xsl:template match="trans" /> <xsl:template match="chapter[saxon:evaluate($path)='aa']"> <hello>world</hello> </xsl:template> </xsl:stylesheet> that works fine, but of course (and that's the reason why i'm using a variable here) i'd like to make this dynamic so the test works for both documents. i read that saxon:evaluate can take more parameters and use them in the expression provided as the first parameter, but be it because i misunderstood that or any other reason, it doesn't seem to work. i tried this: <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:saxon="http://saxon.sf.net/" version="2.0"> <xsl:output method="xml"/> <xsl:variable name="path"><xsl:text>/doc/trans/tag[@name=&apos;$p1&apos;]/real/@name</xsl:text></xsl:variable> <xsl:template match="/"> <xsl:apply-templates/> </xsl:template> <xsl:template match="trans" /> <xsl:template match="chapter[saxon:evaluate($path,@name)='aa']"> <hello>world</hello> </xsl:template> </xsl:stylesheet> which makes use of parameter $p1 in the base expression, and takes the @name attribute as parameter in the function call, but it doesn't seem to work at all. could perhaps anyone tell me what i'm doing wrong here, or how i should use saxon:evaluate to achieve my goal (or perhaps is saxon:evaluate not the right choice at all??)? thx a lot! David


Replies (7)

Please register to reply

RE: value translation using saxon:evaluate? - Added by Anonymous about 16 years ago

Legacy ID: #5292995 Legacy Poster: David (pagod)

actually, there's also another reason i'm using a variable: i need to use this "translation" several times during the XSLT transformation, and i'd like to centralize the declaration of the path in case i need to change it in the future. i also tried to create the path dynamically by using a placeholder in the global variable and replacing it at runtime with the proper value (and then use saxon:evaluate() with the result), but replace() fails if the path (in my example, the @name attribute) is not present ("An empty sequence is not allowed as the third argument of replace()). of course i can test for availability before applying my function, but that makes the code really hard to read and heavy, and i'd like to avoid that. D.

RE: value translation using saxon:evaluate? - Added by Anonymous about 16 years ago

Legacy ID: #5293017 Legacy Poster: Michael Kay (mhkay)

Generally I advise using xsl-list at mulberrytech for coding advice, and this list for things that are specific to the Saxon product - but because you're asking about saxon:evaluate, this one is borderline. I don't think you need saxon:evaluate here - and using it in a predicate of a match pattern is certainly going to be very expensive. I think you just want <xsl:template match="chapter[/doc/trans/tag[@name=current()/@name]/real/@name='aa']"> or perhaps better <xsl:key name="k" match="/doc/trans/tag" use="@name"/> <xsl:template match="chapter[key('k', @name)/real/@name = 'aa]"> But.... In general I think a better design approach when you are dealing with input documents that exhibit variety of structure is to use a pipeline approach in which you first transform the document into a "normal form", and then do the transformation proper. That would seem to apply in this case. The pipeline design pattern simplifies your code and makes it more robust and reusable; it also makes it easier to add new "varieties" as time goes on. Michael Kay

RE: value translation using saxon:evaluate? - Added by Anonymous about 16 years ago

Legacy ID: #5293018 Legacy Poster: David (pagod)

i also tried this as the value for the variable: /doc/trans/tag[@name=current()/@name]/real/@name this works great when called directly from the code, but calling saxon:evaluate on this "path" crashes the whole saxon, with the following exception: "Exception in thread "main" java.lang.AssertionError: current() function should have been rewritten at compile time" i guess the current context is not available when evaluate()'ing the path?.. D.

RE: value translation using saxon:evaluate? - Added by Anonymous about 16 years ago

Legacy ID: #5293038 Legacy Poster: David (pagod)

Hi Michael, thanks a lot for the answer. i also hesitated between this list and mulberrytech's, but seeing as i was using this saxon:evaluate function... also tried that with the current()/@name -- see my previous comments. it would be a good choice if i could use it as a variable, so it doesn't lie around everywhere in the xslt code, but apparently it doesn't work. i wasn't aware of the xsl:key construct. i'm gonna try to use that, it sounds like a good solution :-) pipelining might also be a good solution, but unfortunately it's not my decision to make. i'll mention that possibility (and say you recommended it), and see how my boss likes it ;-).

RE: value translation using saxon:evaluate? - Added by Anonymous about 16 years ago

Legacy ID: #5293087 Legacy Poster: Michael Kay (mhkay)

current() is an XSLT addition to the XPath function library, so it's not available in standalone XPath expresions and therefore not in saxon:evaluate(). But it shouldn't have crashed like that, of course - I think it's in two minds about whether it's in an XSLT context or not.

RE: value translation using saxon:evaluate? - Added by Anonymous about 16 years ago

Legacy ID: #5298552 Legacy Poster: Michael Kay (mhkay)

In fact, the spec for saxon:evaluate() says that the static context (including the set of functions available for calling) is the same as that of the calling expression, and the code internally attempts to work this way. So current() should be available. I've raised a bug and a patch to make it work. (This leaves the question of what current() does when called within saxon:evaluate(). I fixed it so it returns the item that is the context item at the point where saxon:evaluate() is called.)

RE: value translation using saxon:evaluate? - Added by Anonymous about 16 years ago

Legacy ID: #5298637 Legacy Poster: Michael Kay (mhkay)

I'm wrong about what the spec says; I've just found where it says that use of XSLT-specific functions like format-number() isn't allowed, and current() falls into this category. What's actually happening is that the parser recognizes the function name, but in many cases execution fails because of dependencies on the XSLT-specific context, e.g. decimal format names. Anyway, current() is now supported and working, and there's a TODO to validate the others and get them working if possible.

    (1-7/7)

    Please register to reply