2010-09-15 11 views
15

मैं एक स्क्रिप्ट बना रहा हूं जिसे एक्सएमएल फाइलों को पैच करना है, जिसमें तत्वों की एक सूची को दूसरे के साथ बदलना शामिल है। निम्न फ़ंक्शन एक पैच (उसी नाम वाले तत्वों की संभावित रूप से रिक्त सूची को शामिल करना) को उसी नाम से तत्वों की मूल तत्व की सूची (संभवतः एक खाली सूची) पर लागू करता है। (यह पैचिंग तर्क का केवल एक छोटा सा हिस्सा है)।मैं अभी पाया गया एक बाल तत्व क्यों नहीं हटा सकता? NOT_FOUND_ERR

क्यों, जब मैं कोड चलाता हूं, तो क्या मुझे निम्न त्रुटि मिलती है?

org.w3c.dom.DOMException: NOT_FOUND_ERR: An attempt is made to reference a node in a context where it does not exist. 
    at com.sun.org.apache.xerces.internal.dom.ParentNode.internalRemoveChild(ParentNode.java:503) 
    at com.sun.org.apache.xerces.internal.dom.ParentNode.removeChild(ParentNode.java:484) 
    at CombineSweeps$PTReplaceNodeList.apply(CombineSweeps.java:514) 

(लाइन 514 से नीचे चिह्नित किया गया है।) जहाँ तक मुझे यह समझ के रूप में, मैं सिर्फ सत्यापित किया है कि तत्व मौजूद है (क्योंकि NodeList लाइव है, अपनी पहली प्रविष्टि हमेशा अगले मैच या अशक्त हो जाएगा)। दिलचस्प बात यह है कि यह हमेशा एक समस्या नहीं है।

private static class PTReplaceNodeList extends PTBase { 
    private final String name; 
    private final String nextElement; 
    private final List<Node> childList; 

    ... 

    int apply(Document document, Node parent, Node node_unused) { 
     NodeList nodes; 
     // A marker for where to insert our nodes. 
     // We make a guess using nextElement (if null, means at end). 
     Node refNode = null; 
     if (parent instanceof Document) { // root element 
      Document parDoc = (Document) parent; 
      nodes = parDoc.getElementsByTagName(name); 
      if (nextElement != null) { 
       refNode = parDoc.getElementsByTagName(nextElement).item(0); 
      } 
     } else { 
      Element parElt = (Element) parent; 
      nodes = parElt.getElementsByTagName(name); 
      if (nextElement != null) { 
       refNode = parElt.getElementsByTagName(nextElement).item(0); 
      } 
     } 

     while (true) { 
      // iterate through the list of nodes 
      Node node = nodes.item(0); 
      if (node == null) { 
       break; 
      } 

      // Reliable guess: insert before node following last in list 
      refNode = node.getNextSibling(); 

      parent.removeChild(node); // line 514 
     } 

     for (Node child : childList) { 
      Node imported = document.importNode(child, true); 
      parent.insertBefore(imported, refNode); 
     } 
     return childList.size(); 
    } 
} 

संपादित करें: मैं getElementsByTagName() के लिए एक स्थानापन्न (स्वीकार किए जाते हैं जवाब देखें) के रूप में निम्नलिखित समारोह का इस्तेमाल किया।

/** Returns all direct children of node with name name. 
* 
* Note: not the same as getElementsByTagName(), which finds all descendants. */ 
static List<Node> getChildNodes(Node node, String name){ 
    ArrayList<Node> r = new ArrayList<Node>(); 
    NodeList children = node.getChildNodes(); 
    int l = children.getLength(); 
    for(int i = 0; i < l; ++i){ 
     if(name.equals(children.item(i).getNodeName())) 
      r.add(children.item(i)); 
    } 
    return r; 
} 

उत्तर

12

इसका कारण यह है कि जब आप parent.removeChild (नोड) कर रहे हैं, माता-पिता जरूरी नहीं कि नोड के माता पिता क्योंकि getElementsByTagName() एक पुनरावर्ती खोज कर रहा है है।

+0

धन्यवाद कैसे तुम दोनों। क्या कोई गैर-पुनरावर्ती संस्करण है- 'getChildNodes()' और अपना स्वयं का खोज-नाम-नाम लागू करें? जितना अधिक मैं जावा की एक्सएमएल लाइब्रेरी के बारे में सीख रहा हूं, उतना ही कम मैं इसे ढूंढ रहा हूं जो मैं उम्मीद करता हूं। – dhardy

+0

मुझे लगता है कि आपको अपनी खुद की खोज –

+0

लागू करना होगा यह सबसे अच्छा समाधान प्रतीत होता है। मैंने अपने मामले में 'सूची ' लौटने वाला एक फ़ंक्शन लागू किया है, क्योंकि मैं वास्तव में 'नोडलिस्ट' के "लाइव" व्यवहार को भी नहीं चाहता हूं (मेरे प्रश्न के अंत में जोड़ा गया है क्योंकि मैं यहां कोड ब्लॉक पोस्ट नहीं कर सकता)। – dhardy

4

parent.removeChild(node) NOT_FOUND_ERR फेंक रहा है क्योंकि nodeparent का बच्चा नहीं है। मुझे लगता है कि nodegetElementsByTagName से आता है जो parent का तत्काल बच्चा नहीं हो सकता है। यह parent के तहत कहीं भी हो सकता है।

0

बिल्डिंग @Maurice और @fahd द्वारा निदान पर ...

आप बस से पहले एक शर्त नहीं डाल सकते हैं

if (parent.isSameNode(node.getParentNode())) 

parent.removeChild(node); 

जैसे

तो यह केवल होगा दिए गए माता-पिता के प्रत्यक्ष बच्चे को हटा दें।

+0

मुझे लगता है कि यह काम करेगा - दुर्भाग्य से एक अक्षम तरीके से। – dhardy

11

के बारे में
nodeToBeRemoved.getParentNode().removeChild(nodeToBeRemoved); 
+0

यह प्रश्न का उत्तर नहीं प्रदान करता है। किसी लेखक से स्पष्टीकरण की आलोचना या अनुरोध करने के लिए, अपनी पोस्ट के नीचे एक टिप्पणी छोड़ दें। – NT3RP

+0

ऐसा करता है, यह लाइन 514 पर होनी चाहिए - आपको getElementsByTagName का उपयोग करके एक नोड मिलता है, आप getParentNode API का उपयोग करके इसे अपने माता-पिता से हटा दें –