给定org.w3c.dom.Document
的实例,如何将其内容保存到文件/流?
编辑:
正如CommonsWare所指出的那样,在Android 2.2(API 8)之前使用Android SDK的类没有这种可能性。您能否建议使用第三方库将Document
内容保存到文件/流?
答案 0 :(得分:39)
您可以像所有其他文本文件一样编写xml。 要将Document解析为我使用过的字符串:
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);
}
}
答案 1 :(得分:20)
有一个非常轻量级的框架,用于从带注释的Java对象中读取和编写XML。它与Android完全兼容。
答案 2 :(得分:16)
从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);
答案 3 :(得分:10)
这是API Level 4的解决方案。它需要一个外部库,但是,库并不大,这使得它更容易。
我使用XOM 1.2.6,其核心包仅使用jar文件。
完整活动代码,包括导入:
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
。
答案 4 :(得分:7)
我意识到Isaac正在寻找使用API级别4的解决方案,但对于其他可以使用最低级别8的解决方案,这里有一个很好的解决方案,基于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;
}
}