Escribir XML en Android

Dada una instancia de org.w3c.dom.Document , ¿cómo org.w3c.dom.Document sus contenidos en un archivo / secuencia?

EDITAR: Como señaló CommonsWare, no existe la posibilidad de utilizar clases de Android SDK anteriores a Android 2.2 (API 8). ¿Puede recomendar entonces una biblioteca de terceros para guardar los contenidos del Document en un archivo / secuencia?

Puede escribir xml como todos los demás archivos de texto. Para analizar el documento en la cadena que utilicé:

 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(""); } 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(""); } } return result.toString(); } 

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

 private String writeXml(List 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); } } 

Existe un marco muy liviano para leer y escribir XML a partir de objetos Java anotados. Es totalmente compatible con Android.

http://simple.sourceforge.net

Desde API nivel 8 puedes usar:

 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 API Nivel 4. Requiere una biblioteca externa, sin embargo, la biblioteca no es grande y lo hace mucho más fácil.

Usé XOM 1.2.6 y sus paquetes principales solo archivo jar.

Código de actividad completa que incluye 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 terriblemente largo. Sería un poco más corto para API nivel 7+ ya que puede omitir todo el trabajo requerido para encontrar el elemento raíz. La aplicación resultante es 162k, así que no creo que XOM agregue mucho peso a un proyecto.

La magia está en DOMConverter .

Me doy cuenta de que Isaac estaba buscando una solución con API nivel 4, pero para otros que pueden usar un nivel mínimo de 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; } }