2012-05-24 14 views
7

Sto cercando di utilizzare Java per rimuovere tutti gli attributi xml da un file XML che corrisponde a un nome-attributo. Sono bloccato a questo punto. Nella parte inferiore di questo codice sono in grado di ottenere il valore dell'attributo di ciascun nodo mentre eseguo il ciclo, ma non riesco a capire come eliminare completamente l'attributo dal nodo. Qualche idea?Utilizzo di Java per rimuovere tutti gli attributi xml da un file XML che corrisponde a un nome-attributo?

import java.io.IOException; 
import java.io.StringWriter; 

import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 
import javax.xml.parsers.ParserConfigurationException; 
import javax.xml.transform.OutputKeys; 
import javax.xml.transform.Transformer; 
import javax.xml.transform.TransformerConfigurationException; 
import javax.xml.transform.TransformerException; 
import javax.xml.transform.TransformerFactory; 
import javax.xml.transform.TransformerFactoryConfigurationError; 
import javax.xml.transform.dom.DOMSource; 
import javax.xml.transform.stream.StreamResult; 

import org.w3c.dom.*; 
import org.xml.sax.SAXException; 


public class StripAttribute { 

    public static void main(String[] args) { 

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
    factory.setNamespaceAware(true); 
    org.w3c.dom.Document doc = null; 
    NodeList nodes = null; 
    try { 
     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
     DocumentBuilder db = dbf.newDocumentBuilder(); 
     doc = db.parse("a.xml"); 
     nodes = doc.getChildNodes(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } catch (ParserConfigurationException e) { 
     e.printStackTrace(); 
    } catch (SAXException e) { 
     e.printStackTrace(); 
    } 
    for (int i = 0; i < nodes.getLength(); i++) { 
     String id = nodes.item(i).getNodeValue(); 
     if (id.equals("siteKey")) { 
     Element el = ((Attr) nodes.item(i)).getOwnerElement(); 
     el.removeAttribute(id); 
     } 
    } 

    Transformer transformer; 
    StreamResult result = null; 
    try { 
     transformer = TransformerFactory.newInstance().newTransformer(); 
     transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 
     result = new StreamResult(new StringWriter()); 
     DOMSource source = new DOMSource(doc); 
     transformer.transform(source, result); 
    } catch (TransformerConfigurationException e) { 
     e.printStackTrace(); 
    } catch (TransformerFactoryConfigurationError e) { 
     e.printStackTrace(); 
    } catch (TransformerException e) { 
     e.printStackTrace(); 
    } 
    String xmlString = result.getWriter().toString(); 
    System.out.println(xmlString); 
    } 
}  

Ecco un esempio di XML che voglio trasformare:

https://gist.github.com/2784907

risposta

3

Prova:

for (int i = 0; i < nodes.getLength(); i++) { 
    String id = nodes.item(i).getNodeValue(); 
    if (id.equals("siteKey")) { 
     //doc.removeChild(nodes.item(i)); 
     Element el = ((Attr) nodes.item(i)).getOwnerElement(); 
     el.removeAttribute(id); 
    } 
} 

Sembra che i nodi restituiti dalla query sono staccati dalla documento in modo che getParentNode sia null. - no, non sono distaccati, ho aggiornato il codice.

Ho trovato un article che indica che i nodi restituiti da XPathExpression sono ancora collegati al documento.

Sei codice originale + il cambiamento di cui sopra:

public static void main(String[] args) throws Exception { 

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
    factory.setNamespaceAware(true); 
    Document doc = null; 
    NodeList nodes = null; 
    Set<String> ids = null; 
    try { 
     doc = factory.newDocumentBuilder().parse(new File("d:/a.xml")); 

     XPathExpression expr = XPathFactory.newInstance().newXPath().compile("//@siteKey"); 
     ids = new HashSet<String>(); 
     nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); 
    } catch (SAXException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } catch (ParserConfigurationException e) { 
     e.printStackTrace(); 
    } catch (XPathExpressionException e) { 
     e.printStackTrace(); 
    } 

    for (int i = 0; i < nodes.getLength(); i++) { 
     String id = nodes.item(i).getNodeValue(); 
     if (id.equals("siteKey")) { 
      Element el = ((Attr) nodes.item(i)).getOwnerElement(); 
      el.removeAttribute(id); 
     } 
    } 

    int dupes = 0; 
    for (int i = 0; i < nodes.getLength(); i++) { 
     String id = nodes.item(i).getNodeValue(); 
     if (ids.contains(id)) { 
      System.out.format("%s is duplicate\n\n", id); 
      dupes++; 
     } else { 
      ids.add(id); 
     } 
    } 

    System.out.format("Total ids = %d\n Total Duplicates = %d\n", ids.size(), dupes); 

    Transformer transformer; 
    StreamResult result = null; 
    try { 
     transformer = TransformerFactory.newInstance().newTransformer(); 
     transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 
     result = new StreamResult(new StringWriter()); 
     DOMSource source = new DOMSource(doc); 
     transformer.transform(source, result); 
    } catch (TransformerConfigurationException e) { 
     e.printStackTrace(); 
    } catch (TransformerFactoryConfigurationError e) { 
     e.printStackTrace(); 
    } catch (TransformerException e) { 
     e.printStackTrace(); 
    } 

    String xmlString = result.getWriter().toString(); 
    System.out.println(xmlString); 

} 

Aggiornamento:

for (int i = 0; i < nodes.getLength(); i++) { 
    String id = nodes.item(i).getNodeValue(); 
    Element el = ((Attr) nodes.item(i)).getOwnerElement(); 
    el.removeAttribute(id); 
} 
+0

Questa versione del documento (org.w3c.dom.Document) non sembra avere un metodo removeAttributeByName (String), che è quello che avrei bisogno. – djangofan

+0

@djangofan scusa, non ho prestato abbastanza attenzione. Cerca di ottenere l'elemento e quindi rimuovere gli attributi. – tibtof

+0

Ho provato il tuo suggerimento ma non ha funzionato. Ho aggiornato il mio codice nella mia domanda per riflettere le modifiche. Ti darò un upvote per avermi aiutato. O forse ha funzionato e sto solo stampando l'oggetto sbagliato? Bisogno di ricerca ... – djangofan

0

Ecco il codice finale che ha risolto il problema:

import java.io.File; 
import java.io.IOException; 
import java.io.StringWriter; 
import java.util.HashSet; 
import java.util.Set; 

import javax.xml.parsers.DocumentBuilderFactory; 
import javax.xml.parsers.ParserConfigurationException; 
import javax.xml.transform.OutputKeys; 
import javax.xml.transform.Transformer; 
import javax.xml.transform.TransformerConfigurationException; 
import javax.xml.transform.TransformerException; 
import javax.xml.transform.TransformerFactory; 
import javax.xml.transform.TransformerFactoryConfigurationError; 
import javax.xml.transform.dom.DOMSource; 
import javax.xml.transform.stream.StreamResult; 
import javax.xml.xpath.XPathConstants; 
import javax.xml.xpath.XPathExpression; 
import javax.xml.xpath.XPathExpressionException; 
import javax.xml.xpath.XPathFactory; 

import org.w3c.dom.*; 
import org.xml.sax.SAXException; 


public class StripAttributes { 

    public static void main(String[] args) throws Exception { 

     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
     factory.setNamespaceAware(true); 
     Document doc = null; 
     NodeList nodes = null; 
     Set<String> ids = null; 
     try { 
      doc = factory.newDocumentBuilder().parse(new File("a.xml")); 

      XPathExpression expr = XPathFactory.newInstance().newXPath() 
        .compile("//@siteKey"); 
      ids = new HashSet<String>(); 
      nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); 
     } catch (SAXException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (ParserConfigurationException e) { 
      e.printStackTrace(); 
     } catch (XPathExpressionException e) { 
      e.printStackTrace(); 
     } 

     for (int i = 0; i < nodes.getLength(); i++) { 
      System.out.println("."); //progress indicator 
      Element el = ((Attr) nodes.item(i)).getOwnerElement(); 
      if (el.hasAttribute("siteKey")) el.removeAttribute("siteKey"); 
     } 

     int dupes = 0; 
     for (int i = 0; i < nodes.getLength(); i++) { 
      String id = nodes.item(i).getNodeValue(); 
      if (ids.contains(id)) { 
       System.out.format("%s is duplicate\n\n", id); 
       dupes++; 
      } else { 
       ids.add(id); 
      } 
     } 

     System.out.format("Total ids = %d\n Total Duplicates = %d\n", ids 
       .size(), dupes); 

     Transformer transformer; 
     StreamResult result = null; 
     try { 
      transformer = TransformerFactory.newInstance().newTransformer(); 
      transformer.setOutputProperty(OutputKeys.INDENT, "yes"); 
      result = new StreamResult(new StringWriter()); 
      DOMSource source = new DOMSource(doc); 
      transformer.transform(source, result); 
     } catch (TransformerConfigurationException e) { 
      e.printStackTrace(); 
     } catch (TransformerFactoryConfigurationError e) { 
      e.printStackTrace(); 
     } catch (TransformerException e) { 
      e.printStackTrace(); 
     } 

     String xmlString = result.getWriter().toString(); 
     System.out.println(xmlString); 

    } 
}  

Inoltre, qui è un collegamento a una traduzione Groovy di questo codice:

https://gist.github.com/2789163

1
NamedNodeMap attributes = node.getAttributes(); 
attributes.removeNamedItem(attName); 
Problemi correlati