在Android上编写XML

给定一个org.w3c.dom.Document的实例,如何将其内容保存到文件/stream?

编辑:正如CommonsWare所指出的那样,在Android 2.2(API 8)之前没有使用Android SDK的类的可能性。 你可以推荐一个第三方库来保存Document内容到文件/stream?

您可以像所有其他文本文件一样编写xml。 为了parsing文档到string我使用:

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

但是有一个更简单的方法可以做到这一点: 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); } } 

从注释的Java对象读取和写入XML有一个非常轻量级的框架。 它完全兼容Android。

http://simple.sourceforge.net

由于API级别8,您可以使用:

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

这是API级别4的解决scheme。它需要一个外部库,但是,库不是很大,这使得这更容易。

我用XOM 1.2.6和它的核心软件包只有jar文件。

完整的活动代码包括import:

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

这不是很长。 由于您可以跳过查找根元素所需的全部工作,因此对于API级别7+而言,这会相当短一些。 结果apk是162k,所以我不觉得XOM增加了很多项目的重量。

神奇的是在DOMConverter

我意识到Isaac正在寻找一个使用API​​级别4的解决scheme,但是对于可以使用最低级别8的其他人来说,这是一个很好的解决scheme,基于radek-k发布的内容:

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