jenetics / jpx

JPX - Java GPX library
Apache License 2.0
206 stars 31 forks source link

Can't read file if it contains any extension tag #137

Closed TheNatanx closed 3 years ago

TheNatanx commented 3 years ago

Hello,

I am currently trying to use your lib to encode and decode GPX files. I am running into a problem whenever I want to read any file containing extensions tags. As soon as the tag is removed, the parser can properly read the file without any difficulty. I get the “java.io.InvalidObjectException: Invalid 'gpx' input.”. I tried using GPX files generated by software such as MapSource (see exemple xml file below) and ultimately I resorted to try using xml files yourself used in your tests such as jpx/src/test/resources/io/jenetics/jpx/extensions-waypoint.gpx and it still does not work. The code I wrote in to read the file is the following:

try {
            GPX gpx = GPX.read(pastString);
            List<WayPoint> list = gpx.getWayPoints();

            for (WayPoint wayPoint : list) {
                log.info(String.valueOf(wayPoint.getName()));
                log.info(String.valueOf(wayPoint.getComment()));
                log.info(String.valueOf(wayPoint.getLatitude().toDegrees()));
                log.info(String.valueOf(wayPoint.getLongitude().toDegrees()));
                log.info(String.valueOf(wayPoint.getElevation()));
                log.info(String.valueOf(wayPoint.getSymbol()));
            }
        } catch (IOException e) {
            log.error(String.valueOf(e));
        }

At this point I am wondering if this a bug? if I am doing something wrong? and whether if it is possible to simply ignore the extension tags whenever I want to read a file.

Hopefully you can help me out 😊

My XML File ```xml Garmin International 85 TESTTOS azertyy azertyy Flag, Blue 2000 25 45 SymbolAndName
az er rt France 45000
0606060606
```
jenetics commented 3 years ago

Hi @TheNatanx,

I'm able to parse the given file.

@Test
public void issue137_Parsing() throws IOException {
    final String resource = "/io/jenetics/jpx/ISSUE-137.gpx";

    final GPX gpx;
    try (InputStream in = getClass().getResourceAsStream(resource)) {
        gpx = GPX.read(in);
    }

    final var ext = gpx.getWayPoints().get(0).getExtensions();
    ext.ifPresent(doc ->
        System.out.println(XML.toString(doc))
    );
}

And it prints out the content of the extension. I run it with Java 11 with the latest library version 2.1. Can you tell me which version are you using, the OS and the full stack-trace of your error?

TheNatanx commented 3 years ago

Well I am running the latest 2.1 version of the library on Windows 10. As of the stacktrace, there is only this one line i mentionned before "java.io.InvalidObjectException: Invalid 'gpx' input".

By the way, I am not able to execute your code as of the following message "'io.jenetics.jpx.XML' is not public in 'io.jenetics.jpx'. Cannot be accessed from outside package".

And, to conclude with, if i try using this piece of code on the same file i get a "java.io.InvalidObjectException: Null InputStream is not a valid argument" error :

final GPX gpx;
try (InputStream in = getClass().getResourceAsStream(s)) {
    gpx = GPX.read(in);
}

List<WayPoint> list = gpx.getWayPoints();

for (WayPoint wayPoint : list) {
    log.info(String.valueOf(wayPoint.getName()));
    log.info(String.valueOf(wayPoint.getComment()));
    log.info(String.valueOf(wayPoint.getLatitude().toDegrees()));
    log.info(String.valueOf(wayPoint.getLongitude().toDegrees()));
    log.info(String.valueOf(wayPoint.getElevation()));
    log.info(String.valueOf(wayPoint.getSymbol()));
}
TheNatanx commented 3 years ago

Okay, ultimately I found were it can be mixed up. I am using other libs alongside yours and one seems to interfere with the XML provider because I get this error javax.xml.transform.TransformerException: Unable to transform a source of type javax.xml.transform.stax.StAXSource

Is there anyway to overide it to get back to the original provider ? I would appreciate any advice from you. I found that it may be related to another lib trying to handle XMLs and could cause a direct or indirect conflict : the woodstox library (https://github.com/FasterXML/woodstox)

jenetics commented 3 years ago

Maybe implementing your own XMLProvider class will help. It's based on the service loader mechanism of Java.

TheNatanx commented 3 years ago

Okay, i just don't understand fully the part about the META-INF file an how to define/use it.

jenetics commented 3 years ago

Create a class and extend from the XMLProvider class of the JPX library.

package com.mypackage;
class MyXMLProvider extends XMLProvider {
   @Override
   public DocumentBuilderFactory documentBuilderFactory() {
      // Configure your own document builder factory.
      return ...;
   }
}

Create a file META_INF/services/io.jenetics.jpx.XMLProvider, in the resources folder of your project (if you are using the usual maven layout), with the following content:

com.mypackage.MyXMLProvider

The JPX library will now load and use your MyXMLProvider and use the DocumentBuilderFactory, created by your implementation, for parsing the extensions.

jenetics commented 3 years ago

It might also be necessary to override the [xmlInputFactory](https://www.javadoc.io/static/io.jenetics/jpx/2.1.0/io.jenetics.jpx/io/jenetics/jpx/XMLProvider.html#xmlInputFactory()) method.