2017-02-10 8 views
0

Есть пара подобных вопросов, я прочитал их все, но не могу заставить его работать.Java удаляет узлы из XML

Я хава XML файл (журнал GPS трек), ищет что-то вроде этого:

<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> 

который получает объединены с некоторыми другими данными (частота сердечных сокращений) Фром в другой файл. Я только что изменил какой-то существующий код для своей цели, и это уже работает.

Теперь я хочу полностью удалить трекпоинты, если они находятся вне определенного диапазона времени. Я могу определить эти трекпоинты и (для тестирования) добавить «комментарий» к записям, которые я хочу удалить, но я не смог их удалить.

Вот код:

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); 
         } 
        } 
       } 
      } 

// .... ниже этого данные записываются на файл ...

результат Лоос что-то вроде этого в данный момент:

..... 
<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> 

.....

Спасибо за помощь!

Edit:

Я пытался что-то вроде:

trackPt.getParentNode().removeChild(trackPt); 

, но это приводит к NullPoiterException

Node removeNode = sections.item(i); mergedDoc.removeChild(removeNode);, но это приводит к org.w3c.dom.DOMExeption: NOT_FOUND_ERR

mergedDoc.getElementsByTagName("trkseg").item(0).removeChild‌​(trackPt);, а также я также получаю java.lang.NullPointerException

ответ

0

Я читал где-то еще, что удаление элементов внутри цикла с использованием им может привести к непредсказуемым результатам, поэтому я решил эту проблему, удалив их в отдельном цикле:

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); 
} 
0

Вы не показываете, как вы пробовали. Но общее правило: дочерний элемент должен быть удален из его родителя, а не из него.

1) Вы можете получить родительский объект, вызвав getParentNode() (Node).

2) Затем из родительского узла вы можете вызывать removeChild() с параметром дочерний узел для удаления.

+0

Я попытался «trackPt.getParentNode() .removeChild (trackPt);» но это приводит к исключению NullPoiterException. – roska

+0

Я также пробовал «Узел removeNode = section.item (i); mergedDoc.removeChild (removeNode);», но это приводит к org.w3c.dom.DOMExeption: NOT_FOUND_ERR – roska

+0

Это довольно странно, как поведение. Если вы попробуете 'mergedDoc.getElementsByTagName (« trkseg »). Item (0) .removeChild (trackPt);' что вы получаете? – davidxxx