To make the new e4 way of building a complete model from small model pieces – named fragments – more flexible in 4.1, I’ve been developing a JXPath extension which works ontop of the reflective EMF-API.
I know that there’s already the possibility to query models using OCL but there are many more people familiar with XPath than the sometimes very cryptic OCL syntax. Some code samples might make clear why I think querying and navigating through EMF-Models using XPath is a very useful thing.
As an example model I’m using the Library-Model which is well known to most people who’ve worked with EMF.
An instance of the model would probably look like this:
The XML-Source helps probably to understand the references:
<?xml version="1.0" encoding="ASCII"?> <extlib:Library xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:extlib="http:///org/eclipse/emf/examples/library/extlibrary.ecore/1.0.0" xsi:schemaLocation="http:///org/eclipse/emf/examples/library/extlibrary.ecore/1.0.0 ../org.eclipse.emf.examples.library/model/extlibrary.ecore"> <stock xsi:type="extlib:Book" borrowers="//@borrowers.1" title="Mystery Book 1" author="//@writers.0"/> <stock xsi:type="extlib:Book" borrowers="//@borrowers.0" title="Sience Book 1" category="ScienceFiction" author="//@writers.0"/> <stock xsi:type="extlib:Book" borrowers="//@borrowers.1" title="Mystery Book 2" author="//@writers.1"/> <stock xsi:type="extlib:Book" borrowers="//@borrowers.0" title="Sience Book 2" category="ScienceFiction" author="//@writers.1"/> <writers address="Hometown" firstName="Tom" lastName="Schindl" books="//@stock.0 //@stock.1"/> <writers address="Homecity" firstName="Boris" lastName="Bokowski" books="//@stock.2 //@stock.3"/> <borrowers address="Hometown" firstName="Paul" lastName="Webster" borrowed="//@stock.1 //@stock.3"/> <borrowers address="Homecity" firstName="Remy" lastName="Suen" borrowed="//@stock.0 //@stock.2"/> </extlib:Library>
Now let’s try to answer some questions:
- Find all “Mystery Books”
- Authors of “Mystery Books”
- Find all writers and borrowers in “Hometown”
- Find all borrowers “Mystery books”
The XPath-Code one can use with the new support is like this.
- Load the model and setup a context for the XPath-Query
public class Application implements IApplication { public Object start(IApplicationContext context) throws Exception { ResourceSet resourceSet = new ResourceSetImpl(); resourceSet.getResourceFactoryRegistry() .getExtensionToFactoryMap() .put(Resource.Factory.Registry.DEFAULT_EXTENSION,new XMIResourceFactoryImpl()); URI uri = URI.createPlatformPluginURI("/testxpath/Library.xmi",true); Resource resource = resourceSet.getResource(uri, true); Library l = (Library) resource.getContents().get(0); XPathContextFactory<EObject> f = EcoreXPathContextFactory.newInstance(); XPathContext xPathContext = f.newContext(l); // Execute the XPaths } }
- Find all “Mystery Books”
{ System.out.println("Mystery Books:"); Iterator<Book> it = xPathContext.iterate("/books[category='Mystery']"); while( it.hasNext() ) { System.out.println(" " + it.next().getTitle()); } }
- Authors of “Mystery Books”
{ System.out.println("Mystery Book Authors:"); Iterator<Writer> it = xPathContext.iterate("/books[category='Mystery']/author"); while( it.hasNext() ) { Writer w = it.next(); System.out.println(" " + w.getFirstName() + "," + w.getLastName()); } }
- Find all writers and borrowers in “Hometown”
{ System.out.println("Borrower/Writer in Hometown:"); Iterator<Person> it = xPathContext.iterate( "/borrowers[address='Hometown']|/writers[address='Hometown']" ); while( it.hasNext() ) { Person b = it.next(); System.out.println(" " + b.getFirstName() + "," + b.getLastName()); } }
- Find all borrowers “Mystery books”
{ System.out.println("Borrower of Mystery books:"); Iterator<Borrower> it = xPathContext.iterate( "/borrowers[borrowed/category='Mystery']"); while( it.hasNext() ) { Borrower b = it.next(); System.out.println(" " + b.getFirstName() + "," + b.getLastName()); } }
Executing the code leads to the following output:
Mystery Books: Mystery Book 1 Mystery Book 2 Mystery Book Authors: Tom,Schindl Boris,Bokowski Borrower/Writer in Hometown: Paul,Webster Tom,Schindl Borrower of Mystery books: Remy,Suen
I think the above shows how easy it is to navigate/query an EMF-Model-Instance using JXPath and using this new EMF-extension.
I hope we’ll manage to integrate this support into one of the next Eclipse 4.1 I-builds until then you can access the source from the e4-cvs-repository. I’m also thinking about moving the code at some point to EMF directly because there’s no dependency on e4 and such an implementation could be of use for others as well.
Nice, Tom! Two questions:
1) Can you filter on the class of objects, e.g. [classname() = ‘SpecialBook’]
2) There are many utilities for both the core and UI of EMF, that could/should have a home at Eclipse. But where should these be gathered (and who should decide their ‘worthyness’).
1) No not yet but I think one can implement custom functions and so it should easily possible
2) I agree probably there should be an EMF project which hosts such additions
I’ve developed similar thing in-house, I would like to try replacing it with your implementation since it’s probably nicer and more complete. Where in Eclipse CVS is this ?
You can find the bundle in Eclipse CVS pserver:dev.eclipse.org:/cvsroot/eclipse/e4/org.eclipse.e4.ui/bundles/org.eclipse.e4.emf.xpath
Hello Tom,
are ExtendedMetaData supported?
We have an XSD and generate Ecore from it with some renamings. In this case the ExtendedMetaData tags are filled and the XML parser/serializer is aware of these. But what about your (and other) XPath Tools?
For me it seems reasonable to be aware of them because XPath only deals with XML and says nothing about Ecore.
Also from an API point of view the XPath that points inside of an XML and the XML instance itself should be aligned.
What about this?
10x in avdance, Michael
No ExtendedMetaData is not yet supported. The XPath is not executed on the XML-File but on the in memory representation of the EMF-Model. I’ll try to take a look at the ExtendedMetaData stuff to see if I can support it.
I searched a lot to find the following soltion, thus I’d like to mention it here:
To query th XML model one can save the EMF resource and query on the returned DOMDocument. You can use the DomHelper to map the returned nodes back to EObjects.
Naturallly that always works but it is much better to query the in memory model like provided by jxpath. Just fetch the projects from git.eclipse.org and you are ready to go
Is the // syntax of xpath supported? I personally tried and it blocked my application when I call iterator.hasNext()
This sounds like a bug. Please provide a minimal test case so that I can take a look and debug
I am new to EMF Query / Query 2 and after browsing through the standard and OCL query tutorials in the eclipse help content, I wish that the xpath support would already be available as third option (in 3.x eclipse/emf environments). You are so right when saying that “there are many more people familiar with XPath than the sometimes very cryptic OCL syntax”. I think it would crush the learning curve for emf query immensely.
Is there already a bug / feature request to establish xpath as third option as query syntax for emf query?
I don’t think there’s a bug open to include XPath to EMF Query. If you file one just add me to the CC list (tom dot schindl at bestsolution dot at)
Hi Tom,
I’m a newer of EMF and XPath. I want to query point of interest from a xml file. But I failed to install JXPath with my eclipse. Is it not compatible with Mac OX? I can get XPath and XPathFactory but no XPathContext. Could you please give me some advice?
Thank you in advance!
Yvonne
First of all – the library here is not executing queries on XML-Structures but their in memory representation. I’m not sure what you mean compatible. How did you try to install JXPath?
Hi Tom,
I’m fine with JXPath now. I directly imported JXPath in build path.
Thank you for your help!
This looks very useful. Is there a way to install and use this on Eclipse 3.6?
yes – only EMF and jxpath are needed
Sorry if this is obvious, but how do I go about installing it (and jxpath) then in 3.6? If I just need to use them as java packages where is the best place to get the jxpath-emf code? Thx.
well easiest is to check them out from the git-repo (emf-support) and jxpath from orbit
Hi I would like to use the tool but I do not know how to get and install it. I am using Eclipse 4.2. Thanks in advance,
Daniel.
Hi Tom, I would like to use this tool for query a KDM instance meta-model. How can I get and install it?. I´m using eclipse 4.2.
Thanks
Daniel
Hi Tom. Is this still the correct repo?
git://git.eclipse.org/gitroot/e4/eclipse.platform.ui.e4.git
Is an existing build for org.eclipse.e4.emf.xpath available through some p2 repo?
yes the repo is still correct but IIRC it is not contained in any build.
Nice. I just had a need for something like this again and tried to dig out an implementation of JXPath for EMF models I wrote nearly ten years ago (http://emfsearch.sourceforge.net/), but then I found yours first instead 🙂 Have you meanwhile introduced a function to query an object’s EClass? I think I had something like that in my implementation.
I think I will try to see if my implementation still works in a new Eclipse since it also featured a simple UI.
I have not really been working on the code base but lately others picked it up and https://bugs.eclipse.org/bugs/show_bug.cgi?id=442821