Schreiben von XML auf Android

Wie kann ich bei einer Instanz von org.w3c.dom.Document den Inhalt in einer Datei / einem Stream speichern?

Bearbeiten: Wie CommonsWare darauf hingewiesen, gibt es keine solche Möglichkeit mit classn aus Android SDK vor Android 2.2 (API 8). Können Sie dann eine Bibliothek eines Drittanbieters zum Speichern von Document in einer Datei / einem Stream empfehlen?

Sie können XML wie alle anderen Textdateien schreiben. Um das Dokument nach String zu analysieren, benutzte ich:

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

Aber es gibt einen einfacheren Weg, dies zu tun: 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); } } 

Es gibt ein sehr einfaches Framework zum Lesen und Schreiben von XML aus annotierten Java-Objekten. Es ist voll kompatibel mit Android.

http://simple.sourceforge.net

Seit API Level 8 können Sie Folgendes verwenden:

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

Hier ist eine Lösung für API Level 4. Es erfordert eine externe Bibliothek, aber die Bibliothek ist nicht groß und macht es viel einfacher.

Ich habe XOM 1.2.6 und seine corepakete nur JAR-Datei verwendet.

Vollständiger Aktivitätscode einschließlich der Importe:

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

Es ist nicht schrecklich lang. Bei API-Stufe 7+ wäre es ein wenig kürzer, da Sie alle Arbeiten überspringen können, die für die Suche nach dem Stammelement erforderlich sind. Resultierendes apk ist 162k, also fühle ich nicht XOM fügt viel Gewicht zu einem Projekt hinzu.

Die Magie ist in DOMConverter .

Ich weiß, dass Isaac nach einer Lösung gesucht hat, die API Level 4 verwendet, aber für andere, die ein Minimum Level 8 verwenden können, ist hier eine nette Lösung basierend auf dem, was radek-k gepostet hat:

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