在Android上编写XML

时间:2010-02-18 18:02:21

标签: xml android serialization

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

编辑: 正如CommonsWare所指出的那样,在Android 2.2(API 8)之前使用Android SDK的类没有这种可能性。您能否建议使用第三方库将Document内容保存到文件/流?

5 个答案:

答案 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完全兼容。

http://simple.sourceforge.net

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