Navigating/Querying EMF-Models using XPath


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.

This entry was posted in e4, EMF. Bookmark the permalink.

25 Responses to Navigating/Querying EMF-Models using XPath

  1. Hallvard Trætteberg says:

    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’).

    • Tom Schindl says:

      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

  2. Aleksander Bandelj says:

    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 ?

    • Tom Schindl says:

      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

  3. 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

    • Tom Schindl says:

      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.

      • Jörg says:

        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.

      • Tom Schindl says:

        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

  4. Bob says:

    Is the // syntax of xpath supported? I personally tried and it blocked my application when I call iterator.hasNext()

  5. Kris says:

    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?

    • Tom Schindl says:

      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)

  6. Yvonne says:

    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

    • Tom Schindl says:

      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?

      • Yvonne says:

        Hi Tom,
        I’m fine with JXPath now. I directly imported JXPath in build path.
        Thank you for your help!

  7. This looks very useful. Is there a way to install and use this on Eclipse 3.6?

  8. Daniel says:

    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.

  9. Daniel says:

    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

  10. Felix Dorner says:

    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?

  11. 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.

Leave a reply to Yvonne Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.