Firefox Hacks [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Firefox Hacks [Electronic resources] - نسخه متنی

Nigel McFarlane

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید






Hack 70. Work with RDF Facts

Make Firefox act like a small database server
that is smart about RDF data.

The W3C's Resource Description
Framework (RDF) standard is one of the more complex XML standards.
RDF
is an application of XML, but it makes little use of the XML tag
hierarchy. Instead, it turns any specified tags into
facts. Facts are stored in memory separate from
the DOM tree of the RDF content. This hack shows how to use facts.
Firefox has both scripting and direct XML support for facts.

What is Firefox RDF good for? It's a very general
mechanism for managing any kind of data, whether that data fits in an
XML hierarchy or not. The output of an SQL query is an obvious
example.


6.14.1. Learn RDF


If you are new to RDF, be selective about the material you lean on.
Much RDF literature is not suited for beginners. The book
Rapid Application Development with Mozilla
(Prentice Hall PTR) is one source of a digestible tutorial. An
alternate approach is to learn a little Prolog.
RDF
and Prolog are both examples of propositional
calculus (a field of mathematical logic). On top of
these ideas, you also need a bit of experience scripting Mozilla
XPCOM components.

Very briefly, RDF is a more general way of representing data than
relational tables. RDF is concerned with making statements about
things. Each statement is comprised of three
pieces of information: the thing we're making the
statement about, a property of the thing, and
the value of that property. In RDF parlance,
this is called a triple, and the thing,
property, and values are called subject,
predicate, and object,
respectively. For Example, Firefox Hacks (the
thing) has an author (the property) of Nigel
McFarlane (the value).

To compare RDF with SQL, here's
an example of two SQL tables that have one record each. They might
look like this, with data shown in plain type and schema information
in bold:

table employee:
empid name jobcode
----- ------ -------
2 Fred 33
table department:
depid name manager
----- ------ -------
3 sales 2

RDF requires that all information be stated as facts. Look at the
standard (or chrome) .rdf examples for a first
glimpse. Here's a shorthand (one of several) for the
facts covering the above two tables:

<- employee, empid, 2 ->
<- 2, name, Fred ->
<- 2, jobcode, 33 ->
<- department, depid, 3 ->
<- 3, name, sales ->
<- 3, manager, 2 ->

That's six facts, with the first one reading
"employee has a property
empid with value
2." Each fact must have three
parts (obscurely named subject,
predicate, and object).
That provides regularity and makes it possible for processing systems
to act in a general way. A set of facts are lumped together into a
fact store. No tables are required.
Here's a sample RDF document for these facts:

<?xml version="1.0"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<Description about="urn:example:employee">
<empid
resource="urn:example:key:2
">
</Description> <!-- one fact -->
<Description about="urn:example:key:2
name
="Fred"
jobcode="33"/> <!-- two facts -->
<Description about="urn:example:department
">
<depid
resource="urn:example:key:3
">
</Description> <!-- one fact -->
<Description about="urn:example:key:3
<name
>sales
</name
>
<manager resource="urn:example:key:
2"/>
</Description> <!-- two facts -->
</RDF>

You can see that the
RDF content is hard to digest, which
is why shorthand notations are popular. If you prefer procedures,
read this next bit on scripting RDF first. If you're
more visual and interactive, skip down to the bit about XUL
templates. If you understand database transactions, try the example
in [Hack #72], although that one
is more advanced.

Use of RDF facts in Firefox is restricted to secure content and to
remotely delivered XUL. There are plans to make some RDF available to
ordinary web pages, but that functionality is not ready as of this
writing.


6.14.2. Manipulate Content in Firefox's Head


To load an RDF file, you need a
datasource that can turn XML into facts.
Firefox provides a one-stop shop for datasources called the
RDF Service. You can also make your own
datasource. Here's a script that loads the contents
of an RDF URL into a new datasource:

var klass = Components.classes["@mozilla.org/rdf/rdf-service;1"];
var rs = klass.createInstance(Components.interfaces.nsIRDFService);
var ds = rs.GetDataSourceBlocking("file:///tmp/test.rdf");

The URL specified is a Unix one. For Windows, try method is preferable to
GetdataSource() if you're just
starting out. It avoids strange behavior caused by asynchronous
loading.

After this code runs, the ds object holds the
datasource. It should be retained as a variable as long as the set of
RDF facts is needed. The datasource is invisibly full of RDF facts,
and you can add, delete, modify, or query it as you see fit. In RDF
land, asserting a fact pretty much means
adding or inserting one.
The methods that do so are defined in the file
nsIRDFDataSource.idl. Read that file here:

http://lxr.mozilla.org/mozilla/source/rdf/base/idl/nsIRDFDataSource.idl

Here's some code that checks whether Fred is still
employed and adds Joe if that's not the case. This
kind of thing is similar to transaction processing in SQL:

var found      = false;
var ns = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
// RDF nodes
var pred_name = rs.GetResource(ns + "name");
var pred_empid = rs.GetResource(ns + "empid");
var emp = rs.GetResource("urn:example:employee");
var who = rs.GetLiteral("Fred");
var dep = rs.GetLiteral("sales");
// query for Fred
var empid = ds.GetSource(pred_name, who, true);
if ( empid != null ) {
found = ds.HasAssertion(emp, pred_empid, empid, true);
}
// insert Joe
if (!found)
{
who = rs.GetLiteral("Joe");
empid = rs.GetResource("urn:example:key:" + 5);
ds.Assert(emp, pred_empid, empid, true);
ds.Assert(empid, pred_name, who, true);
}

In this code, the variables pred_name and
pred_empid are roughly equivalent to object
property names: "employee 3 has a
property called name with a value of
Fred." pred is
short for predicate. For RDF reasons, predicates
must be URLs. The URLs are never downloaded. Each piece of a fact
must be an nsIRDFNode object or a subtype of that
type, so we have to construct them laboriously. The logic is simple:
test for the presence of two facts and insert two more if necessary.

The test part is done with the GetSource() and HasAssertion() methods. The latter method tests for the
existence of one fact. The former tests for any fact that has its
second and third parts as described, and returns the unknown first
part. That's how we find out Fred's
employee number. Always use TRue as the final
argument; it's almost irrelevant, but
it's required. Here are the two facts we test for:

<- 2, name, Fred ->
<- employee, empid, 2 ->

If either one is missing, then Fred's not there, so
Joe is added in using the Assert()
method. You can add a fully described fact only. Here are
Joe's two facts:

<- employee, empid, 5 ->
<- 5, name, Joe ->

Unlike SQL, there's no commit required, since the
datasource is all in memory. The whole thing can be flushed back out
to disk as RDF if required:

var rds = ds.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
rds.Flush( );

You can also receive notification if a datasource has changed [Hack #71], either because it was
refreshed from its origin or because extra facts were inserted by
scripts.


6.14.3. Display Facts with Templates


Firefox XUL templates are one of the hardest
Mozilla technologies, but a lot can be done with them once the art is
learned. When starting out, do not experiment
with tree-based templates, which are tricky, but
do regularly check all the XUL and RDF XML that
you create with an XML validation tool [Hack #59] .

Here's a simple XUL page that displays the dogs and
cats in an RDF datasource using two templates. This example uses the
simple template
syntax (as opposed to examples of the
extended template syntax [Hack #72] ). Notice here (everywhere)
how the template syntax hooks into the normal XUL syntax:

<?xml version="1.0"?>
<?xml-stylesheet href="?>
<window
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<hbox>
<vbox style="border:solid thin"
datasources="pets.rdf" ref="urn:test:dogs"
>
<template>
<label uri="rdf:*"
value="Dog: rdf:http://www.example.org/test#name"/>
</template>
</vbox>
<vbox style="border:solid thin"
datasources="pets.rdf" ref="urn:test:cats">
<template>
<label uri="rdf:*"
value="Cat: rdf:
http://www.example.org/test#name"/>
</template>
</vbox>
</hbox>
</window>

A template always starts with the datasources
attribute lodged with the parent tag of the
<template> tag. Figure 6-14
shows one window that might result.


Figure 6-14. Simple XUL window showing two template queries

The contents of the window are driven by the datasource that is
filled with facts from pets.rdf.
Here's a sample file with three pets in it. The
highlighted items are used by the XUL template code. Compare the two
documents. This is standard RDF, but laid out in a way that templates
can automatically understand:

<?xml version="1.0"?>
<RDF
xmlns:Test="http://www.example.org/test#"
xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<Description about="http://www.example.org">
<Test:Container>
<Seq about="urn:test:dogs">
<li resource="urn:test:dog1"/>
<li resource="urn:test:dog2"/>
</Seq>
<Seq about="urn:test:cats">
<li resource="urn:test:cat1"/>
</Seq>
</Test:Container>
</Description>
<Description about="urn:test:dog1" Test:name="Fido"/>
<Description about="urn:test:dog2" Test:name="Spot"/>
<Description about="urn:test:cat1" Test:name="Puss"/>
</RDF>

Even though there's just one datasource and just one
RDF file, the displayed content is revealed two different ways. If
the two templates were identical, the same content would be displayed
in each half of the page. If the RDF file changes, the displayed XUL
changes without any change to the XUL file. The user interface is
thus data-driven.


/ 164