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?
- Android Spinner Dropdown flecha que no se muestra
- Error: (218) Apóstrofo no precedido por \
- Cómo crear una tabla dinámica de datos en android?
- Círculo transparente con borde
- Abrir archivo XML desde res / xml en Android
- Fuera de error de memoria al inflar el diseño xml simple en android
- Edición de Android Dibujo de rutas largas en MapView mediante análisis XML
- Cómo llamar a los colores de los recursos de forma dinámica en Android?
- Permiten a los usuarios crear formularios dentro de la aplicación android survey / data collection
- CollapsingToolbarLayout | Problemas de desplazamiento y diseño 2
- Android: Múltiples vistas de los niños para una vista personalizada con un diseño existente
- Disposición de teclado personalizada de Android dejando un margen de blanco en el lateral
- Exhibición de la secuencia de la Cadena de Android Signo de porcentaje
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.
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; } }
- WebView no procesa la página HTML local en el lanzamiento de la aplicación en Android 4.0.x Ice Cream Sandwich
- SDK de Android Facebook: comprueba si el usuario está conectado o no