# $Id: N3Model.py,v 1.17 2004/08/16 12:56:00 graham Exp $ # # RDF model for use with N3 parser # # Very loosely based on Jena idea of a model for RDF data, but the similarity # ends there. This N3Model is very much simpler, containing the following # main concepts: # - N3Statement values: correspond to arcs in an RDF graph. # - N3Node values: these include uriref nodes, blank nodes, literal nodes. # Additionally, any node can contain a formula - a collection of statements. # - a prefix table: a Python dictionary keyed by prefix names that relate # to corresponding namespace URIs. # A model consists of a single N3Node containing a formula # # TODO: # - initialization of special URI vocabularies is a mess, split between # N3Model and N3Parser -- needs to be pulled in to N3Model. # - query with substring/pattern match on literals # - add method to compare models # #--------+---------+---------+---------+---------+---------+---------+---------+ # # Copyright (c) 2002, G. KLYNE # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #--------+---------+---------+---------+---------+---------+---------+---------+ # $Source: /file/cvsdev/PythonN3/N3Model.py,v $ # $Author: graham $ # $Revision: 1.17 $ $Date: 2004/08/16 12:56:00 $ #--------+---------+---------+---------+---------+---------+---------+---------+ # 1 2 3 4 5 6 7 8 #import os #import re import sys import string import StringIO from N3Exception import N3Exception from N3Node import N3Node, NameStartChar, NameChar from N3Statement import N3Statement from N3Parser import N3Parser #--------+---------+---------+---------+---------+---------+---------+---------+ # Define N3Model package exception conditions # # Base class for exceptions # class N3ModelError( N3Exception ): """ Base class for N3Model access errors. Attributes: message -- explanation of the error """ def __init__(self, message): N3Exception.__init__( self, "N3ModelError: "+message ) pass class N3PrefixError( N3ModelError ): """ Prefix table conflict """ def __init__(self, message): N3ModelError.__init__( self, "Prefix table mismatch: "+message ) pass class N3MergeError( N3ModelError ): """ Prefix table conflict """ def __init__(self, message): N3ModelError.__init__( self, "Model merge error: "+message ) pass #--------+---------+---------+---------+---------+---------+---------+---------+ # N3Model - defines graph access methods # class N3Model: """ N3Model - defines a graph and associated access methods. """ #--------------------------------------------------------------------------- # Construction and parse methods #--------------------------------------------------------------------------- # Override this constructor for alternative model storage. # def __init__( self, Input=None, Filename=None ): """ Construct a model from a supplied input stream or file name. """ self.DefaultPrefixTable = \ { "": "#", "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", "rdfs": "http://www.w3.org/2000/01/rdf-schema#" } self.read( Input=Input, Filename=Filename ) return def read( self, Input=None, Filename=None, DefaultPrefix=1 ): """ Read and parse N3 from the specified input stream, storing the resulting formula in the current N3Model object. """ if Filename: self.debug( "Init: filename: "+Filename ) if Input: raise N3ModelError( "N3Model takes stream or filename, not both" ) Input = open( Filename, 'r' ) if Input: # Input specified: parse into model Parser = N3Parser( DefaultPrefix=DefaultPrefix ) self.setFormula( Parser.Parse( Input ) ) self.setPrefixTable( Parser.getPrefixTable() ) self.SpecialURI = Parser.getSpecialURI() else: # No input: initialize empty model with default prefix table Formula = N3Node() Formula.makeFormula() self.setFormula( Formula ) #### Parser = N3Parser( DefaultPrefix=DefaultPrefix ) p = Parser.getPrefixTable() # p[""] = self.DefaultPrefixTable[""] CAUSES PROBLEMS, CANNOT DECLARE NULL @prefix self.setPrefixTable( p ) self.SpecialURI = Parser.getSpecialURI() #### #self.setPrefixTable( self.DefaultPrefixTable ) #self.SpecialURI = {} return def parseOK( self ): return self.ParseOK def setPrefixTable( self, Table ): self.PrefixTable = Table return def getPrefixTable( self ): return self.PrefixTable def close( self ): self.Formula = None self.ParseOK = None return # Override this method for alternative model storage. # def setFormula( self, Formula ): self.Formula = Formula self.ParseOK = ( Formula != None ) return # Override this method for alternative model storage. # def addStatement( self, Stmt ): if self.Formula == None: self.Formula = N3Node() self.Formula.makeFormula() self.Formula.addStatement( Stmt ) return def merge( self, Model ): """ Merge a supplied model with the current model. """ ### self.debug( "Merging" ) if not self.parseOK(): raise N3MergeError( "self input parse failed" ) if not Model.parseOK(): raise N3MergeError( "supplied model input parse failed" ) # Merge prefix table for p in Model.PrefixTable.keys(): if p in self.PrefixTable.keys(): if Model.PrefixTable[p] != self.PrefixTable[p]: raise N3PrefixError( "key '"+str(p)+"'" ) self.PrefixTable[p] = Model.PrefixTable[p] # Add statements Iter = Model.makeStatementIterator( None, None, None ) while Iter.hasNext(): s = Iter.next() self.addStatement( s ) return #--------------------------------------------------------------------------- # Node creation and access methods #--------------------------------------------------------------------------- def makeNode( self, QName ): """ Construct a node given a QName """ i = QName.find( ":" ) p = QName[:i] l = QName[i+1:] n = self.PrefixTable[p] return N3Node( ns=n, name=l ) def makeSpecialNode( self, Name ): """ Retrieve a special node corresponding to the supplied name. Special node names and their default values are: { "a": "rdf:type", "equals": "daml:equivalent", "listfirst": "rdf:first", "listrest": "rdf:rest", "listnull": "rdf:nil", "contains": "rdfs:contains", "plus": "operator:plus", "minus": "operator:minus", "slash": "operator:slash", "star": "operator:star" } See N3Parser.DefaultURI for the definitive list. """ return self.makeNode( self.SpecialURI[Name] ) def getQName( self, Node ): """ Return QName for a node, or None """ return Node.getQName( self.PrefixTable ) def getNodeName( self, Node ): """ Return convenient description for a node: QName, string or blank node id """ return Node.getNodeName( self.PrefixTable ) #--------------------------------------------------------------------------- # Model access methods #--------------------------------------------------------------------------- # Return node with statements matching components supplied # def findStatements( self, Subj, Prop, Obj ): """ Return list containing statements that match the supplied subject, property and/or object. Values supplies as None match any corresponding part of the statement. Return: A list value containing a statements matching the supplied values. """ Statements = [] Iter = self.makeStatementIterator( Subj, Prop, Obj ) while Iter.hasNext(): Statements.append( Iter.next() ) Iter.close() return Statements # Return object node for supplied subject and property # def findObjectValue( self, Subj, Prop ): """ Return object node for the supplied subject and object values. Return: The N3Node value that is the object of a statement with the specified subject and property, or None. If there is more than one possible value, one is selected arbitrarily. """ Iter = self.makeStatementIterator( Subj, Prop, None ) if Iter.hasNext(): Result = Iter.next().getObject() Iter.close() return Result return None # Return object node obtained by walking a specified path of # property nodes from a given subject starting point # def findPathValue( self, Subj, Path ): """ Return object node for the supplied subject and object values. Return: The N3Node value that is the object of a statement located by walking the specified sequence of property arcs from a specified start point in the graph, or None. If there is more than one possible path at any point in the graph traversal, one is selected arbitrarily. """ n = Subj for p in Path: n = s.findObjectValue( n, p ) if not n: break return n # Return a list of object nodes for a supplied subject and # each occurrence of a given property. # def listObjectValues( self, Subj, Prop ): """ Return a list of object nodes for the supplied subject and object values. Return: The a lists of N3Node values that are the objects of statement with the specified subject and property, or an empty list. """ Result = [] Iter = self.makeStatementIterator( Subj, Prop, None ) while Iter.hasNext(): Result.append( Iter.next().getObject() ) Iter.close() return Result # Return a list of object nodes obtained by walking a specified # path of property nodes from a given subject starting point. # def listPathValues( self, Subj, Path ): """ Return a list of object nodes obtained by walking a specified path of property nodes from a given subject starting point. Return: The a lists of N3Node values that are the objects of statement with the specified subject and property, or an empty list. """ if not Path: return [Subj] p1 = Path[0] Path = Path[1:] Result = [] for s in self.findStatements( Subj, p1, None ): r = self.listPathValues( s.getObject(), Path ) if r: if Result: for n in r: Result.append( n ) else: Result = r return Result # Local class and helper function to create an iterator over statements # in a model. The class conforms to the Python 2.2 Iterator protocol, # but this software does not assume Iterator support so code that uses # it can run under earlier Python language versions (notably Jython). # # This class must be redefined (or method makeIterator overidden) to use # this N3Model class with different back-end RDF statement stores. # class StatementIterator: def __init__( self, StatementList, Subj, Prop, Obj ): self.List = StatementList self.Subj = Subj self.Prop = Prop self.Obj = Obj self.Index = 0 self.Next = None return def __iter__( self ): return self def next( self ): if not self.hasNext(): raise StopIteration() result = self.Next self.Next = None return result def hasNext( self ): if self.Next: return 1 while self.Index < len( self.List ): self.Next = self.List[self.Index] self.Index += 1 if self.Next.match( self.Subj, self.Prop, self.Obj ): return 1 self.Next = None return 0 def close( self ): self.List = None self.Subj = None self.Prop = None self.Obj = None self.Index = 0 self.Next = None # End of class StatementIterator def makeStatementIterator( self, Subj, Prop, Obj ): """ Return a statement iterator over statements from the current model that match the supplied subject, property and/or object. Values supplies as None match any corresponding part of a Model statement. Return: An iterator that returns statements matching the supplied values. """ return self.StatementIterator( self.Formula.getStatements(), Subj, Prop, Obj ) ### Query with substring/pattern match on literals #--------------------------------------------------------------------------- # Diagnostics #--------------------------------------------------------------------------- def dump( self, ostr ): """ Diagnostic function: dump model to supplied output stream. """ ostr.write( ">>> Dump of N3Model data\n" ) Iter = self.makeStatementIterator( None, None, None ) while Iter.hasNext(): s = Iter.next() ostr.write( s.getStmtDisplay( self.getPrefixTable() )+"\n" ) ostr.write( "<<< Dump ends\n" ) return def debug( self, val ): sys.stdout.write( "N3Model: " + val + "\n" ) return # End of N3Model #--------+---------+---------+---------+---------+---------+---------+---------+ # N3Vocab - defines some common vocabulary # class N3Vocab: _m = N3Model() rdf_type = _m.makeNode( "rdf:type" ) rdf_first = _m.makeNode( "rdf:first" ) rdf_rest = _m.makeNode( "rdf:rest" ) rdf_nil = _m.makeNode( "rdf:nil" ) rdfs_label = _m.makeNode( "rdfs:label" ) rdfs_comment = _m.makeNode( "rdfs:comment" ) rdfs_contains = _m.makeNode( "rdfs:contains" ) _m = None # End of N3Vocab #--------+---------+---------+---------+---------+---------+---------+---------+ # # Stand-alone test code follows: # if __name__ == '__main__': # Some basic tests sys.stdout.write( "Node tests\n" ) Node1 = N3Node() sys.stdout.write( "Node 1: "+str(Node1)+"\n" ) Node2 = N3Node( uri='http://example.org/base/local' ) sys.stdout.write( "Node 2: "+str(Node2)+"\n" ) Node3 = N3Node( ns='http://example.org/base/', name='local' ) sys.stdout.write( "Node 3: "+str(Node3)+"\n" ) Node4 = N3Node( lit='a string' ) sys.stdout.write( "Node 4: "+str(Node4)+"\n" ) if Node1 == Node1: sys.stdout.write( "Node1 == Node1 (OK)\n" ) else: sys.stdout.write( "Node1 != Node1 (Error)\n" ) if Node2 == Node3: sys.stdout.write( "Node2 == Node3 (OK)\n" ) else: sys.stdout.write( "Node2 != Node3 (Error)\n" ) sys.stdout.write( "Statement tests\n" ) Stmt1 = N3Statement( Node1, Node2, Node4 ) sys.stdout.write( "Stmt 1: "+str(Stmt1)+"\n" ) Stmt2 = N3Statement( Node1, Node3, Node4 ) sys.stdout.write( "Stmt 2: "+str(Stmt2)+"\n" ) if Stmt1 == Stmt2: sys.stdout.write( "Stmt1 == Stmt2 (OK)\n" ) else: sys.stdout.write( "Stmt1 != Stmt2 (Error)\n" ) sys.stdout.write( "Model tests\n" ) Model = N3Model() Node5 = Model.makeNode( "rdf:type" ) sys.stdout.write( "Node 5: "+str(Node5)+"\n" ) Node6 = Model.makeNode( ":foo" ) sys.stdout.write( "Node 6: "+str(Node6)+"\n" ) Stmt3 = N3Statement( Node1, Node5, Node4 ) Stmt4 = N3Statement( Node1, Node6, Node5 ) Model.addStatement( Stmt1 ) Model.addStatement( Stmt2 ) Model.addStatement( Stmt3 ) Model.addStatement( Stmt4 ) # Simple query Q1 = Model.findStatements( Node1, Node5, None ) if len(Q1) != 1: sys.stdout.write( "Q1, 1 result expected, got: "+str(len(Q1))+"\n" ) sys.stdout.write( "Q1 result expected: "+str(Stmt3)+"\n" ) if Q1[0] != Stmt3: sys.stdout.write( "Q1 result returned: "+str(Q1[0])+" (error)\n" ) # Another simple query Q2 = Model.findStatements( Node1, Node6, None ) if len(Q2) != 1: sys.stdout.write( "Q2, 1 result expected, got: "+str(len(Q2))+"\n" ) sys.stdout.write( "Q2 result expected: "+str(Stmt4)+"\n" ) if Q2[0] != Stmt4: sys.stdout.write( "Q2 result returned: "+str(Q1[0])+" (error)\n" ) # Blank node query Node7 = N3Node() Q3 = Model.findStatements( Node1, Node6, Node7 ) sys.stdout.write( "Q3 no result expected\n" ) if len(Q3) != 0: sys.stdout.write( "Q3, No result expected, got: "+str(len(Q3))+"\n" ) # List query: sys.stdout.write( "Q4 list result test\n" ) Node8 = Model.makeNode( "rdf:li" ) Stmt51 = N3Statement( Node1, Node8, N3Node(lit="1") ) Stmt52 = N3Statement( Node1, Node8, N3Node(lit="2") ) Stmt53 = N3Statement( Node1, Node8, N3Node(lit="3") ) Stmt54 = N3Statement( Node1, Node8, N3Node(lit="4") ) Model.addStatement( Stmt51 ) Model.addStatement( Stmt52 ) Model.addStatement( Stmt53 ) Model.addStatement( Stmt54 ) Q4 = Model.listObjectValues( Node1, Node8 ) sys.stdout.write( "Q4: "+repr(Q4)+"\n" ) #### if len(Q4) != 4: sys.stdout.write( "Q4, 4 results expected, got: "+str(len(Q4))+"\n" ) if Q4[0] != Stmt51.getObject(): sys.stdout.write( "Q4[0], expected "+str(Stmt51.getObject())+ ", got: "+str(Q4[0])+"\n" ) if Q4[1] != Stmt52.getObject(): sys.stdout.write( "Q4[1], expected "+str(Stmt52.getObject())+ ", got: "+str(Q4[1])+"\n" ) if Q4[2] != Stmt53.getObject(): sys.stdout.write( "Q4[2], expected "+str(Stmt53.getObject())+ ", got: "+str(Q4[2])+"\n" ) if Q4[3] != Stmt54.getObject(): sys.stdout.write( "Q4[3], expected "+str(Stmt54.getObject())+ ", got: "+str(Q4[3])+"\n" ) # List path query: sys.stdout.write( "Q5 path list result test\n" ) Node91 = N3Node() Node92 = N3Node() Stmt61 = N3Statement( Node1, Node8, Node91 ) Stmt62 = N3Statement( Node91, Node8, N3Node(lit="62") ) Stmt63 = N3Statement( Node91, Node8, N3Node(lit="63") ) Stmt64 = N3Statement( Node1, Node8, Node92 ) Stmt65 = N3Statement( Node92, Node8, N3Node(lit="65") ) Stmt66 = N3Statement( Node92, Node8, N3Node(lit="66") ) Model.addStatement( Stmt61 ) Model.addStatement( Stmt62 ) Model.addStatement( Stmt63 ) Model.addStatement( Stmt64 ) Model.addStatement( Stmt65 ) Model.addStatement( Stmt66 ) Q5 = Model.listPathValues( Node1, (Node8,Node8) ) sys.stdout.write( "Q5: "+repr(Q5)+"\n" ) #### if len(Q5) != 4: sys.stdout.write( "Q5, 4 results expected, got: "+str(len(Q5))+"\n" ) if Q5[0] != Stmt62.getObject(): sys.stdout.write( "Q5[0], expected "+str(Stmt62.getObject())+ ", got: "+str(Q5[0])+"\n" ) if Q5[1] != Stmt63.getObject(): sys.stdout.write( "Q5[1], expected "+str(Stmt63.getObject())+ ", got: "+str(Q5[1])+"\n" ) if Q5[2] != Stmt65.getObject(): sys.stdout.write( "Q5[2], expected "+str(Stmt65.getObject())+ ", got: "+str(Q5[2])+"\n" ) if Q5[3] != Stmt66.getObject(): sys.stdout.write( "Q5[3], expected "+str(Stmt66.getObject())+ ", got: "+str(Q5[3])+"\n" ) ######################### sys.exit( 99 ) ######################### # Full-blown parsing and query tests def MakeDocDescription( Model, doc ): # [ hdr:document ; # hdr:section "3" ] ; hdr_document = Model.makeNode( "hdr:document" ) hdr_section = Model.makeNode( "hdr:section" ) dtext = "" dnode = Model.findObjectValue( doc, hdr_document ) if dnode.isURI(): dname = dnode.getURI() dtext += "%s" % (dname,dname) else: dtext += dnode.getString() snode = Model.findObjectValue( doc, hdr_section ) if snode: dtext += ", section %s" % snode.getString() return dtext def MakePostalDescription( Model, pnode ): # [ foaf:building "Clearswift Corporation" ; # foaf:street1 "1310 Waterside, Arlington Business Park" # foaf:street2 "Theale" ; # foaf:city "Reading" ; # foaf:area "Berks" ; # foaf:postcode "RG7 4SA" ; # foaf:country "UK" ] ; text = "" for p in ( Model.makeNode( "foaf:building" ), Model.makeNode( "foaf:street1" ), Model.makeNode( "foaf:street2" ), Model.makeNode( "foaf:street3" ), Model.makeNode( "foaf:city" ), Model.makeNode( "foaf:area" ), Model.makeNode( "foaf:postcode" ) ): node = Model.findObjectValue( pnode, p ) if node: text += "%s,
\n" % (node.getString(),) for p in ( Model.makeNode( "foaf:country" ), ): node = Model.findObjectValue( pnode, p ) if node: text += "%s
\n" % (node.getString(),) return text def MakeAuthorDescription( Model, anode ): # hdr:author # [ foaf:name "Graham Klyne" ; # foaf:mbox "GK-headers@ninebynine.org" ; # foaf:workplacePostal # [ ... ] ; # foaf:workplaceTel "011 8903 8903" ; # foaf:workplaceFax "011 8903 9000" ; # foaf:workplaceHomepage ] ; foaf_name = Model.makeNode( "foaf:name" ) foaf_mbox = Model.makeNode( "foaf:mbox" ) foaf_workplacePostal = Model.makeNode( "foaf:workplacePostal" ) foaf_workplaceTel = Model.makeNode( "foaf:workplaceTel" ) foaf_workplaceFax = Model.makeNode( "foaf:workplaceFax" ) foaf_workplaceHomepage = Model.makeNode( "foaf:workplaceHomepage" ) text = "" name = Model.findObjectValue( anode, foaf_name ) mbox = Model.findObjectValue( anode, foaf_mbox ) text += "%s <%s>
\n" % (name.getString(),mbox.getString()) post = Model.findObjectValue( anode, foaf_workplacePostal ) if post: text += MakePostalDescription( Model, post ) tel = Model.findObjectValue( anode, foaf_workplaceTel ) if tel: text += "Tel: %s
\n" % (tel.getString(),) fax = Model.findObjectValue( anode, foaf_workplaceFax ) if fax: text += "Fax: %s
\n" % (fax.getString(),) url = Model.findObjectValue( anode, foaf_workplaceHomepage ) if url: urlstr = url.getURI() or url.getString() text += "Web: %s
\n" % (urlstr,urlstr) text += "\n" return text N3Input = ''' @prefix rdf: . @prefix rdfs: . @prefix foaf: . @prefix hdr: . # temporary ??? a hdr:HeaderField ; hdr:fieldName "Content-features" ; rdfs:label "Indicates content features of a MIME body part" ; hdr:protocol [ hdr:protocolName "mail" ; hdr:specification [ = ; hdr:document ] ] ; hdr:status "standards-track" ; hdr:author [ foaf:name "Graham Klyne" ; foaf:mbox "GK-headers@ninebynine.org" ; foaf:workplacePostal [ foaf:building "Clearswift Corporation" ; foaf:street """1310 Waterside, Arlington Business Park, Theale""" ; foaf:city "Reading" ; foaf:area "Berks" ; foaf:postcode "RG7 4SA" ; foaf:country "UK" ] ; foaf:workplaceTel "011 8903 8903" ; foaf:workplaceFax "011 8903 9000" ; foaf:workplaceHomepage ] ; hdr:listitem "1" ; hdr:listitem "2" ; hdr:listitem "3" ; hdr:specification [ = ; hdr:document ; hdr:section "3" ] ; rdfs:comment """The 'Content-features:' header can be used to annotate a MIME body part with a media feature expression, to indicate features of the body part content. See also: RFC 2533, RFC 2506, RFC 2045.""" . ''' HeaderListingHead=''' Table of header field registrations ''' HeaderListingEntry='''

Header field %s

Header field name:
%s
Applicable protocol:
%s (%s)
Purpose:
%s
Status:
%s
Author/Change controller:
%s
Specification document(s):
%s
Related information:
%s
''' HeaderListingFoot=''' ''' sys.stdout.write( "Create model\n" ) InputStr = StringIO.StringIO( N3Input ) Model = N3Model( InputStr ) hdr_HeaderField = Model.makeNode( "hdr:HeaderField" ) hdr_fieldName = Model.makeNode( "hdr:fieldName" ) hdr_protocol = Model.makeNode( "hdr:protocol" ) hdr_protocolName = Model.makeNode( "hdr:protocolName" ) hdr_specification = Model.makeNode( "hdr:specification" ) hdr_status = Model.makeNode( "hdr:status" ) hdr_author = Model.makeNode( "hdr:author" ) sys.stdout.write( "Pass 1, create header line\n" ) sys.stdout.write( "Field-name Protocol Description\n" ) sys.stdout.write( "---------- -------- -----------\n" ) # 20.................. 8....... ?.......... n = Model.findStatements( None, N3Vocab.rdf_type, hdr_HeaderField ) for s in n.getStatements(): subj = s.getSubject() nam = Model.findObjectValue( subj, hdr_fieldName ).getString() pro = Model.findPathValue( subj, (hdr_protocol,hdr_protocolName) ).getString() lab = Model.findObjectValue( subj, N3Vocab.rdfs_label ).getString() sys.stdout.write( "%-20s %-8s %s\n" % (pro,nam,nam,pro,lab) ) sys.stdout.write( "Pass 2, create full description\n" ) sys.stdout.write( HeaderListingHead ) for s in n.getStatements(): subj = s.getSubject() nam = Model.findObjectValue( subj, hdr_fieldName ).getString() pro = Model.findPathValue( subj, (hdr_protocol,hdr_protocolName) ).getString() dnode = Model.findPathValue( subj, (hdr_protocol,hdr_specification) ) prodoc = MakeDocDescription( Model, dnode ) lab = Model.findObjectValue( subj, N3Vocab.rdfs_label ).getString() sts = Model.findObjectValue( subj, hdr_status ).getString() anode = Model.findObjectValue( subj, hdr_author ) author = MakeAuthorDescription( Model, anode ) dnode = Model.findObjectValue( subj, hdr_specification ) hdrdoc = MakeDocDescription( Model, dnode ) info = Model.findObjectValue( subj, N3Vocab.rdfs_comment ).getString() sys.stdout.write( HeaderListingEntry % (nam,nam,pro,prodoc,lab,sts,author,hdrdoc,info) ) sys.stdout.write( HeaderListingFoot ) sys.stdout.write( "Exiting\n" ) #--------+---------+---------+---------+---------+---------+---------+---------+ # # $Log: N3Model.py,v $ # Revision 1.17 2004/08/16 12:56:00 graham # Removed default (empty) prefix definition in N3Model, which was # causing # the report generator to fail on input files containing a null @prefix declaration. # Be aware that this fix might cause some failures in other places that should # be fixed rather than backing out this change - having a default empty prefix # like this was a bad idea. # # Revision 1.16 2004/02/17 23:37:57 graham # Sync # # Revision 1.15 2002/12/11 13:51:49 graham # Fix up some URI initialization problems # # Revision 1.14 2002/09/19 09:37:08 graham # Added facility to scan contents of list (using rdf:first, rdf:rest) # # Revision 1.13 2002/05/15 17:21:13 graham # N3ModelJenaRdb.py, with supporting code, # works with a Jena RDB model store. # Tested against a MySQL server. # # Revision 1.12 2002/05/14 15:18:44 graham # Initial verion of N3ModelJenaMem.py, which # works with a Jena memory-based RDF store # # Revision 1.11 2002/05/09 16:14:40 graham # Add method to return multiple matches for a path query # # Revision 1.10 2002/05/07 10:54:16 graham # Fixes to accept N3 output: options to control default prefix table, accept 'this' as node name (treated as <#>), allow '-' in qnames (not strictly valid N3?) # # Revision 1.9 2002/05/01 15:43:48 graham # Cleanup small details # # Revision 1.8 2002/04/28 17:01:45 graham # Partial port to Jython-21 (but having problems with os module support) # # Revision 1.7 2002/04/28 11:12:19 graham # Further improvements to N3 parser, and extend options for N3SyntaxCheck. # # Revision 1.6 2002/04/27 18:06:48 graham # Fix bugs in N3 parser, add N3 syntax checker program # # Revision 1.5 2002/04/25 19:00:13 graham # Update CVS keyword fields # # Revision 1.4 2002/04/25 18:53:26 graham # Add copyright and disclaimer notices # # Revision 1.3 2002/04/24 14:36:33 graham # Save edits # # Revision 1.2 2002/04/23 17:09:57 graham # Basic query and report generation works # # Revision 1.1 2002/04/19 22:07:39 graham # Separated into smaller modules; basic N3Model functions working # # Revision 1.3 2002/04/18 07:39:42 graham # Added TODO # # Revision 1.2 2002/04/17 23:41:31 graham # Basic N3 parser is working #