2012-05-24 15 views
7

Estoy tratando de usar Java para eliminar todos los atributos xml de un archivo XML que coincida con un nombre de atributo. Estoy atascado en este punto. En la parte inferior de este código, puedo obtener el valor del atributo de cada nodo a medida que avanzo, pero no puedo entender cómo eliminar el atributo del Nodo por completo. ¿Algunas ideas?¿Usar Java para eliminar todos los atributos xml de un archivo XML que coincida con un nombre de atributo?

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

Este es un ejemplo del XML Quiero transformar:

https://gist.github.com/2784907

Respuesta

3

Probar:

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

Parece que los nodos devueltos por la consulta se separan de la documento para que getParentNode sea nulo. - No, no están desacoplados, actualicé el código.

Encontré un article que dice que los nodos devueltos por XPathExpression todavía están adjuntos al documento.

Eres código original + el cambio anterior:

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

} 

Actualización:

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

Esta versión del documento (org.w3c.dom.Document) no parecen tener un método removeAttributeByName (Cadena), que es lo que iba a necesitar. – djangofan

+0

@djangofan lo siento, no presté suficiente atención. Intenta obtener el elemento y luego elimina los atributos. – tibtof

+0

Intenté su sugerencia pero no funcionó del todo. Actualicé mi código en mi pregunta para reflejar los cambios. Te daré un voto positivo por ayudarme. ¿O tal vez funcionó y solo estoy imprimiendo el objeto equivocado? Necesito investigar ... – djangofan

0

Este es el código final que resuelve el 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); 

    } 
}  

Además, aquí es un enlace a una traducción de Groovy de este código:

https://gist.github.com/2789163

1
NamedNodeMap attributes = node.getAttributes(); 
attributes.removeNamedItem(attName); 
Cuestiones relacionadas