使用 SAX 解析日期 Java

Parsing dates with SAX Java

我在使用 SAX 解析 gpx 文件的日期时遇到问题。不知何故,它无法正确获取某些节点的 <time> 标记。大部分节点没问题,其他标签好像没问题
我在不同的 gpx 文件上进行测试,它总是在相同文件的相同节点上失败,并且没有特殊字符或任何东西。而且是周期性的。

我正在打印错误旁边的节点号。而第3列是当前错误与上次错误的差值

它通常在第一个错误 800 到 1000 左右开始。如您所见,日期没有被正确选择,出于某种原因它们被修剪了。

这是我的经纪人

package ec.com.mapachedev.webmapper.gpx;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class SAXFileHandler extends DefaultHandler {
    private String reading;
    private List<SAXTrack> tracks;
    private List<SAXWayPoint> waypoints;
    private List<SAXTrackPoint> trackpoints;
    private SAXTrack track;
    private SAXTrackPoint trackPoint;
    private SAXWayPoint wayPoint;
    private LocalDateTime fechaExtraido;
    private LocalDateTime fechaIni;
    private LocalDateTime fechaFin;
    private DateTimeFormatter parser = DateTimeFormatter
            .ofPattern("[yyyy-MM-dd'T'HH:mm:ss.SSS'Z']" + "[yyyy-MM-dd'T'HH:mm:ss'Z']");
    private boolean isWaypoint = false;
    private boolean isTrackPoint = false;
    private int cont = 0;

    public SAXFileHandler() {
        super();
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        try {
            if (qName.equals("trkpt")) {
                trackPoint = new SAXTrackPoint();
                isWaypoint = false;
                isTrackPoint = true;
                try {
                    trackPoint.setLat(Double.parseDouble(attributes.getValue("lat")));
                    trackPoint.setLon(Double.parseDouble(attributes.getValue("lon")));
                } catch (Exception e) {
                    System.out.println("Error " + e.getMessage());
                }

            } /*
                 * else if (qName.equals("trkseg")) {
                 * 
                 * }
                 */else if (qName.equals("trk")) {
                track = new SAXTrack();
                isWaypoint = false;
                isTrackPoint = false;
            } else if (qName.equals("wpt")) {
                isWaypoint = true;
                isTrackPoint = false;
                wayPoint = new SAXWayPoint();
                try {
                    wayPoint.setLat(Double.parseDouble(attributes.getValue("lat")));
                    wayPoint.setLon(Double.parseDouble(attributes.getValue("lon")));
                } catch (Exception e) {
                    System.out.println("Error " + e.getMessage());
                }
            } else if (qName.equals("gpx")) {
                tracks = new ArrayList<SAXTrack>();
                waypoints = new ArrayList<SAXWayPoint>();

                isWaypoint = false;
                isTrackPoint = false;
            }
        } finally {
            // no matter the node, we empty the StringBuilder accumulator when
            // we start
            // a new node.
            reading=null;
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {

        if (qName.equals("trkpt")) {
            track.getPuntos().add(trackPoint);
        } else if (qName.equals("speed")) {
            try {
                trackPoint.setVelocidad(Double.parseDouble(reading));
            } catch (Exception e) {
                System.out.println("Error " + e.getMessage());
            }
        } else if (qName.equals("time") && isTrackPoint) {
            System.out.println("Time Track " + reading + " "
                    + cont++);/*
                                 * try { cont++;
                                 * //System.out.println("Time Track " + reading
                                 * + " "+cont++);
                                 * trackPoint.setFecha(LocalDateTime.parse(
                                 * reading, parser)); // Siempre guardamos la
                                 * ultima fecha y si es la primer vez que //
                                 * grabamos fechas tambien ponemos fechaInicial
                                 * fechaFin = trackPoint.getFecha(); if
                                 * (fechaIni == null) fechaIni =
                                 * trackPoint.getFecha(); } catch (Exception e)
                                 * { System.out.println("Error " +
                                 * e.getMessage()+" " +cont); }
                                 */
        } else if (qName.equals("ele") && isTrackPoint) {
            try {
                trackPoint.setEle(Double.parseDouble(reading));
            } catch (Exception e) {
                System.out.println("Error " + e.getMessage());
            }
        } else if (qName.equals("name") && isTrackPoint) {
            // System.out.println("Nombre: "+reading);
            trackPoint.setNombre(reading);
        } else if (qName.equals("desc") && !isWaypoint && !isTrackPoint) {
            track.setDesc(reading);
        } else if (qName.equals("name") && !isWaypoint && !isTrackPoint) {
            track.setName(reading);
        } else if (qName.equals("desc") && isWaypoint) {
            wayPoint.setDesc(reading);
        } else if (qName.equals("cmt") && isWaypoint) {
            wayPoint.setCmt(reading);
        } else if (qName.equals("name") && isWaypoint) {
            wayPoint.setCmt(reading);
        } else if (qName.equals("time") && isWaypoint) {
            System.out.println("Time WP " + reading);
            wayPoint.setFecha(LocalDateTime.parse(reading, parser));
        } else if (qName.equals("ele") && isWaypoint) {
            try {
                wayPoint.setEle(Double.parseDouble(reading));
            } catch (Exception e) {
                System.out.println("Error " + e.getMessage());
            }
        } else if (qName.equals("trk")) {
            tracks.add(track);
        } else if (qName.equals("time") && tracks.size() == 0) {
            System.out.println("Time GPX " + reading);
            fechaExtraido = LocalDateTime.parse(reading, parser);
        }

    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        reading = new String(ch, start, length);
    }

    public List<SAXTrack> getTracks() {
        return tracks;
    }

    public void setTracks(List<SAXTrack> tracks) {
        this.tracks = tracks;
    }

    public List<SAXWayPoint> getWaypoints() {
        return waypoints;
    }

    public void setWaypoints(List<SAXWayPoint> waypoints) {
        this.waypoints = waypoints;
    }

    public List<SAXTrackPoint> getTrackpoints() {
        return trackpoints;
    }

    public void setTrackpoints(List<SAXTrackPoint> trackpoints) {
        this.trackpoints = trackpoints;
    }

    public SAXTrack getTrack() {
        return track;
    }

    public void setTrack(SAXTrack track) {
        this.track = track;
    }

    public SAXTrackPoint getTrackPoint() {
        return trackPoint;
    }

    public void setTrackPoint(SAXTrackPoint trackPoint) {
        this.trackPoint = trackPoint;
    }

    public SAXWayPoint getWayPoint() {
        return wayPoint;
    }

    public void setWayPoint(SAXWayPoint wayPoint) {
        this.wayPoint = wayPoint;
    }

    public LocalDateTime getFechaExtraido() {
        return fechaExtraido;
    }

    public void setFechaExtraido(LocalDateTime fechaExtraido) {
        this.fechaExtraido = fechaExtraido;
    }

    public LocalDateTime getFechaIni() {
        return fechaIni;
    }

    public void setFechaIni(LocalDateTime fechaIni) {
        this.fechaIni = fechaIni;
    }

    public LocalDateTime getFechaFin() {
        return fechaFin;
    }

    public void setFechaFin(LocalDateTime fechaFin) {
        this.fechaFin = fechaFin;
    }

    public DateTimeFormatter getParser() {
        return parser;
    }

    public void setParser(DateTimeFormatter parser) {
        this.parser = parser;
    }

}

您使用的 java.time class 和您的日期时间格式模式似乎不匹配。

您的所有日期时间实例都声明为类型:LocalDateTime,因此它们将期望传递给 parse 函数的文本值遵循:DateTimeFormatter.ISO_LOCAL_DATE_TIME 格式,即:2011-12-03T10:15:30.

来自 LocalDateTime JavaDoc:

A date-time without a time-zone in the ISO-8601 calendar system, such as 2007-12-03T10:15:30.

请注意格式 DOES 包含:'T',但 NOT 包含:'Z'。这与您问题中包含的所有错误消息一致;这些错误消息中引用的所有文本值都包含 'Z' 字符。

如果你调整传递给的格式模式:DateTimeFormatter.ofPattern删除'Z'字符,我相信你的问题会得到解决。

我更改了我的代码以使用它。 https://mappingdev.wordpress.com/2011/09/22/parsing-gpxxml-files-with-sax/

只需在代码中将 localName 更改为 name,一切正常