Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 19 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
19
Dung lượng
34,43 KB
Nội dung
Chapter 10.RDF,RDFTools,andtheContentModel-P4
When you create RDF statements with assertions or work with in-memory
datasources, it is often difficult to remember the shape of the graph, which
statements exist about which resources, or which objects are attached to
which subjects. These "getter" methods can help you verify the shape of
your graph.
10.3.6. nsIRDFRemoteDataSource
The Section 10.3.3
section (earlier in this chapter) showed how to load a
datasource from a remote server simply. If you want control over that
datasource, you can manage it by using the nsIRDFRemoteDatasource to set
up a remote datasource:
xml = '@mozilla.org/rdf/datasource;1?name=xml-
datasource';
datasource = Components.classes[xml].
createInstance(Components.interfaces.nsIRDFRemoteDa
taSource);
datasource.Init('http://books.mozdev.org/file.rdf')
;
datasource.Refresh(false);
In this example, the Init and Refresh methods control the datasource on
the server. In addition to these methods, you can call the Flush method to
flush the data that's been changed and reload, or you can check whether the
datasource is loaded by using the loaded property:
if (datasource.loaded) {
// Do something
}
Built-in datasources that implement nsIRDFRemoteDataSource (and other
necessary interfaces) and do their own data handling include:
@mozilla.org/rdf/datasource;1?name=history
@mozilla.org/browser/bookmarks-service;1
@mozilla.org/autocompleteSession;1?type=history
@mozilla.org/browser/global-history;1
@mozilla.org/rdf/datasource;1?name=bookmarks
10.3.7. nsIRDFPurgeableDataSource
Using the nsIRDFPurgeableDatasource interface allows you to delete a
whole section of an existing in-memory datasource in one fell swoop. This
means that all relatives all statements derived from that node are
removed. When you work with large in-memory datasources (such as email
systems), the using interface can manipulate the data efficiently. The
Sweep( ) method can delete a section that is marked in the datasource.
datasource.
QueryInterface(Components.interfaces.nsIRDFPurgeabl
eDataSource);
rootSubject = RDF.GetResource('urn:root');
predicate =
RDF.GetResource('http://books.mozdev.org/rdf#chapte
rs');
object = RDF.GetResource('Chapter1');
datasource.Mark(rootSubject,predicate,object,true);
datasource.Sweep( );
In this instance, a statement about a chapter in a book is marked and then
removed from the datasource. You can also mark more than one node before
sweeping.
10.3.8. nsIRDFNode, nsIRDFResource, and nsIRDFLiteral
These types of objects come from only a few different places. Here are all
the functions that can return the resource of a literal:
nsIRDFService.GetResource
nsIRDFService.GetAnonymousResource
nsIRDFService.GetLiteral
nsIRDFDataSource.GetSource
nsIRDFDataSource.GetTarget
nsIRDFNode is the parent of nsIRDFResource and nsIRDFLiteral. It is not
used often because it's sole function is to test equality:
isEqual = resource1.EqualsNode(resource2);
The other two interfaces inherit this function automatically. EqualsNode
tests the equivalency of two resources, which can be useful when you try to
put together different statements (e.g., "Eric wrote a book" and "[This] book
is about XML") and want to verify that a resource like "book" is the same in
both cases.
10.3.8.1. nsIRDFResource
Like nsIRDFNode, nsIRDFResource is a minimalist interface. Here are the
functions andthe property available in a resource from the nsIRDFResource
interface:
resource = RDF.GetAnonymousResource( );
// get the resource value, something like
'rdf:#$44RG7'
resourceIdentifierString = resource.Value;
// compare the resource to an identifier
isTrue =
resourceEqualsString(resourceIdentifierString);
// Give the resource a real name.
resource.Init('Eric');
10.3.8.2. nsIRDFLiteral
A literal's value can be read but not written. To change the value of a literal,
make a new literal and set it properly:
aValue = literal.Value;
Note that aValue could be a string or an integer in this case. The base type
conversion, based on the data's format, is done automatically.
10.3.9. nsIRDFContainerUtils
This interface facilitates the creation of containers and provides other
container-related functions. It provides functions that make and work with a
sequence, bag, and alternative. (The functions work the same way
for all types of containers, so only sequence is covered here.) To create an
instance of nsIRDFContainerUtils, use the following:
containerUtils =
Components.classes['@mozilla.org/rdf/container-
utils;1'].
getService(Components.interfaces.nsIRDFContainerUti
ls);
Once you create an anonymous resource, you can create a sequence from it.
Then you can test the type of the container and see whether it's empty:
// create an anonymous resource
anonResource = RDF.GetAnonymousResource( );
// create a sequence from that resource
aSequence =
containerUtils.MakeSeq(datasource,anonResource);
// test the resource
// (all of these are true)
isContainer =
containerUtils.isContainer(datasource,anonResource)
;
isSequence =
containerUtils.isSequence(datasource,anonResource);
isEmpty =
containerUtils.isEmpty(datasource,anonResource);
Note that the sequence object is not passed into the functions performing the
test in the previous example; the resource containing the sequence is passed
in. Although aSequence and anonResource are basically the same
resource, their data types are different. isContainer, isSequence, and
isEmpty can be used more easily with other RDF functions when a
resource is used as a parameter:
object =
datasource.GetTarget(subject,predicate,true);
if(RDF.isAnonymousResource(object))
{
isSeq = containerUtils.IsSeq(datasource,object);
}
The RDF container utilities also provide an indexing function. indexOf is
useful for checking if an element exists in a container resource:
indexNumber =
containerUtils.indexOf(datasource,object,RDF.GetLit
eral('Eric'));
if(index != -1)
alert('Eric exists in this container');
10.3.10. nsIRDFContainer
This interface provides vector-like access to an RDF container's elements.[1]
The nsIRDFContainer interface allows you to add, look up, and remove
elements from a container once you create it.
10.3.10.1. Adding an element to a container
You can add an element to a container in two ways. You can append it to the
end of the list with Append or insert it at a specific place in the container:
newLiteral = RDF.GetLiteral('Ian');
aSequence.AppendElement(newLiteral);
// or
aSequence.InsertElementAt(newLiteral,3,true);
The second attribute in InsertElementAt is where the element should
be placed. The third attribute specifies that the list can be reordered. This
method is useful for working with ordered containers such as sequences. If
this locking parameter is set to false and an element already exists at that
location, then the existing element is overwritten.
10.3.10.2. Removing an element from a container
Removing an element from a container works much the same as adding one.
The difference is that a reordering attribute is included on
RemoveElement. If this attribute is set to false, you may have holes in the
container, which can create problems when enumerating or indexing
elements within.
newLiteral = RDF.GetLiteral('Ian');
aSequence.RemoveElement(newLiteral,true);
// or
aSequence.RemoveElementAt(newLiteral,3,true);
If you use the indexOf property of nsIRDFContainer, you can also
use GetCount to learn how many elements are in the container. The count
starts at 0 when the container is initialized:
numberOfElements = aSequence.GetCount( );
Once you have the sequence, the datasource and resource the sequence
resides in can be retrieved. In effect, these properties look outward instead of
toward the data:
seqDatasource = aSequence.DataSource;
seqResource = aSequence.Resource;
Like many methods in theRDF interfaces, this one allows you to traverse
and retrieve any part of theRDF graph.
10.3.11. nsIRDFXML Interfaces
The RDF/XML interfaces are covered only briefly here. Besides being
abstract and confusing, these interfaces require a lot of error handling to
work correctly. Fortunately, a library on mozdev.org called JSLib handles
RDF file access. The JSLib XML library does the dirty work in a friendly
manner. See the section Section 10.5
, later in this chapter, for more
information.
10.3.11.1. nsIRDFXMLParser and nsIRDFXMLSink
nsIRDFXML is the raw RDF/XML parser of Mozilla. Used by Mozilla, its
main purpose is to parse an RDF file asynchronously as a stream listener.
Though this subject is beyond the scope of this book, the interface provides
something interesting and useful. The parseString function allows you
to feed nsIRDFXMLParser a string and have it parse that data as RDFand
put it into a datasource, as Example 10-9
demonstrates.
Example 10-9. Parse an RDF/XML string into a datasource
RDF = Components.classes['@mozilla.org/rdf/rdf-
service;1'].
getService(Components.interfaces.nsIRDFService);
// Used to create a URI below
ios = Components.classes["@mozilla.org/network/io-
service;1"].
getService(Components.interfaces.nsIIOService);
xmlParser = '@mozilla.org/rdf/xml-parser;1';
parser = Components.classes[xmlParser].
createInstance(Components.interfaces.nsIRDFXMLParse
r);
uri = ios.newURI("http://books.mozdev.org/rdf#",
null);
// Entire RDF File stored in a string
rdfString =
'<rdf:RDF xmlns:rdf=http://www.w3.org/1999/02/22-
rdf-syntax-ns#' +
'xmlns:b="http://books.mozdev.org/rdf#">' +
'<rdf:Description about="urn:root">' + // Rest of
file
parser.parseString(datasource,uri,rdfString);
// Parsed string data now resides in the datasource
The RDF/XML data that was in the string is a part of the datasource and
ready for use (just like any other RDF data in a datasource). The uri acts as
a base reference for theRDF in case of relative links.
nsIRDFXMLParser uses nsIRDFXMLSink for event handling. The interfaces
are totally separate, but behind the scenes, they work together withthe
incoming data. Example 10-10
shows how a series of events is created in an
object and then used to handle parser events.
Example 10-10. Setup nsIRDFXMLSink with event handlers
var Observer = {
onBeginLoad: function(aSink)
{
alert("Beginning to load the RDF/XML ");
},
onInterrupt: function(aSink) {},
onResume: function(aSink) {},
onEndLoad: function(aSink)
{
[...]... handlers that manipulate the data as it appears 10.3 .11.2 nsIRDFXMLSerializer and nsIRDFXMLSource These two interfaces are meant to work together nsIRDFXMLSerializer lets you init a datasource into the xml-serializer module that outputs RDF However, nsIRDFXMLSource actually contains the Serialize function Here's how to serialize a datasource into an alert: serializer = '@mozilla.org /rdf/ xml-serializer;1';... createInstance(Components.interfaces.nsIRDFDataSour ce); // Create the Root Node and an Anonymous Resource to Start With root = rdf. GetResource('urn:root'); people = rdf. GetAnonymousResource( ); // Insert the People resource into theRDF graph datasource.Assert (root, rdf. GetResource('http://www.mozdev.org /rdf# people') , people,true); // Initialize Methods needed for Containers rdfc = Components classes['@mozilla.org /rdf/ containerutils;1']... something withthe datasource }, onError: function(aSink, aStatus, aErrorMsg) { alert("Error: " + aErrorMsg); } }; Once the event handlers are set up, you can use nsIRDFXMLSink: sink = datasource.QueryInterface(Components.interfaces.nsI RDFXMLSink); sink.addXMLSinkObserver(observer); The events are then triggered automatically when the datasource is loaded up with data, allowing you to create handlers... getService(Components.interfaces.nsIRDFContainerUt ils); // For the People resource, make a Sequence of people peopleSequence = rdfc.MakeSeq(datasource, people); for(i=0;i Obviously, the comma is used as the delimiter for this list The constructor element in Example 10-11 uses JavaScript to break up this string Example 10-11 Binding with in-memory datasource and template ... will now update its display to show contents tree.database.RemoveDataSource(someDatasource); // tree will now be empty // Optional, use only when tree is not updating for some reason tree.builder.rebuild( ); You can add and remove any datasource as long as the template actually matches the data inside it Also, multiple datasources can be applied to the same template with no problems, which allows you . Chapter 10. RDF, RDF Tools, and the Content Model-P4
When you create RDF statements with assertions or work with in-memory
datasources,. behind the scenes, they work together with the
incoming data. Example 10- 10
shows how a series of events is created in an
object and then used to handle