jOOQ / jOOX

jOOX - The Power of jQuery Applied to W3C DOM Like JDBC, DOM is a powerful, yet very verbose low-level API to manipulate XML. The HTML DOM an be manipulated with the popular jQuery product, in JavaScript. Why don't we have jQuery in Java? jOOX is jQuery's XML parts, applied to Java.

Home Page:http://www.jooq.org/products

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Wrong selector to XPath translation in the presence of namespaces in the XML document

warren-bank opened this issue · comments

desired use case:

    try {
      Match xmlRoot = JOOX.$(
        new File(xmlFilepath)
      );

      Match points = xmlRoot.find("wpt, rtept, trkpt");

      System.out.println("GPX points found: " + points.size());  // 0
    }
    catch(Exception e) {
      System.out.println("Error: " + e.toString());
    }

workaround:

    private static final FastFilter is_wpt   = JOOX.tag("wpt",   true);
    private static final FastFilter is_rtept = JOOX.tag("rtept", true);
    private static final FastFilter is_trkpt = JOOX.tag("trkpt", true);

    private static final Filter is_point_tag = new Filter() {
      @Override
      public boolean filter(Context context) {
        return (
          is_wpt.filter(  context) ||
          is_rtept.filter(context) ||
          is_trkpt.filter(context)
        );
      }
    };

    try {
      Match xmlRoot = JOOX.$(
        new File(xmlFilepath)
      );

      Match points = xmlRoot.find(is_point_tag);

      System.out.println("GPX points found: " + points.size());  // 100
    }
    catch(Exception e) {
      System.out.println("Error: " + e.toString());
    }

Thank you very much for your report. Would you mind sharing an example file (xmlFilepath) that contains XML data to see what the input would be in your case?

Hi. Here is everything you'll need to run the exact same tests that I did. Thanks for looking into it. And big thanks for this library. Aside from this minor inconvenience, it's made parsing XML in Java extremely easy.

GPX data files:

app.java test 1 (fail):

import org.joox.JOOX;
import org.joox.Match;
import org.joox.Each;
import org.joox.Context;

import java.io.File;

class app {
  public static void main(String[] args){
    String GPX_filepath = args[0];

    try {
      Match xmlRoot = JOOX.$(
        new File(GPX_filepath)
      );

      Match points = xmlRoot.find("wpt, rtept, trkpt");

      System.out.println("GPX points found: " + points.size());
    }
    catch(Exception e) {
      System.out.println("Error: " + e.toString());
    }
  }
}

app.java test 2 (success):

import org.joox.JOOX;
import org.joox.Match;
import org.joox.Context;

import org.joox.Filter;
import org.joox.FastFilter;

import java.io.File;

class app {
  private static final FastFilter is_wpt   = JOOX.tag("wpt",   true);
  private static final FastFilter is_rtept = JOOX.tag("rtept", true);
  private static final FastFilter is_trkpt = JOOX.tag("trkpt", true);

  private static final Filter is_tag_group = new Filter() {
    @Override
    public boolean filter(Context context) {
      return (
        is_wpt.filter(  context) ||
        is_rtept.filter(context) ||
        is_trkpt.filter(context)
      );
    }
  };

  public static void main(String[] args){
    String GPX_filepath = args[0];

    try {
      Match xmlRoot = JOOX.$(
        new File(GPX_filepath)
      );

      Match points = xmlRoot.find(is_tag_group);

      System.out.println("GPX points found: " + points.size());
    }
    catch(Exception e) {
      System.out.println("Error: " + e.toString());
    }
  }
}

1-compile.bat:

@echo off

set JAVA_HOME=C:\Android\android-studio\jre
set CLASSPATH=%JAVA_HOME%\lib;%CLASSPATH%
set PATH=%JAVA_HOME%\bin;%PATH%

set CLASSPATH=%~dp0.;%~dp0.\libs;%~dp0.\libs\JOOX.jar;%CLASSPATH%

javac -classpath "%CLASSPATH%" "app.java"

echo.
pause

2-run.bat:

@echo off

set JAVA_HOME=C:\Android\android-studio\jre
set CLASSPATH=%JAVA_HOME%\lib;%CLASSPATH%
set PATH=%JAVA_HOME%\bin;%PATH%

set CLASSPATH=%~dp0.;%~dp0.\libs;%~dp0.\libs\JOOX.jar;%CLASSPATH%

java "app" "%~dp0data\data.gpx"

echo.
pause

directory organization:

1-compile.bat
2-run.bat
app.java
|_data
| |_data.gpx
|_libs
| |_JOOX.jar

version:

Thanks a lot for your detailed test cases. This reminds me, I will have to create an MCVE template for jOOX as well, just like for jOOQ: https://github.com/jOOQ/jOOQ-mcve, which would have made creating such a test case much easier for you. So, thanks again for going through that trouble :)

I can reproduce the issue. The selector wpt, rtept, trkpt is translated correctly to XPath //wpt | //rtept | //trkpt. Will investigate why this doesn't yield any results.

This is a namespace issue. If you remove your xmlns="http://www.topografix.com/GPX/1/1" (as a workaround), then the selector works.

The behaviour is inconsistent with other usages of selectors in jOOX. I'll see how this can be fixed.

We need namespace unaware XPath expressions, such as:

//*[local-name() = 'wpt'] | //*[local-name() = 'rtept'] | //*[local-name() = 'trkpt']

Version 1.6.2 has been released including a fix for this issue. It will be available from Maven Central shortly.