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.