简体   繁体   中英

Java remove nodes from XML

There are a couple similar questions, I read all of them but can't get it to work.

I hava a XML file (a GPS track log), looking something like this:

  <trk>
<name>Aktueller Track : 07 FEB 2017 19:17</name>
<extensions>
  <gpxx:TrackExtension>
    <gpxx:DisplayColor>DarkGray</gpxx:DisplayColor>
  </gpxx:TrackExtension>
</extensions>
<trkseg>
  <trkpt lat="48.052169037982821" lon="16.298389015719295">
    <ele>142.88999999999999</ele>
    <time>2017-02-07T18:34:34Z</time>
  </trkpt>
  <trkpt lat="48.052171971648932" lon="16.298409970477223">
    <ele>147.22</ele>
    <time>2017-02-07T18:34:39Z</time>
  </trkpt>

which gets merged with some other data (heart rate) frome an other file. I just modified some existing code for my purpose, and this is already working.

Now i want to delete some trackpoints completely, if they are out of a certain time range. I'm able to identify those trackpoints and (for testing) add a "comment" to the entries I want to delete, but I wasn't able to remove them.

Here's the code:

private void create(File outputFile) throws TransformerConfigurationException, TransformerException, ParseException, FileNotFoundException {
            Document mergedDoc = (Document) gpxDoc.cloneNode(true);
            NodeList sections = mergedDoc.getElementsByTagName("trkpt");
            int nTr = sections.getLength();
            for (int i = 0; i < nTr; i++) {

                Element trackPt = (Element) sections.item(i);
                Node timeNode = Util.getChildByName(trackPt, "time");
                if (timeNode != null) {
                    String st = timeNode.getFirstChild().getNodeValue();
                    long time = Util.toTime(st);

                    int heartRate = trackPoints.getHeartRateForTime(time + tcxTimeOffset);
                    if (heartRate > 0) {
                        Element exframe = mergedDoc.createElement("extensions");
                        Element extension = mergedDoc.createElement("gpxtpx:TrackPointExtension"); 
                        Element hr = mergedDoc.createElement("gpxtpx:hr");
                        hr.appendChild(mergedDoc.createTextNode(String.valueOf(heartRate)));//
                        extension.appendChild(hr);
                        exframe.appendChild(extension);
                        trackPt.appendChild(exframe);
                    }
                    if(crop){
                        if (time < (tcxStartTime.getTime()-5000) || time > (tcxEndTime.getTime()+5000)){
                            //for testing
                            Element remove = mergedDoc.createElement("delete");
                            trackPt.appendChild(remove);
                        }
                    }
                }
            }

//.... below this the data is written out to the file...

the result loos something like this at the moment:

.....
<trkpt lat="48.052186975255609" lon="16.29835800267756">
    <ele>206.81999999999999</ele>
    <time>2017-02-07T18:37:28Z</time>
  <delete/>
</trkpt>
<trkpt lat="48.052185969427228" lon="16.298419022932649">
    <ele>206.34</ele>
    <time>2017-02-07T18:38:30Z</time>
    <extensions>
        <gpxtpx:TrackPointExtension>
             <gpxtpx:hr>83</gpxtpx:hr>
        </gpxtpx:TrackPointExtension>
    </extensions>
</trkpt>

.....

Thanks for help!

Edit:

I tried things like:

trackPt.getParentNode().removeChild(trackPt);

but this results in a NullPoiterException

Node removeNode = sections.item(i); mergedDoc.removeChild(removeNode); , but this results in a org.w3c.dom.DOMExeption: NOT_FOUND_ERR

mergedDoc.getElementsByTagName("trkseg").item(0).removeChild‌​(trackPt); and I also also get a java.lang.NullPointerException

You don't show how you have tried. But the general rule is : a child element has to be removed from its parent and not from itself.

1)You can retrieve the parent by invoking getParentNode() ( Node interface).

2)Then from the parent node you can invoke removeChild() with as parameter the child node to remove.

I read somewhere else, that removing elements within a loop using them the can cause unpredictable results, therefore I solved the problem by deleting them in a separate loop:

NodeList sections = mergedDoc.getElementsByTagName("trkpt");
Set<Element> targetElements = new HashSet<Element>();
int nTr = sections.getLength();
for (int i = 0; i < nTr; i++) {
    Element trackPt = (Element) sections.item(i);

    //................
    //removed not relevant code for answer.....
    //.......

    //
    if (time < (tcxStartTime.getTime()-5000) || time > (tcxEndTime.getTime()+5000)){
        targetElements.add(trackPt);
    }

}


for (Element trackPt: targetElements) {
    trackPt.getParentNode().removeChild(trackPt);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM