Una xml-datasource può essere salvata in un file dopo le modifiche fatte. Infatti, RDF/XML caricato da un URL di un file tende ad essere automaticamente salvato sul disco quando la stessa datasource non è più usata. Nnon dovresti affidarti a questo comportamento, comunque, perché il salvataggio non funziona in maniera affidabile se la datasource è ancora in uso quando viene chiuso Mozilla. Perciò dovresti sempre salvare la datasource se ne hai bisogno.
Non ti preoccupare del salvataggio automatico che avverrà comunque in seguito. La datasource sarà salvata solo se sono stati fatti dei cambiamenti, perciò un salvataggio manuale seguito da un salvataggio automatico provocherà soltanto un salvataggio della stessa datasource. Questo significa anche che il salvataggio manuale non fa niente se la datasource non è cambiata.
Per salvare un file RDF/XML, usa il metodo Flush dell'interfaccia nsIRDFRemoteDataSource.
Questo metodo salverà le modifiche a RDF/XML nel file da cui
è stato caricato. Solo i files caricati da URL file possono
essere salvati in questo modo. I files remoti e i files caricati da URL
chrome non possono essere salvati.
var ds=rdfService.GetDataSourceBlocking("file:///main/animals.rdf");
var subject = rdfService.GetResource("http://www.some-fictitious-zoo.com/crustaceans");
var predicate = rdfService.GetResource("http://www.some-fictitious-zoo.com/rdf#name");
var name = rdfService.GetLiteral("Crustaceans");
ds.Assert(subject, predicate, name, true);
ds.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
ds.Flush();
Questo esempio carica un file RDF/XML, aggiunge una dichiarazione al file, e salva di nuovo il file sul disco. Dato che RDF non è ordinato, il file salvato apparirà probabilmente piuttosto diverso da come era all'inizio.
Un secondo metodo FlushTo può salvare una datasource in uno specifico URL. Come per il metodo Flush attualmente possono essere salvati solo URL di tipo file. In futuro, altri tipi di URL possono essere supportati per il salvataggio. Comunque, è possibile salvare da qualunque tipo di URI. Questo significa che anche se puoi salvare solo da URL di tipo file, il metodo FlushTo può salvare una datasource che può essere caricata da un'altra sorgente. Il metodo FlushTo prende un argomento, l'URL in cui salvare. Non modifica la datasource originale, né il suo URL e scrive soltanto una versione serializzata dei dati in forma RDF/XML. Dal momento che scrive su un altro file, puoi usare il metodo FlushTo anche se non hai modificato la datasource.
L'esempio sopra carica una datasource e la salva su un altro file.
var ds=rdfService.GetDataSourceBlocking("file:///main/animals.rdf");
ds.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
ds.FlushTo("file:///main/more-animals.rdf");
Nota che solo la xml-datasource supporta il tipo di salvataggio descritto sopra. Per altri tipi di datasource, puoi aver bisogno di serializzare i dati in una stringa. Quindi puoi salvare la stringa in un file usando le interfacce file di Mozilla. Puoi anche serializzare una xml-datasource in una stringa, per esempio, se vuoi mostrare l'RDF/XML all'utente.
Serializzare in una stringa richiede due interfacce e un componente
serializzatore. Questo componente è il reciproco del parser RDF
usato per parserizzare RDF. Il serializzatore implementa due
interfacce, nsIRDFXMLSource e nsIRDFXMLSerializer.
La prima è usate per inizializzare il serializzatore con una
datasource in cui scrivere, mentre il secondo è usato per
effettuare la conversione. Se si sta usando l'xml-datasource, la prima parte è gestita per te e ti basta chiamare il metodo Serialize. L'xml-datasource implementa l'interfaccia nsIRDFXMLSerializer direttamente, perciò scrivere queste datasource richiede meno passaggi.
Il metodo Serialize è usaato per scrivere dati RDF/XML in uno stream. Non scrive direttamente in una stringa (invece non dobbiamo creare un unvolucro intorno alla stringa per scrivere in una stringa). Naturalmente, se vuoi scrivere in uno stream non hai bisogno di questo. Lo stream dovrebbe implementare l'interfaccia nsIOutputStream.
E' piuttosto semplice implementare uno stream di output. Ci sono solo quattro metodi e solo uno, write, deve fare tutto. Questo metodo verrà chiamato per scrivere nello stream i dati serializzati. Non verrà inviato in una volta sola, così puoi usarlo per scritture asimmetriche che non bloccano l'interfaccia utente.
var outputStream = {
data: "",
close : function(){},
flush : function(){},
write : function (buffer,count){
this.data += buffer;
return count;
},
writeFrom : function (stream,count){},
isNonBlocking: false
}
ds.QueryInterface(Components.interfaces.nsIRDFXMLSource);
ds.Serialize(outputStream);
Nell'esempio sopra, creiamo un oggetto stream output. Il ponte XPConnect che connette XPCOM e JavaScript è capace di convertire questo in una implementazione dell'interfaccia nsIOutputStream semplicemente perché inomi dei metodi coincidono. Il metodo write prende due argomenti, il buffer di dati e la lunghezza del buffer. Noi aggiungiamo semplicemente i contenuti del buffer in coda ad una proprietà data, che non è parte dell'interfaccia nsIOutputStream. Appena la serializzazione è completa, la proprietà data conterrà la stringa RDF/XML serializzata.
Nell'esempio sopra, chiamiamo il metodo Serialize direttamente su una datasource, dopo aver chiamato QueryInterface per dirigerlo all'interfaccia corretta. Questo funziona bene pre le datasource XML/RDF, visto che sanno come farlo. Per le altre datasource, devi creare prima un serializzatore, come nell'esempio che segue.
var serializer=Components.classes["@mozilla.org/rdf/xml-serializer;1"]
.createInstance(Components.interfaces.nsIRDFXMLSerializer);
serializer.init(ds);
serializer.QueryInterface(Components.interfaces.nsIRDFXMLSource);
serializer.Serialize(outputStream);
Il serializzatore è creato e inizializzato con la datasource chiamando il metodo init. Quindi, chiamiamo il metodo Serialize direttamente sul serializzatore dopo averlo diretto. Quasi tutte le datasource possono essere serializzate in questo modo. Non puoi serializzare una composite-datasource, devi serializzare separatamente ogni datasource che contiene.
Quando serializzi, gli spazi di nomi e i prefissi verranno
determinati automaticamente. Il serializzatore usa un meccanismo
piuttosto semplice in cui assume che l'ultimo cancelletto (#) o slash
(/) siano separatori tra la parte riguardante lo spazio di nomi e la
parte del valore. Per esempio http://www.xulplanet.com/rdf/people/name avrà uno spazio di nomi 'http://www.xulplanet.com/rdf/people/'
e un valore predicato 'name'. Il serializzatore creerà un
prefisso da usare. Il comportamento può sembrare inusuale e non
funzionerà se i predicati non seguono questa convenzione. Per
fortuna, il serializzatore ha un mezzo per controllare gli spazi di
nomi usati.
Il serializzatore ha un metodo addNameSpace che può essere usato per associare un prefisso con l'URI dello spazio di nomi. Nella serializzazione, la lista di spazi di nomi aggiunti è usata nella conversione dei predicati a spazi di nomi e valori. Il metodo addNameSpace ha bisogno di due argomenti, il prefisso e l'URI dello spazio di nomi. Anche se l'URI dello spazio di nomi è una stringa, il prefisso è un oggetto atom invece. Un atom è semplicemente na stringa che è tenuta in cache con una chiave ed è semplice da confrontare. E' piuttosto simile a un letterale RDF nello scopo, anche se gli atom sono costruiti nella libreria XPCOM che è comoda per le applicazioni basate su Mozilla che non usano RDF. Mozilla usa atoms internamente per gestire spazi di nomi, così che gli elementi e gli attributi possono essere comparati velocemente. Per creare un atom, ti basta usare il servizio atom.
var atomService = Components.classes["@mozilla.org/atom-service;1"]
.createInstance(Components.interfaces.nsIAtomService);
var prefix = atomService.getAtom("people");
ser.addNameSpace(prefix,"http://www.xulplanet.com/rdf/people/");
Nell'esempio, il metodo getAtom del servizio atom è usato per avere referenze atom. Il servizio atom implementa nsIAtomService e gli atom implementano l'interfaccia nsIAtom. Il metodo addNameSpace è usato per aggiungere il prefisso 'people' allo spazio di nomi 'http://www.xulplanet.com/rdf/people/'. Quando si serializza una datasource RDF, qualsiasi predicato inizi con questo spazio di nomi verrà serializzato usando il prefisso dello spazio di nomi 'people'. Nota che lo spazio di nomi 'RDF' è già aggiunto al serializzatore perciò non dovrai aggiungerlo manualmente.