Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » M2T (model-to-text transformation) » Use of JET setVariable to store commonly used XPath expressions
Use of JET setVariable to store commonly used XPath expressions [message #53855] Sat, 13 December 2008 07:49 Go to next message
Mark Wood is currently offline Mark Wood
Messages: 8
Registered: July 2009
Junior Member
Hello,

This post is a sort of follow on from:

http://dev.eclipse.org/newslists/news.eclipse.modeling.m2t/m sg00706.html

In my current project using JET I am finding that I use the same
expressions over and over again throughout numerous files. Some of these
expressions are quite long. In order to increase maintainability of my
templates, I require a way to store an XPath expression as a global
variable. Clearly, c:setVariable is what I need. However, I'm running into
a couple of issues...

In my main.jet file, I would like to declare the following variable:

<c:setVariable var="allEntityAttributes"
select=" //namedElements[self::Entity][@name='{$entityName}']/feature s[self::Attribute] "
/>

The issues are as follows:

- The select expression is evaluated as an XPath expression because of the
nature of setVariable, however I just want to store the actual string it
represents.

Adding spaces in this way:
select="
//namedElements[self::Entity][@name='{$entityName}']/feature s[self::Attribute]
"

could work, however, this expression is declared right at the top of my
main.jet. Consequently, the variable $entityName does not yet exist (it is
assigned later on when processing elements). When $entityName does not
exist, not only are errors thrown but the variable $allEntityAttributes is
not assigned any value and as a result cannot be used.

Are there any ways to achieve the functionality I require? I simply want
to store an XPath expression string (which itself includes variables) as a
variable so it can be reused many times.

Thanks,

Mark
Re: Use of JET setVariable to store commonly used XPath expressions [message #53880 is a reply to message #53855] Sun, 14 December 2008 17:34 Go to previous messageGo to next message
Eclipse User
Originally posted by: tmothymarc.freenet.de

Mark,

try it with the default string('xyz') function of the XPath 1.0 spec. I
don't know whether this works, but it might be another possibility.

Timothy

Mark Wood schrieb:
> Hello,
>
> This post is a sort of follow on from:
>
> http://dev.eclipse.org/newslists/news.eclipse.modeling.m2t/m sg00706.html
>
> In my current project using JET I am finding that I use the same
> expressions over and over again throughout numerous files. Some of these
> expressions are quite long. In order to increase maintainability of my
> templates, I require a way to store an XPath expression as a global
> variable. Clearly, c:setVariable is what I need. However, I'm running
> into a couple of issues...
>
> In my main.jet file, I would like to declare the following variable:
>
> <c:setVariable var="allEntityAttributes"
> select=" //namedElements[self::Entity][@name='{$entityName}']/feature s[self::Attribute] "
> />
>
> The issues are as follows:
>
> - The select expression is evaluated as an XPath expression because of
> the nature of setVariable, however I just want to store the actual
> string it represents.
>
> Adding spaces in this way:
> select="
> //namedElements[self::Entity][@name='{$entityName}']/feature s[self::Attribute]
> "
>
> could work, however, this expression is declared right at the top of my
> main.jet. Consequently, the variable $entityName does not yet exist (it
> is assigned later on when processing elements). When $entityName does
> not exist, not only are errors thrown but the variable
> $allEntityAttributes is not assigned any value and as a result cannot be
> used.
>
> Are there any ways to achieve the functionality I require? I simply want
> to store an XPath expression string (which itself includes variables) as
> a variable so it can be reused many times.
>
> Thanks,
>
> Mark
>
Re: Use of JET setVariable to store commonly used XPath expressions [message #53902 is a reply to message #53880] Mon, 15 December 2008 09:12 Go to previous messageGo to next message
Mark Wood is currently offline Mark Wood
Messages: 8
Registered: July 2009
Junior Member
Hi Timothy,

Thanks for getting back to me so quickly.

Unfortunately the string() function doesn't make any difference -- I get
the same results.

I think it's due to how the variable $entityName is used:

'{$entityName}'

I think maybe the presence of the curly brackets is causing the expression
to be evaluated regardless (just a guess). Obviously though if I remove
the brackets then the expression will be selecting entities which have the
name "$entityName". Clearly this is not what I want.

Any suggestions welcome.

Thanks,

Mark
Re: Use of JET setVariable to store commonly used XPath expressions [message #53923 is a reply to message #53855] Mon, 15 December 2008 10:32 Go to previous messageGo to next message
Paul Elder is currently offline Paul Elder
Messages: 849
Registered: July 2009
Senior Member
Mark:

Out of the box, JET doesn't have a way to dynamically evaluate an XPath
expression stored as a string. But, I've crafted an XPath function that can
do it.

You then have two steps:
1) store your XPath expression as a string:
2) use the custom Xpath function to evaluate it:

Storing your XPath expression as a string
-----------------------------------------
You want to store the unevaluated XPath expression, so, use a String
expression - that is, surround the expression in quotes. Of course, you are
using quotes in the expression, and the attribute itself is using quotes, so
you need to do a little escaping (this works in JET 0.9 and later). Here's
your expression, respun:

<c:setVariable var="allEntityAttributes"
select=" \"
//namedElements[self::Entity][@name=$entityName]/features[se lf::Attribute]
\" "
/>

(I've made a small change in your expression around the $entityName variable
to remove the {} and the single quotes.)

An XPath funciton to evaluate a string as an XPath
---------------------------------------------------

Declare the function using the xpathFunctions extension point. Here's a
snippet from plugin.xml:

<extension
point="org.eclipse.jet.xpathFunctions">
<function
implementation="test.jet.defered.xpaths.functions.EvalFunction "
maxArgs="1"
minArgs="1"
name="eval">
</function>

And, here's the function itself...

package test.jet.defered.xpaths.functions;

import java.util.List;

import org.eclipse.jet.xpath.Context;
import org.eclipse.jet.xpath.XPath;
import org.eclipse.jet.xpath.XPathException;
import org.eclipse.jet.xpath.XPathExpression;
import org.eclipse.jet.xpath.XPathFactory;
import org.eclipse.jet.xpath.XPathFunction;
import org.eclipse.jet.xpath.XPathFunctionWithContext;
import org.eclipse.jet.xpath.XPathRuntimeException;
import org.eclipse.jet.xpath.XPathUtil;
import org.eclipse.osgi.util.NLS;

public class EvalFunction implements XPathFunction, XPathFunctionWithContext
{

private Context context;

@Override
public Object evaluate(List args) {
// one and only argument is a string containing an unparsed XPath
expression
String unparsedXPath = XPathUtil.xpathString(args.get(0));

// create an XPath instance, on configure it from the current XPath
context.
XPath xpath =
XPathFactory.newInstance().newXPath(context.getAnnotationMan ager());
xpath.setXPathFunctionResolver(context.getFunctionResolver() );
xpath.setXPathVariableResolver(context.getVariableResolver() );

try {
// compile and return the result of the XPath
XPathExpression compiledXPath = xpath.compile(unparsedXPath);
return compiledXPath.evaluate(context.getContextNode());
} catch (XPathException e) {
throw new XPathRuntimeException(NLS.bind("XPath compilation error: %1.
Expression: %2", e.getLocalizedMessage(), unparsedXPath), e);
}
}

@Override
public void setContext(Context context) {
// save the current XPath context - used by evaluate(List)
this.context = context;
}

}

I declared the function right in the JET project I was testing with. But,
you can do this in another plug-in project if you wish (lets you re-use the
function).


Using the function
------------------

<%-- ensure the variables used are set --%>
<c:setVariable var="entityName" select=" 'SomeEntityName' "/> <%-- not
the single quotes --%>

<c:iterate select="eval($allEntityAttributes)" var="attr" >
....
</c:iterate>




Any votes for adding this to JET itself?

Paul
Re: Use of JET setVariable to store commonly used XPath expressions [message #53949 is a reply to message #53923] Mon, 15 December 2008 11:08 Go to previous messageGo to next message
Mark Wood is currently offline Mark Wood
Messages: 8
Registered: July 2009
Junior Member
Paul,

Many thanks for getting back to me. I had a quick play with your first
suggested solution and that was successful. I will switch over to using
the function later.

I'd certainly vote for this being added to JET permanently. It facilitates
easier to read, more manageable code; particularly if the model you are
generating from changes significantly -- going through all of the
templates and having to change each expression is a real pain.

Thanks again for all of your help.

Mark
Re: Use of JET setVariable to store commonly used XPath expressions [message #54335 is a reply to message #53949] Tue, 16 December 2008 13:59 Go to previous message
Paul Elder is currently offline Paul Elder
Messages: 849
Registered: July 2009
Senior Member
Mark:

Here's the bugzilla. I've scheduled it for the Galileo release:

https://bugs.eclipse.org/bugs/show_bug.cgi?id=258996

Paul
Previous Topic:[MTL] Status?
Next Topic:Problem loading model after updating to latest version of JET
Goto Forum:
  


Current Time: Thu Aug 21 02:39:28 EDT 2014

Powered by FUDForum. Page generated in 0.02017 seconds