web-dev-qa-db-fra.com

Écriture de XML sur Android

Étant donné une instance de org.w3c.dom.Document, comment enregistrer son contenu dans un fichier/flux?

EDIT: Comme CommonsWare l'a souligné, il n'y a pas une telle possibilité en utilisant des classes de Android SDK avant Android 2.2 (API 8). Pouvez-vous recommander ensuite un troisième- bibliothèque de partie pour enregistrer le contenu de Document dans un fichier/flux?

35
Marek Stój

Vous pouvez écrire du xml comme tous les autres fichiers texte. Pour analyser le document dans la chaîne que j'ai utilisée:

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

Mais il existe un moyen plus simple de le faire: 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);
    } 
}
39
Dmytro

Il existe un cadre très léger pour lire et écrire du XML à partir d'objets annotés Java. Il est entièrement compatible avec Android.

http://simple.sourceforge.net

20
ng.

Depuis l'API niveau 8, vous pouvez utiliser:

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

Voici une solution pour l'API de niveau 4. Elle nécessite une bibliothèque externe, cependant, la bibliothèque n'est pas grande et rend cela beaucoup plus facile.

J'ai utilisé XOM 1.2.6 et ses packages principaux ne contiennent que le fichier jar.

Code d'activité complet, y compris les importations:

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

    }
}

Ce n'est pas terriblement long. Ce serait un peu plus court pour l'API de niveau 7+, car vous pouvez ignorer tout le travail requis pour trouver l'élément racine. L'APK résultante est de 162k, donc je ne pense pas que XOM ajoute beaucoup de poids à un projet.

La magie est dans DOMConverter .

10
Rich Schuler

Je me rends compte qu'Isaac cherchait une solution utilisant l'API niveau 4, mais pour ceux qui peuvent utiliser un niveau minimum 8, voici une belle solution basée sur ce que radek-k a posté:

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