Escribir XML en Android

Dada una instancia de org.w3c.dom.Document , ¿cómo org.w3c.dom.Document su contenido en un archivo / stream?

EDIT: Como CommonsWare señaló, no hay tal posibilidad de utilizar clases de Android SDK antes de Android 2.2 (API 8). ¿Puede recomendar una biblioteca de terceros para guardar el contenido del Document en un archivo o una secuencia?

Puede escribir xml como todos los demás archivos de texto. Para analizar Documento a cadena que he utilizado:

 public static String getStringFromNode(Node root) throws IOException { StringBuilder result = new StringBuilder(); if (root.getNodeType() == 3) result.append(root.getNodeValue()); else { if (root.getNodeType() != 9) { StringBuffer attrs = new StringBuffer(); for (int k = 0; k < root.getAttributes().getLength(); ++k) { attrs.append(" ").append( root.getAttributes().item(k).getNodeName()).append( "=\"").append( root.getAttributes().item(k).getNodeValue()) .append("\" "); } result.append("<").append(root.getNodeName()).append(" ") .append(attrs).append(">"); } else { result.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); } NodeList nodes = root.getChildNodes(); for (int i = 0, j = nodes.getLength(); i < j; i++) { Node node = nodes.item(i); result.append(getStringFromNode(node)); } if (root.getNodeType() != 9) { result.append("</").append(root.getNodeName()).append(">"); } } return result.toString(); } 

Pero hay una manera más sencilla de hacer esto: http://www.ibm.com/developerworks/opensource/library/x-android/index.html#list11

 private String writeXml(List<Message> messages){ XmlSerializer serializer = Xml.newSerializer(); StringWriter writer = new StringWriter(); try { serializer.setOutput(writer); serializer.startDocument("UTF-8", true); serializer.startTag("", "messages"); serializer.attribute("", "number", String.valueOf(messages.size())); for (Message msg: messages){ serializer.startTag("", "message"); serializer.attribute("", "date", msg.getDate()); serializer.startTag("", "title"); serializer.text(msg.getTitle()); serializer.endTag("", "title"); serializer.startTag("", "url"); serializer.text(msg.getLink().toExternalForm()); serializer.endTag("", "url"); serializer.startTag("", "body"); serializer.text(msg.getDescription()); serializer.endTag("", "body"); serializer.endTag("", "message"); } serializer.endTag("", "messages"); serializer.endDocument(); return writer.toString(); } catch (Exception e) { throw new RuntimeException(e); } } 

Hay un marco muy ligero para leer y escribir XML desde objetos Java anotados. Es totalmente compatible con Android.

http://simple.sourceforge.net

Desde API nivel 8 puede utilizar:

 javax.xml.transform.TransformerFactory factory = new javax.xml.transform.TransformerFactory(); javax.xml.transform.Transformer transformer = factory.newTransformer(); javax.xml.transform.dom.DOMSource domSource = new javax.xml.transform.dom.DOMSource(rootNode); javax.xml.transform.stream.StreamResult result = new javax.xml.transform.stream.StreamResult(outputStream); transformer(domSource, result); 

Aquí hay una solución para el nivel 4 de la API. Requiere una biblioteca externa, sin embargo, la biblioteca no es grande y hace esto mucho más fácil.

He utilizado XOM 1.2.6 y sus paquetes básicos sólo jar archivo.

Código de actividad completo, incluidas las importaciones:

 import java.io.BufferedReader; import java.io.File; import java.io.FileWriter; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Writer; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import nu.xom.converters.DOMConverter; import org.w3c.dom.DOMException; import org.w3c.dom.Document; import org.w3c.dom.DocumentFragment; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import android.app.Activity; import android.os.Bundle; import android.os.Environment; import android.util.Log; public class XOMTestActivity extends Activity { private static final String TAG = "XOMTestActivity"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); try { DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); //Used XOM project.xml file for testing InputStream rawStream = this.getResources().openRawResource(R.raw.project); Document document = docBuilder.parse(rawStream); //API Level 4 will not always return a valid Document for XOM //So, find the root level element manually NodeList nodeList = document.getChildNodes(); Node elementNode = null; for(int i = 0 ; i < nodeList.getLength() ; i++) { Node n = nodeList.item(i); if(n instanceof Element) { elementNode = n; break; } } //assuming there was a root level element DocumentFragment docFragment = document.createDocumentFragment(); docFragment.appendChild(elementNode); nu.xom.Nodes nodes = DOMConverter.convert(docFragment); nu.xom.Document xomDoc = new nu.xom.Document((nu.xom.Element) nodes.get(0)); Log.d(TAG, "onCreate: " + xomDoc.toXML()); String outFile = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "wc3-xom-doc.xml"; Writer writer = new FileWriter(outFile); writer.write(xomDoc.toXML()); writer.close(); } catch(DOMException de) { Log.e(TAG, "onCreate: dom exception: " + de.code, de); } catch(Exception e) { Log.e(TAG, "onCreate: exception", e); } } } 

No es muy largo. Sería bastante más corto para el nivel API 7+ ya que puede omitir todo el trabajo necesario para encontrar el elemento raíz. Apk resultante es 162k por lo que no siento XOM añade mucho peso a un proyecto.

La magia está en DOMConverter .

Me doy cuenta de que Isaac estaba buscando una solución usando el nivel 4 de API, pero para otros que pueden usar un nivel mínimo 8, aquí hay una buena solución basada en lo que radek-k publicó:

StringOutputStream.java:

 import java.io.OutputStream; class StringOutputStream extends OutputStream { private StringBuilder m_string; StringOutputStream() { m_string = new StringBuilder(); } @Override public void write(int b) throws IOException { m_string.append( (char) b ); } @Override public String toString() { return m_string.toString(); } } 

XMLHelper.java:

 import java.util.Properties; 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.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; public class XMLhelper { private static String serializeDocument(Document doc) { String xml = null; try { TransformerFactory factory = TransformerFactory.newInstance(); Transformer transformer = factory.newTransformer(); Properties outFormat = new Properties(); outFormat.setProperty( OutputKeys.INDENT, "yes" ); outFormat.setProperty( OutputKeys.METHOD, "xml" ); outFormat.setProperty( OutputKeys.OMIT_XML_DECLARATION, "no" ); outFormat.setProperty( OutputKeys.VERSION, "1.0" ); outFormat.setProperty( OutputKeys.ENCODING, "UTF-8" ); transformer.setOutputProperties( outFormat ); DOMSource domSource = new DOMSource( doc.getDocumentElement() ); OutputStream output = new StringOutputStream(); StreamResult result = new StreamResult( output ); transformer.transform( domSource, result ); xml = output.toString(); android.util.Log.i( "XMLHELPER", xml ); } catch (TransformerConfigurationException e) { android.util.Log.d( "XMLHELPER", "Exception: " + e ); e.printStackTrace(); } catch (TransformerException e) { android.util.Log.d( "XMLHELPER", "Exception: " + e ); e.printStackTrace(); } return xml; } } 
  • Tema Programáticamente establecido. Cómo volver a cargar Actividad para aplicar
  • Nombre de paquete alias o apodo
  • ¿Por qué SwitchPreference no muestra animación al cambiar de encendido a apagado y viceversa?
  • La elevación no se muestra en la barra de herramientas de los dispositivos pre-pirulí
  • Forma de analizar XML (org.w3c.Document) en Android
  • Ancho del elemento RecyclerView layout_width = "match_parent" no coincide con el padre
  • Recepción de SMS en Android Manifest.xml
  • Cómo detener el evento de clic a través de un fondo semitransparente?
  • ListView dentro de ScrollView con DrawerLayout
  • ¿Cómo hacer Android componentes de auto y utilizarlo de una biblioteca jar?
  • Android: crea automáticamente variables para todos los IDs en xml
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.