org.w3c.dom.Document
のインスタンスが与えられた場合、その内容をファイル/ストリームに保存するにはどうすればよいですか?
編集:CommonsWareが指摘したように、Android 2.2(API 8)より前のAndroid SDKのクラスを使用する可能性はありません。 Document
のコンテンツをファイル/ストリームに保存するためのサードパーティライブラリをお勧めできますか?
他のすべてのテキストファイルと同様に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();
}
しかし、これを行うもう1つの簡単な方法があります。 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と完全に互換性があります。
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のソリューションを次に示します。外部ライブラリが必要ですが、ライブラリは大きくなく、これは非常に簡単です。
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
にあります。
IsaacはAPIレベル4を使用したソリューションを探していましたが、最小レベル8を使用できる他のユーザー向けに、radek-kが投稿したものに基づいたNiceソリューションがあります。
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;
}
}