1.6 Interroger les sources de données RDF

Écrit par Neil Deakin. Traduit par René-Luc D'Hont (13/06/2005).
Page originale : http://www.xulplanet.com/tutorials/mozsdk/rdfquery.php xulplanet.com

Cette section décrit comment consulter des information contenu dans un datasource.

Méthodes d'interrogation

L'interface nsIRDFDataSource fournit un certain nombre de méthodes pour interroger un datasource RDF. Les deux datasources courants in-memory-datasource et xml-datasource implémentent toutes ces méthodes. Cependant, d'autres datasources peuvent ne pas implémenter tous les dispositifs. Si une méthode n'est pas appliquée par un datasource, une exception sera faites quand la méthode sera appelé. C'est vrai pour plusieurs des datasources intégrés à Mozilla, c.-à-d., ceux qui commencent par 'rdf:' cela sont fournit avec Mozilla. Ces méthodes sont toutes désimplementées quand elles ne sont pas nécessaires pour le produit.

Puisque RDF stocke des triplets de données, vous pouvez interroger une partie du triplet pour certaines données. Par exemple, si vous avez le sujet et le prédicat du triplet, vous pouvez interroger le datasource pour les cibles qui sont présentes. De même, si vous avez le prédicat et la cible, vous pouvez rechercher les sujets.

Les exemples de cette section utilisent l'exemple RDF de la famille de Karen d'une des sections précédentes. La représentation du RDF/XML de ces données RDF est répétée ci-dessous.


<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:wordnet="http://xmlns.com/wordnet/1.6/"
         xmlns:people="http://www.xulplanet.com/rdf/people/">

<wordnet:Person rdf:about="http://www.xulplanet.com/rdf/people/Karen" people:name="Karen">
  <people:children>
    <rdf:Seq rdf:about="http://www.xulplanet.com/rdf/people/KarensKids">
      <rdf:li>
        <wordnet:Person rdf:about="http://www.xulplanet.com/rdf/people/Sandra" people:name="Sandra"/>
      </rdf:li>
      <rdf:li>
        <wordnet:Person rdf:about="http://www.xulplanet.com/rdf/people/Kevin" people:name="Kevin"/>
      </rdf:li>
      <rdf:li>
        <wordnet:Person rdf:about="http://www.xulplanet.com/rdf/people/Jack" people:name="Jack"/>
      </rdf:li>
    </rdf:Seq>
  </people:children>
</wordnet:Person>

</rdf:RDF>

une liste des méthodes d'interrogations disponibles pour tous les datasources RDF est énumérée ci-dessous. Le tableau présente les fonctions que vous appellerez connaissant certaines parties d'un triplet et que vous voulez une autre partie du triplet. Par exemple, la première ligne indique que si vous avez le sujet du triplet, et que vous voulez rechercher les prédicats qui précisent le sujet de cette ressource, employez la fonction ArcLabelsOut.

Vous avez Vous voulez Méthode
Sujet Prédicat Cible
X     Prédicat ArcLabelsOut
X     Cible ArcLabelsOut et GetTarget(s)
X X   Cible GetTarget ou GetTargets
    X Prédicat ArcLabelsIn
    X Sujet ArcLabelsIn et GetSource(s)
  X X Sujet GetSource ou GetSources
X X   Existence de cible hasArcOut
  X X Existence de sujet hasArcIn
X X X Existence HasAssertion

Recherche Des Cibles

La méthode la plus généralement utilisée est GetTarget. Cette méthode renverra une simple cible en donnant un sujet et un prédicat. Disons que nous voulons renvoyer le nom de la ressource Karen. L'URI de la ressource Karen est http://www.xulplanet.com/rdf/people/Karen. D'abord, nous obtenons cette ressource en utilisant le service RDF.


var rdfService = Components.classes["@mozilla.org/rdf/rdf-service;1"].
                   getService(Components.interfaces.nsIRDFService);

var karen = rdfService.GetResource("http://www.xulplanet.com/rdf/people/Karen");

Rappelez-vous que les ressources sont des objets globaux. Si Karen apparaît dans un autre datasource, les deux ressources seront le même objet. Ceci rend facile la combinaison de deux datasources ensemble.

Après, nous employons la méthode GetTarget pour rechercher le nom de Karen. Nous employons cette méthode parce que nous avons le sujet -- la ressource Karen que nous venons juste d'obtenir du service RDF ci-dessus -- et le prédicat qui est 'name'. Nous devrons qualifier le prédicat avec le namespace. Dans le RDF/XML ci-dessus, le préfixe people du namespace est employé, mais naturellement nous ne pouvons pas employer le préfixe en code puisqu'il est juste une sténographie XML. Nous devrons employer l'URI complète qui est http://www.xulplanet.com/rdf/people/name. Puisque le prédicat est également une ressource, nous le recherchons avec le service RDF exactement comme le sujet.


var name = rdfService.GetResource("http://www.xulplanet.com/rdf/people/name");

var target = datasource.GetTarget(karen, name, true);

Il est passée à la méthode GetTarget le sujet et le prédicat de la ressource. Elle renvoie la cible comme noeud RDF. La méthode renvoie toujours les objets qui implémente l'interface nsIRDFNode, jamais les interfaces de ressource ou de literal directement. Si vous voulez ces interfaces, vous devrez obtenir l'interface désirée en utilisant QueryInterface. Dans le cas de Karen, nous supposerons que son nom est un literal et que nous voulons obtenir la valeur du nom. Notez que la valeur retournée n'est pas une chaîne de caractères. Aucune des interfaces d'interrogation de RDF ne fonctionne directement sur des chaînes de carctères.


var karensname;

var target = datasource.GetTarget(karen, name, true);
if (target instanceof Components.interfaces.nsIRDFLiteral){
  karensname = target.Value;
}

L'opérateur instanceof vérifie si la valeur de la 'cible' est un literal RDF, et a également l'effet secondaire de remettre la valeur à l'interface si elle est bien un literal. Cette utilisation est également utile si la cible est placée dans une étape puisque nous faisons les deux obtenir et contrôler. Si la cible est nulle, il signifie que la cible n'existe pas. Dans cet exemple, la cible sera nulle si Karen n'a pas de nom indiqué. À l'intérieur du block if, la valeur du literal est recherchée comme chaîne de caractères en utilisant la propriété Value.

Vous avez peut-être noté que la méthode GetTarget a un troisième argument qui est placé à true ci-dessus. Ceci est employé pour indiquer si vous voulez rechercher un triplet négatif au lieu de normal. C'est un dispositif spécial spécifique à Mozilla qui permet à un lien RDF d'être faux au lieu de vrai. Rappelez-vous que quand une information n'est pas fournie dans le datasource, il signifie que le datasource ne sait pas cette information, pas que l'information est blanche. Par exemple, si nous n'avions pas indiqué le nom de Karen dans le RDF/XML, cela signifie que le nom de Karen n'est pas connu par le datasource. Elle peut cependant tout de même avoir un nom.

Un triplet négatif indique qu'un lien particulier n'est pas vrai. Par exemple, nous pourrions ajouter en lien que le nom de Karen n'est pas 'Tracy'. Notez qu'il n'y a aucune manière d'indiquer réellement ceci dans le RDF/XML, seulement en manoeuvrant directement le datasource. Cependant, des triplets négatifs devraient généralement être évités. Ils n'offrent pas vraiment beaucoup de valeur et habituellement ce genre d'informations sont mieux indiqué d'une autre manière.

Cependant, si le troisième argument de la méthode GetTarget est false, il renverra seulement des triplets négatifs. Cependant, pour presque tous les buts, true devrait être fourni pour cet argument.

La méthode GetTarget renverra seulement une des cibles qui existent dans le datasource. Si Karen avait plusieurs noms, seulement un d'eux serait retourné. La méthode relative GetTargets renverra une liste de tous les noms. Vous devriez ne jamais compter sur l'ordre dans lequel les noms sont retournés, puisque les données RDF ne sont dans aucun ordre particulier. Bien que la méthode GetTarget renverra probablement la même valeur à chaque appel successif, la valeur peut être différente chaque fois que votre application est parcourue.

La méthode GetTargets renverra une énumération qui est un objet qui peut être employé pour réitérer ensuite des résultats dans l'ordre.


var targets = datasource.GetTargets(karen, name, true);
while (targets.hasMoreElements()){
  var name = targets.getNext();
  if (name instanceof Components.interfaces.nsIRDFLiteral){
    alert(name.Value);
  }
}

L'énumération met en application l'interface nsISimpleEnumeration et a deux fonctions, hasMoreElements pour vérifier si tous les éléments ont bien été itérés, et getNext pour obtenir le prochain élément dans l'ordre. La boucle ci-dessus itérera chaque nom qui existe. Un ordre doit encore être exécutée sur chaque résultat. Si le résultat n'existe pas, une énumération vide sera retournée, ce qui signifie que l'appel de hasMoreElements renverra toujours faux. Notez que la valeur nulle n'est jamais retournée par la méthode GetTargets.

Recherche des sujets

Il y a également deux méthodes GetSource et GetSources qui fonctionnent dans la direction opposée. Ceci signifie que nous pouvons obtenir la ressource de Karen en donnant son nom comme literal. En combinant les méthodes de récupération de cible et de source, nous pouvons naviguer n'importe où dans le graphique RDF.


var rdfService = Components.classes["@mozilla.org/rdf/rdf-service;1"].
                   getService(Components.interfaces.nsIRDFService);

var karensname = rdfService.GetLiteral("Karen");
var name = rdfService.GetResource("http://www.xulplanet.com/rdf/people/name");

var subject= datasource.GetSource(name, karensname, true);

Ce code trouvera la ressource de Karen qui est http://www.xulplanet.com/rdf/people/Karen. Cela fonctionne pareillement aux méthodes de récupération de cible, excepté qu'elle va dans la direction inverse. En fournissant le nom de Karen, nous pouvons déterminer quelles ressources ont ce nom par l'intermédiaire du prédicat 'name'. La méthode GetSource prend la valeur du prédicat, de la cible et true comme arguments. Le prédicat est le premier argument à la différence de la méthode GetTarget où c'est le deuxième argument. La méthode GetSource renvoie toujours un objet de nsIRDFResource puisque les literals ne peuvent pas avoir de propriétés, ainsi vous pouvez employer les méthodes de nsIRDFResource directement sans obtenir le résultat.

Il y a également une méthode GetSources qui renverra une énumération de toutes les sources existantes. Ceci serait employé dans le cas où plusieurs personnes ont le nom Karen.

Interrogez les prédicats

Parfois vous voudrez déterminer quels prédicats sont spécifiés pour un noeud donné dans le datasource. Par exemple, prenez seulement la ressource Karen, vous voudriez découvrir quelles sont les propriétés qu'elle a. Dans l'exemple, Karen a trois propriétés, son nom, son type et ses enfants. Le nom a la valeur Karen. Le type est http://xmlns.com/wordnet/1.6/Person. La propriété 'enfants' est une ressource http://www.xulplanet.com/rdf/people/KarensKids. Il est possible que d'autres propriétés puissent aussi bien être ajoutées plus tard.

Si vous voulez déterminer quelles propriétés une ressource a, employez la méthode de datasource GetArcsOut. Il renvoie une énumération de tous les prédicats qui précisent une ressource. Si cette méthode est appelée pour la ressource Karen, l'énumération contiendra trois valeurs.


var karen = rdfService.GetResource("http://www.xulplanet.com/rdf/people/Karen");

var targets = datasource.ArcLabelsOut(karen);
while (targets.hasMoreElements()){
  var predicate = targets.getNext();
  if (predicate instanceof Components.interfaces.nsIRDFResource){
    alert(predicate.Value);
  }
}

L'énumération renvoie trois ressources de prédicat, pas les valeurs des prédicats. Ainsi les valeurs retournées seraient des ressources avec les valeurs http://www.xulplanet.com/rdf/people/name, http://www.xulplanet.com/rdf/people/children, et http://www.w3.org/1999/02/22-rdf-syntax-ns#type. Rappelez-vous que le RDF est non-ordonnée ainsi les résultats ne seront pas retourné dans un ordre particulier. L'énumération renvoie toujours les objets génériques de nsISupports, ainsi vous devrez obtenir les résultats retournés par la méthode getNext. Dans le cas des énumérations créées par la méthode ArcLabelsOut, les valeurs seront toujours des nsIRDFResources, puisque les prédicats sont toujours des ressources.

Une fois que vous avez la ressource du prédicat, vous pouvez la fournir comme argument à GetTarget pour obtenir la valeur du prédicat pour cette ressource. Par exemple, le code suivant obtiendra la valeur des prédicats trouvés.


var karen = rdfService.GetResource("http://www.xulplanet.com/rdf/people/Karen");

var targets = datasource.ArcLabelsOut(karen);
while (targets.hasMoreElements()){
  var predicate = targets.getNext();
  if (predicate instanceof Components.interfaces.nsIRDFResource){
    var target = datasource.GetTarget(karen, predicate, true);

    if (target instanceof Components.interfaces.nsIRDFResource){
      alert("Resource is: " + target.Value);
    }
    else if (target instanceof Components.interfaces.nsIRDFLiteral){
      alert("Literal is: " + target.Value);
    }
  }
}

Dans ce cas-ci, nous devons vérifier les deux interfaces nsIRDFResource et nsIRDFLiteral après l'appel à GetTarget, puisque un des résultats, le nom, sera un literal, alors que les deux autres, le type et les enfants, sont des ressources, et nous ne savons pas l'ordre dans lequel ils seront retournés. C'est une bonne idée de faire ce contrôle de toute façon à moins que vous soyez absolument sûr du genre du noeud qui sera retourné.

Notez que si deux prédicats 'name' précisent une ressource, par exemple, si Karen a deux noms, seulement un prédicat 'name' sera retourné dans l'énumération. Les énumérations ne contiendront jamais de duplications. Dans ce cas-ci, vous devrez employer la méthode GetTargets pour rechercher les valeurs.

La méthode ArcLabelsIn est semblable à la méthode d'ArcLabelsOut mais fonctionne dans la direction inverse. Par exemple, à partir du literal 'Karen', nous pourrions déterminer quels prédicats sont employés pour se diriger à la valeur. Dans l'exemple, seulement une valeur sera retournée dans l'énumération, le prédicat 'name'. Mais imaginez que quelqu'un est le nom 'April'. Ceci serait employé pour indiquer le nom de quelqu'un, mais pourrait également être employé ailleurs dans le datasource pour indiquer le mois de quelque chose en employant un prédicat 'month'. Dans cette situation, les deux attributs seront retournés, quoiqu'ils ne fassent pas partie de la même ressource. C'est ce dispositif qui rend la navigation dans le graphique RDF tout à fait puissante.

Interrogation sur l'existence

Trois méthodes additionnelles au datasource vous permettent de vérifier l'existence des données dans le RDF. La méthode hasArcOut peut être employée pour vérifier si un noeud a un certain prédicat le précisant. Cette méthode est semblable à la méthode de GetTarget sauf qu'elle ne renvoie pas la cible réelle, seulement un booléen indiquant si le prédicat existe ou pas. Cette méthode pourrait être plus efficace pour quelques datasources. Par exemple, nous pourrions vérifier si Karen a un nom ou pas en employant le code suivant:


var karen = rdfService.GetResource("http://www.xulplanet.com/rdf/people/Karen");
var name = rdfService.GetResource("http://www.xulplanet.com/rdf/people/name");

var hasName = datasource.hasArcOut(karen, name);

Le résultat de la méthode hasArcOut sera vrai ou faux. Dans cet exemple, le résultat sera vrai. Il y a également la méthode relative hasArcIn pour vérifier l'existence d'un prédicat se dirigeant vers l'intérieur d'un noeud. Notez que ces deux méthodes commencent par une lettre minuscule ce qui n'est pas vraie pour d'autres méthodes de datasource.

La méthode HasAssertion peut être employée pour vérifier un triplet dans le datasource en donnant chacun des trois parties du triplet. Ceci vous permettrait de vérifier si Karen a un nom spécifique. Cette méthode renverra vrai si le triplet existe, et faux sinon.

En conclusion, les datasources fournissent une méthode GetAllResources qui renverra une énumération de toutes les ressources qui sont employées comme sujets dans le datasource. Dans l'exemple, cinq valeurs seront retournées. Il n'y a aucune méthode équivalente pour renvoyer tous les literals. Pour faire ceci, vous devrez réitérer chaque ressource en utilisant GetAllResources, appelez ArcLabelsOut sur chaque ressource, et puis appelez GetTargets pour obtenir chaque cible. Ceci réitère efficacement pour toutes les données du datasource.


Mozilla® est une marque déposée de la fondation Mozilla.
Mozilla.org™, Firefox™, Thunderbird™, Mozilla Suite™ et XUL™ sont des marques de la fondation Mozilla.