Creating Applications with Mozilla-Chapter 10. RDF, RDF Tools, and the Content Model-P4

Chia sẻ: Thanh Cong | Ngày: | Loại File: PDF | Số trang:19

0
52
lượt xem
6
download

Creating Applications with Mozilla-Chapter 10. RDF, RDF Tools, and the Content Model-P4

Mô tả tài liệu
  Download Vui lòng tải xuống để xem tài liệu đầy đủ

Tham khảo tài liệu 'creating applications with mozilla-chapter 10. rdf, rdf tools, and the content model-p4', công nghệ thông tin, quản trị web phục vụ nhu cầu học tập, nghiên cứu và làm việc hiệu quả

Chủ đề:
Lưu

Nội dung Text: Creating Applications with Mozilla-Chapter 10. RDF, RDF Tools, and the Content Model-P4

  1. Chapter 10. RDF, RDF Tools, and the Content Model-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
  2. 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);
  3. 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
  4. 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 and the 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
  5. 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) ;
  6. 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');
  7. 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);
  8. // 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 the RDF interfaces, this one allows you to traverse and retrieve any part of the RDF 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
  9. something interesting and useful. The parseString function allows you to feed nsIRDFXMLParser a string and have it parse that data as RDF and 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 = '
  10. 'xmlns:b="http://books.mozdev.org/rdf#">' + '' + // 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 the RDF in case of relative links. nsIRDFXMLParser uses nsIRDFXMLSink for event handling. The interfaces are totally separate, but 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 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) {
  11. doneLoading( ); // A function that does something with the 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 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'; s = Components.classes[serializer].
  12. createInstance(Components.interfaces.nsIRDFXMLSeria lizer); s.init(datasource); output = new Object( ); output.write = new function(buf,count) { alert(buf); // Show the serialized syntax return count; } s.QueryInterface(Components.interfaces.nsIRDFXMLSou rce).Serialize(output); As in the previous example with nsIRDFXMLParser, Example 10-10 does not use RDF data from a file. The serialized data is passed directly to an alert, which then displays the generated RDF. Notes [1] A vector, for those who don't know, is a flexible and more accessible version of the array data structure. 10.4. Template Dynamics Once you learn how to create templates and modify datasources, the ultimate in template mastery is to apply datasources to a template dynamically. This process is done through the database property of a XUL element that contains a template. The object returned by this property has only two
  13. methods, AddDataSource and RemoveDataSource. A separate builder.rebuild function is also available for refreshing the template's display, but you probably won't need it once the template automatically updates itself. The addition and removal of a datasource to a template is demonstrated here: tree = document.getElementById('tree-template'); tree.database.AddDataSource(someDatasource); // tree 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 to aggregate data from different places, such as contact data, work information, and computer hardware information (e.g., "Eric uses a Compaq with the serial number 1223456-1091 to write his book and he sits on the fourth floor of the Acme Building, which is the Bay Area branch of Acme Enterprises.) 10.4.1. Template Dynamics in XBL
  14. Putting templates inside XBL can be a useful organizational scheme. Here is a basic implementation of a widget that creates a list of people based on names listed in an attribute: 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
  15. // Initialize the RDF Service rdf = Components .classes['@mozilla.org/rdf/rdf- service;1'] .getService(Components.interfaces.nsIRDFService); // Initialize a Datasource in Memory inMemory = '@mozilla.org/rdf/datasource;1?name=in-memory- datasource'; datasource = Components.classes[inMemory]. 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 the RDF graph datasource.Assert (root,
  16. rdf.GetResource('http://www.mozdev.org/rdf#people') , people,true); // Initialize Methods needed for Containers rdfc = Components .classes['@mozilla.org/rdf/container- utils;1'] .getService(Components.interfaces.nsIRDFContainerUt ils); // For the People resource, make a Sequence of people peopleSequence = rdfc.MakeSeq(datasource, people); for(i=0;i
  17. rdf.GetResource('http://www.mozdev.org/rdf#name'), rdf.GetLiteral(namesArray[i]),true); peopleSequence.AppendElement(person); } list = document.getAnonymousNodes(this)[1]; list.database.AddDataSource(datasource); ]]>
Đồng bộ tài khoản