Viewing file: Dom.py (35.01 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
######################################################################## # $Header: /var/local/cvsroot/4Suite/Ft/Rdf/Serializers/Dom.py,v 1.45 2005/03/23 07:08:35 mbrown Exp $ """ RDF model-to-DOM serialization, DOM-to-RDF model deserialization where the serialized DOM conforms to RDF/XML syntax (1999 Recommendation)
Copyright 2005 Fourthought, Inc. (USA). Detailed license and copyright information: http://4suite.org/COPYRIGHT Project home, documentation, distributions: http://4suite.org/ """
import cStringIO, posixpath, os from xml.dom import Node
from Ft.Lib import Set, Uri from Ft.Rdf import RDF_MS_BASE, RDF_SCHEMA_BASE, DAML_OIL_NS, OLD_DAML_OIL_NS, OWL_NS from Ft.Rdf import OBJECT_TYPE_RESOURCE, OBJECT_TYPE_LITERAL from Ft.Rdf import RdfException, ParseException from Ft.Rdf.Resource import Resource from Ft.Rdf.Statement import Statement from Ft.Xml import XML_NAMESPACE, XMLNS_NAMESPACE, EMPTY_NAMESPACE, EMPTY_PREFIX from Ft.Xml import Domlette from Ft.Xml.Lib import Language from Ft.Xml.XPath import Evaluate, Compile, Context, Util
VALID_PARSETYPES = [ (EMPTY_NAMESPACE, u'Literal'), (EMPTY_NAMESPACE, u'Resource'), (DAML_OIL_NS, u'collection'), (OLD_DAML_OIL_NS, u'collection'), (EMPTY_NAMESPACE, u'Collection') ]
CONTAINERS = ['Bag', 'Seq', 'Alt']
RDF_SUBJ_PREDICATE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#subject" RDF_OBJ_PREDICATE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#object" RDF_PRED_PREDICATE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#predicate" RDF_TYPE_PREDICATE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" RDF_VALUE_PREDICATE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#value"
RDF_PREDICATES = [ RDF_SUBJ_PREDICATE, RDF_OBJ_PREDICATE, RDF_PRED_PREDICATE, RDF_TYPE_PREDICATE, RDF_VALUE_PREDICATE, ]
class Serializer: """Serialize or deserialize a model based on the XML serialization in the RDF Model and Syntax recommendation.""" def __init__(self, reify=1): #self.reify = 0 return
def serialize(self, model, nsMap=None, selectUri=None, localResources=[], implementation=None, stmts=None): """Construct a DOM representing statements in the model.""" implementation = implementation or Domlette.implementation doc = implementation.createDocument(RDF_MS_BASE, 'rdf:RDF', None)
nsMap = nsMap or {} if RDF_MS_BASE not in nsMap: nsMap[RDF_MS_BASE] = 'rdf'
if stmts is None: stmts = model.statements() stmts = filter(lambda x: x.uri != RDF_SCHEMA_BASE, stmts)
if selectUri: stmts = filter(lambda x, sel=selectUri: x.uri == sel, stmts) else: stmts = filter(lambda x: x.uri != RDF_SCHEMA_BASE, stmts)
inlineResources = filter(lambda x, s=len(RDF_MS_BASE): x.predicate[:s] == x.object[:s] == RDF_MS_BASE and x.predicate[s:] == 'type' and x.object[s:] in CONTAINERS, stmts)
inlineResources = map(lambda s: s.subject, inlineResources)
for resource in inlineResources: used = self.exportInlineResource(doc, nsMap, resource, stmts) stmts = Set.Not(stmts, used)
sorted = self.__sortStatementsForDump(stmts) for subject in sorted: data = sorted[subject] id = '' if subject in localResources: id = subject if id[:1] == '#': id = id[1:] subject = '' self.exportDescription(doc, nsMap, data, subject, id) return doc
def exportInlineResource(self, doc, nsMap, subject, origStmts): #Get all statements with this as a subject stmts = filter(lambda x, s=subject: x.subject == s, origStmts) simpleStatements = {} containerStatements = {} used = [] type = "Description" for stmt in stmts: predNs, predLocal = self.splitUri(stmt.predicate) if (predNs, predLocal) == (RDF_MS_BASE, 'type'): #This has already been handled ns, testType = self.splitUri(stmt.object) if testType != 'Bag': type = testType used.append(stmt) elif predNs == RDF_MS_BASE: #Must be a statement reference used.append(stmt) if predLocal[0] == '_': #See what this points to: nextUsed = filter(lambda x, s=stmt.object: x.subject == s, origStmts) nextUsedType = filter(lambda x, n=RDF_MS_BASE+'Statement': x.object==n, nextUsed) if len(nextUsedType): #Yep, remove the reification used += nextUsed else: if type == 'Description': type = 'Bag' containerStatements[predLocal[1:]] = (stmt.object, stmt.objectType) else: #FIXME: We should serialize this back out as a regular statement pass else: if stmt.predicate not in simpleStatements: simpleStatements[stmt.predicate] = [] simpleStatements[stmt.predicate].append((stmt.object, stmt.objectType)) used.append(stmt)
if type == 'Description': self.exportDescription(doc, nsMap, simpleStatements, id=subject) else: self.exportContainer(doc, doc.documentElement, nsMap, type, containerStatements, id=subject) if len(simpleStatements): self.exportDescription(doc, nsMap, simpleStatements, id=subject) return used
def exportContainer(self, doc, parent, nsMap, type, stmts, id): cont = doc.createElementNS(RDF_MS_BASE, u'rdf:%s' % type) cont.setAttributeNS(RDF_MS_BASE, u'rdf:ID', id)
keys = stmts.keys() keys.sort()
for k in keys: li = doc.createElementNS(RDF_MS_BASE, u"rdf:li") if stmts[k][1] == OBJECT_TYPE_RESOURCE: li.setAttributeNS(EMPTY_NAMESPACE, u'resource', stmts[k][0]) else: li.appendChild(doc.createTextNode(unicode(stmts[k][0]))) cont.appendChild(li)
parent.appendChild(cont) return
def exportDescription(self, doc, nsMap, stmts, subject='', id=''): desc = doc.createElementNS(RDF_MS_BASE, u'rdf:Description') if subject: desc.setAttributeNS(RDF_MS_BASE, u'rdf:about', subject) if id: desc.setAttributeNS(RDF_MS_BASE, u'rdf:ID', id) doc.documentElement.appendChild(desc) self.exportSimpleStatements(doc, desc, nsMap, stmts) return
def exportSimpleStatements(self, doc, parent, nsMap, stmts): for pred in stmts: scheme, authority, path, query, fragment = Uri.SplitUriRef(pred) ns = None if fragment is not None: #fragment ns = Uri.UnsplitUriRef((scheme, authority, path, query, None)) + '#' if ns in nsMap: prefix = nsMap[ns] else: prefix = 'ns' + str(len(nsMap)) nsMap[ns] = prefix predicateName = prefix and prefix + ':' + fragment or fragment elif path and not query: #tail of path p1, p2 = posixpath.split(path) if p1: ns = Uri.UnsplitUriRef((scheme, authority, p1 + '/', None, None)) if ns in nsMap: prefix = nsMap[ns] else: prefix = 'ns' + str(len(nsMap)) nsMap[ns] = prefix predicateName = prefix and prefix + ':' + p2 or p2 else: prefix = EMPTY_PREFIX predicateName = p2 else: #FIXME: Need to specify the whole URI, then predicateName = pred pass
for obj in stmts[pred]: predicate = doc.createElementNS(ns, unicode(predicateName)) parent.appendChild(predicate) if obj[1] == OBJECT_TYPE_RESOURCE: predicate.setAttributeNS(RDF_MS_BASE, u'rdf:resource', obj[0]) else: object = doc.createTextNode(unicode(obj[0])) predicate.appendChild(object)
return
def isResource(self, res): return Uri.MatchesUriSyntax(res)
def __sortStatementsForDump(self, statements): sorted = {} for statement in statements: s = statement.subject p = statement.predicate o = statement.object ot = statement.objectType if s not in sorted: sorted[s] = {} if p not in sorted[s]: sorted[s][p] = [] sorted[s][p].append((o, ot)) return sorted
#6.1 def deserialize(self, model, node, scope=None): """Generate RDF statements from an XML serialization and insert these into a Model.""" rdf_nodes = node.xpath('.//rdf:RDF', explicitNss={'rdf': RDF_MS_BASE}) if not rdf_nodes: rdf_nodes = [node] for r in rdf_nodes: for child in r.childNodes: if child.nodeType != Node.ELEMENT_NODE: continue self.readObject(model, child, scope) return
#6.2 def readObject(self, model, node, scope): if node.namespaceURI == RDF_MS_BASE and node.localName in ['Bag', 'Seq', 'Alt']: return self.readContainer(model, node, scope), OBJECT_TYPE_RESOURCE else: return self.readDescription(model, node, scope), OBJECT_TYPE_RESOURCE
#6.3 def readDescription(self, model, node, scope): try: suri = node.xmlBase is None and scope or node.xmlBase except: suri = scope
id, about, about_each, about_each_prefix = self.readIdAboutAttr(scope, node) bagId = self.readBagIdAttr(node) if bagId is not None: raise ParseException(ParseException.FEATURE_NOT_SUPPORTED, 'bagID') if about_each_prefix is not None: raise ParseException(ParseException.FEATURE_NOT_SUPPORTED, 'aboutEachPrefix') propertyAttrs = self.readPropertyAttrs(node) descUri = '' #reify = 0 if id is not None: descUri = self.uriFromParts(suri, '#', id) type_ = self.readTypeAttr(scope, node) if type_: stmt = Statement(descUri, RDF_MS_BASE + 'type', type_, scope=scope, objectType=OBJECT_TYPE_RESOURCE) model.add(stmt) subjects = [descUri] elif about is not None: subjects = [about] elif about_each is not None: #To add support, retrieve bag according to URI and add each item to subjects raise ParseException(ParseException.FEATURE_NOT_SUPPORTED, 'aboutEach') else: subjects = [model.generateBnode()]
returnReference = subjects[0]
if (node.namespaceURI, node.localName ) != (RDF_MS_BASE, 'Description'): #typed node: an implicit "rdf:Description" + rdf:type type = self.uriFromParts(suri, node.namespaceURI, node.localName) new_stmt = Statement(returnReference, RDF_MS_BASE+'type', type, scope=scope, objectType=OBJECT_TYPE_RESOURCE) model.add(new_stmt)
try: suri = node.xmlBase is None and scope or node.xmlBase except: suri = scope
for (namespaceURI, localName), (value, otype) in propertyAttrs.items(): for s in subjects: predicate = self.uriFromParts(suri, namespaceURI, localName) model.add(Statement(s, predicate, value, scope=scope, objectType=otype) )
self.readResource(model, node.childNodes, scope, subjects) return returnReference
#6.3 def readResource(self, model, nodeList, scope, subjects=None): subjects = subjects or [model.generateBnode()] #print "readResource", nodeList, subjects statements = [] for child in nodeList: if child.nodeType == Node.ELEMENT_NODE: statements.extend(self.readPropertyElt(model, child, subjects, scope) )
#When bagID is supported "statements" should be used to reify added stataments
## if reify: ## stCtr = 1 ## for st in statements: ## uri = st.reify(model) ## predicate = RDF_MS_BASE + '_%s' % stCtr ## stCtr = stCtr + 1 ## stmt = Statement(descUri, predicate, uri, scope=scope) ## model.add(stmt)
return subjects[0]
#6.4 def readContainer(self, model, node, scope): id, about, about_each, about_each_prefix = self.readIdAboutAttr( scope, node ) memberAttrs = self.readMemberAttrs(node) members = [ m for m in node.childNodes if (m.nodeType == Node.ELEMENT_NODE and m.namespaceURI == RDF_MS_BASE and m.localName == 'li') ]
#Make sure the the proper members are there based on type if node.localName == 'Bag': #A bag can have member* or memberAttrs* if len(memberAttrs) and len(members): raise ParseException(ParseException.INVALID_CONTAINER_PROPERTY) elif node.localName == 'Seq': #A seq can have member* or memberAttrs* if len(memberAttrs) and len(members): raise ParseException(ParseException.INVALID_CONTAINER_PROPERTY) elif node.localName == 'Alt': #A alt can have member+ or memberAttrs? if len(memberAttrs): if len(members): raise ParseException(ParseException.INVALID_CONTAINER_PROPERTY) elif len(memberAttrs) > 1: raise Exception("Only one memberAttr allowed in an Alt") elif not len(members): raise Exception("More than one member required on an Alt") else: raise Exception(INVALID_CONTAINER_TYPE, node.localName)
try: suri = node.xmlBase is None and scope or node.xmlBase except: suri = scope #if this doesn't have an id then we need to make one up if about: id = about elif id: origId = id if not self.isResource(id): id = self.uriFromParts(suri, '#', id) else: id = model.generateBnode()
stmts = [Statement(id, RDF_MS_BASE+'type', RDF_MS_BASE+node.localName, scope=scope, objectType=OBJECT_TYPE_RESOURCE)] for attrId,value in memberAttrs.items(): pred = RDF_MS_BASE + '_%s' % attrId if self.isResource(value): stmts.append(Statement(id, pred, value, scope=scope, objectType=OBJECT_TYPE_RESOURCE)) else: stmts.append(Statement(id, pred, value, scope=scope, objectType=OBJECT_TYPE_LITERAL))
model.add(stmts)
ctr = 1 for m in members: object = self.readResourceAttr(scope, m) obj_type = OBJECT_TYPE_RESOURCE children = m.childNodes if object and len(children): raise Exception("%s:%s can have rdf:resource or a child node, but not both." % (node.namespaceURI, node.localName)) if not object and not len(children): raise Exception("%s:%s must have rdf:resource or a child node" % (node.namespaceURI, node.localName)) #if len(children) > 0 and len(children) != 1 and children[0].nodeType != Node.TEXT_NODE: if not object: elems = [ e for e in children if e.nodeType == Node.ELEMENT_NODE ] if len(elems) == 1: object, obj_type = self.readObject(model, elems[0], scope) elif not elems: chunks = [ c.data for c in children ] object = ''.join(chunks) obj_type = OBJECT_TYPE_LITERAL else: raise Exception("%s:%s can only have one child element." % (node.namespaceURI, node.localName)) predicate = RDF_MS_BASE + '_%d' % ctr ctr = ctr + 1 stmt = Statement(id, predicate, object, scope=scope, objectType=obj_type) model.add(stmt) return id
#6.5, 6.6 def readIdAboutAttr(self, scope, node): defaultNsAllowed = node.namespaceURI == RDF_MS_BASE id = self.readRdfKeyAttribute(node, 'ID', defaultNsAllowed) if id is not None: self.validateIdSymbol(id)
try: suri = node.xmlBase is None and scope or node.xmlBase except: suri = scope about = self.readRdfKeyAttribute(node, 'about', defaultNsAllowed) if about is not None: # For now, we'll use BaseJoin just in case suri is not absolute. about = Uri.BaseJoin(suri, about) #about = urlparse.urljoin(suri, about)
about_each = self.readRdfKeyAttribute(node, 'aboutEach', defaultNsAllowed) if about_each is not None: # For now, we'll use BaseJoin just in case suri is not absolute. about_each = Uri.BaseJoin(suri, about_each) #about_each = urlparse.urljoin(suri, about_each)
about_each_prefix = self.readRdfKeyAttribute(node, 'aboutEachPrefix', defaultNsAllowed) if about_each_prefix is not None: # For now, we'll use BaseJoin just in case suri is not absolute. about_each_prefix = Uri.BaseJoin(suri, about_each_prefix) #about_each_prefix = urlparse.urljoin(suri, about_each_prefix)
if (id != None) + \ (about != None) + \ (about_each != None) + \ (about_each_prefix != None) > 1: raise Exception("Only one id, about, aboutEach or aboutEachPrefix allowed on %s:%s" % (node.namespaceURI,node.localName))
return (id, about, about_each, about_each_prefix)
#6.6 def readIdAttr(self, node): id = self.readRdfKeyAttribute(node, 'ID') if id is not None: self.validateIdSymbol(id) return id
#6.9 def readBagIdAttr(self, node): bid = self.readRdfKeyAttribute(node, 'bagID') if bid is not None: self.validateIdSymbol(bid) return bid
#6.10 def readPropertyAttrs(self, node): #http://www.w3.org/TR/rdf-syntax-grammar/#emptyPropertyElt #Says all property attrs besides rdf:type are literals props = {} for attr in node.attributes.values(): if attr.namespaceURI == XMLNS_NAMESPACE: continue if attr.namespaceURI == RDF_MS_BASE: if attr.localName == 'type': self.validateUriReference(attr.value) props[(RDF_MS_BASE, "type")] = (attr.value, OBJECT_TYPE_RESOURCE) elif attr.localName == 'value': props[(RDF_MS_BASE, "value")] = (attr.value, Language(node) or OBJECT_TYPE_LITERAL) elif attr.namespaceURI == XML_NAMESPACE: #Section 6 says xml:lang can be ignored as a property attr if attr.localName == 'lang': continue elif attr.namespaceURI: props[(attr.namespaceURI, attr.localName)] = (attr.value, Language(node) or OBJECT_TYPE_LITERAL) elif attr.localName not in ['about', 'aboutEach', 'ID', 'BagID', 'resource', 'parseType', 'aboutEachPrefix']: props[(attr.namespaceURI, attr.localName)] = (attr.value, Language(node) or OBJECT_TYPE_LITERAL) #print "readPropertyAttrs result:", props return props
#6.11 def readTypeAttr(self, scope, node): try: suri = node.xmlBase is None and scope or node.xmlBase except: suri = scope type_ = self.readRdfKeyAttribute(node, 'type') if type_ is not None: # For now, we'll use BaseJoin just in case suri is not absolute. type_ = Uri.BaseJoin(suri, type_) #type_ = urlparse.urljoin(suri, type_) return type_
#6.12 def readPropertyElt(self, model, node, subjects, scope): #< propName idAttr? > value </propName> #< propName idAttr? parseLiteral > literal </ propName > #< propName idAttr? parseResource > propertyElt* </ propName > #< propName idRefAttr? bagIdAttr? propAttr* />
statements = [] predicate = None object = None parseType = self.readParseType(node)
#The id representing the reification of the statement id = self.readIdAttr(node)
ns, localName = self.readPropName(node) #print "propertyElt", subjects, ns, localName
predicate = self.uriFromParts('', ns, localName)
#if ns == RDF_MS_BASE and predicate not in RDF_PREDICATES: # raise ParseException(ParseException.INVALID_PREDICATE, predicate)
force_type = None if predicate in [DAML_OIL_NS + "oneOf", OLD_DAML_OIL_NS + "oneOf", OWL_NS + "oneOf"]: #daml:oneOf / owl:oneOf are a special sort of property elements, which coerces #its members to be of rdf:type of the subject force_type = subjects[0]
if predicate in [OWL_NS + 'unionOf',OWL_NS + 'intersectionOf', OWL_NS + 'complementOf']: #owl descriptors (based on set operators) require their members #to be owl classes force_type = OWL_NS+'Class'
reify = 0 #Properties and values expressed in XML attribute form within #an empty XML element E by productions [6.10] and [6.12] are #equivalent to the same properties and values expressed as XML #content of a single Description element D which would become #the content of E. propertyAttrs = self.readPropertyAttrs(node) try: suri = node.xmlBase is None and scope or node.xmlBase except: suri = scope obj_type = OBJECT_TYPE_LITERAL if propertyAttrs: if node.hasChildNodes(): raise ParseException(ParseException.NONEMPTY_PROPELT_WITH_PROPATTRS, node.nodeName) if id: subj = self.uriFromParts(suri, '#', id) else: subj = self.readResourceAttr(scope, node) or \ model.generateBnode() for (a_nsuri, a_lname), (a_value, otype) in propertyAttrs.items(): pred = self.uriFromParts(suri, a_nsuri, a_lname) stmt = Statement(subj, pred, a_value, scope=scope, objectType=otype) model.add(stmt) statements.append(stmt) object = subj else: object = self.readResourceAttr(scope, node) if object: obj_type = OBJECT_TYPE_RESOURCE if node.hasChildNodes(): raise ParseException(ParseException.NONEMPTY_PROPELT_WITH_RESATTR, node.nodeName) else: object, obj_type = self.readValue( model, node, scope, parseType, predicate, forceType=force_type ) #try: # object = self.readValue(model, node, scope, parseType, predicate) #except ParseException: # raise ParseException(ParseException.MULTIPLE_VALUE_OBJECTS, predicate) if id: reify = 1
#Note the difference. An resource object cannot be # an empty string (invalid URI Ref), but a literal object can. if object is None: return statements
for s in subjects: stmt = Statement(s, predicate, object, scope=scope, objectType=obj_type) model.add(stmt) statements.append(stmt) if reify: r_subj = Statement(id, RDF_SUBJ_PREDICATE, s, scope=suri, objectType=OBJECT_TYPE_RESOURCE) r_pred = Statement(id, RDF_OBJ_PREDICATE, object, scope=suri, objectType=OBJECT_TYPE_RESOURCE) r_obj = Statement(id, RDF_PRED_PREDICATE, predicate, scope=suri, objectType=obj_type) model.add([r_subj, r_pred, r_obj]) return statements
#6.14 def readPropName(self,node): propName = node.tagName return (node.namespaceURI, node.localName)
#6.17 def readValue(self, model, node, scope, parseType, predicate, forceType=None): # value ::= obj | string #print 'readValue', node, parseType obj_type = OBJECT_TYPE_RESOURCE if parseType == (EMPTY_NAMESPACE, u'Resource'): id, about, about_each, about_each_prefix = self.readIdAboutAttr( scope, node ) if id: return self.readResource(model, node.childNodes, scope, subjects=[id]), OBJECT_TYPE_RESOURCE elif about: return self.readResource(model, node.childNodes, scope, subjects=[about]), OBJECT_TYPE_RESOURCE else: return self.readResource(model, node.childNodes, scope), OBJECT_TYPE_RESOURCE elif parseType == (EMPTY_NAMESPACE, u'Literal'): stream = cStringIO.StringIO() for child in node.childNodes: Domlette.Print(child, stream) return stream.getvalue(), Language(node) or OBJECT_TYPE_LITERAL elif parseType in [(DAML_OIL_NS, 'collection'), (OLD_DAML_OIL_NS, 'collection')]: elementNodes = filter(lambda x: x.nodeType == Node.ELEMENT_NODE, node.childNodes) try: return self.readDamlCollection(model, elementNodes, scope, node.xmlBase, forceType), OBJECT_TYPE_RESOURCE #FIXME: This exception could catch too much except AttributeError: return self.readDamlCollection(model, elementNodes, scope, scope, forceType), OBJECT_TYPE_RESOURCE
elif parseType == (EMPTY_NAMESPACE, u'Collection'): elementNodes = filter(lambda x: x.nodeType == Node.ELEMENT_NODE, node.childNodes) try: return self.readCollection(model, elementNodes, scope, node.xmlBase, forceType), OBJECT_TYPE_RESOURCE #FIXME: see above except AttributeError: return self.readCollection(model, elementNodes, scope, scope, forceType), OBJECT_TYPE_RESOURCE
elementNodes = filter(lambda x: x.nodeType == Node.ELEMENT_NODE, node.childNodes) if len(elementNodes) == 1: # object, possibly typed node obj_elem = elementNodes[0] if obj_elem.namespaceURI == RDF_MS_BASE and obj_elem.localName in CONTAINERS: return self.readContainer(model, obj_elem, scope), OBJECT_TYPE_RESOURCE else: return self.readDescription(model, obj_elem, scope), OBJECT_TYPE_RESOURCE elif elementNodes: # error raise ParseException(ParseException.MULTIPLE_VALUE_OBJECTS, predicate) else: # string textNodes = filter(lambda x: x.nodeType == Node.TEXT_NODE, node.childNodes) if not len(textNodes): return None, Language(node) or OBJECT_TYPE_LITERAL rt = '' for t in textNodes: rt = rt + self.readString(t.data) return rt, Language(node) or OBJECT_TYPE_LITERAL #2.16 def readCollection(self, model, nodeList, scope, xmlBase, forceType=None): if not nodeList: return OWL_NS + 'Nothing' list = model.generateBnode() first, first_obj_type = self.readObject(model, nodeList[0], scope) if forceType: #Remove redundant forced type statements model.removePattern(first,RDF_MS_BASE + 'type',forceType)
#Set forced type statements stmts = [ Statement(first, RDF_MS_BASE + 'type', forceType, scope=scope, objectType=OBJECT_TYPE_RESOURCE), ] model.add(stmts)
rest = self.readCollection(model, nodeList[1:], scope, xmlBase, forceType) stmts = [ Statement(list, RDF_MS_BASE + 'type', RDF_MS_BASE + 'List', scope=scope, objectType=OBJECT_TYPE_RESOURCE), Statement(list, RDF_MS_BASE + 'first', first, scope=scope, objectType=first_obj_type), Statement(list, RDF_MS_BASE + 'rest', rest, scope=scope, objectType=OBJECT_TYPE_RESOURCE), ] model.add(stmts) return list
def readDamlCollection(self, model, nodeList, scope, xmlBase, forceType=None): suri = xmlBase if not nodeList: return DAML_OIL_NS + 'nil' list = model.generateBnode() first, first_obj_type = self.readObject(model, nodeList[0], scope) if forceType: #Remove redundant daml:Thing type stataments stmts = [Statement(first, RDF_MS_BASE + 'type', DAML_OIL_NS + 'Thing', scope=suri, objectType=OBJECT_TYPE_RESOURCE), Statement(first, RDF_MS_BASE + 'type', OLD_DAML_OIL_NS + 'Thing', scope=suri, objectType=OBJECT_TYPE_RESOURCE)] model.remove(stmts) #Handle daml:oneOf special case for enum typing stmts = [ Statement(first, RDF_MS_BASE + 'type', forceType, scope=scope, objectType=OBJECT_TYPE_RESOURCE), ] model.add(stmts)
rest = self.readDamlCollection(model, nodeList[1:], scope, xmlBase, forceType) stmts = [ Statement(list, RDF_MS_BASE + 'type', DAML_OIL_NS + 'List', scope=suri, objectType=OBJECT_TYPE_RESOURCE), Statement(list, DAML_OIL_NS + 'first', first, scope=suri, objectType=first_obj_type), Statement(list, DAML_OIL_NS + 'rest', rest, scope=scope, objectType=OBJECT_TYPE_RESOURCE), ] model.add(stmts) return list
#6.18 def readResourceAttr(self, scope, node): #RDF M&S technically doesn't allow the qualified form, #But user/implementor consensus allows this under the #vague XML NS concept of global attrs try: suri = node.xmlBase is None and scope or node.xmlBase except: suri = scope resource = self.readRdfKeyAttribute(node, 'resource') if resource is not None: # For now, we'll use BaseJoin just in case suri is not absolute. resource = Uri.BaseJoin(suri, resource) #resource = urlparse.urljoin(suri, resource) return resource
def readRdfKeyAttribute(self, node, local, defaultNsAllowed=1): """ Returns None if the attribute is not on the element in null or RDF namespace, otherwise returns the attribute value Note that RDF M&S technically doesn't allow the qualified form, But user/implementor consensu allows this under the XML NS concept of global attrs """ val = None local = unicode(local) if node.hasAttributeNS(RDF_MS_BASE, local): val = node.getAttributeNS(RDF_MS_BASE, local) elif defaultNsAllowed and node.hasAttributeNS(EMPTY_NAMESPACE, local): val = node.getAttributeNS(EMPTY_NAMESPACE, local) return val
#6.24 def readString(self, st): self.validateString(st) return st
#6.31 def readMemberAttrs(self, node): attrs = {} for attr in node.attributes.values(): if attr.namespaceURI == XMLNS_NAMESPACE: continue if (attr.namespaceURI, attr.localName[0]) == (RDF_MS_BASE, '_'): attrs[attr.localName[1:]] = attr.value return attrs
# 6.32, 6.33 def readParseType(self, node): parse_type = None if node.hasAttributeNS(EMPTY_NAMESPACE, u'parseType') or node.hasAttributeNS(RDF_MS_BASE, u'parseType'): parse_type_attr = node.getAttributeNS(EMPTY_NAMESPACE, u'parseType') or node.getAttributeNS(RDF_MS_BASE, u'parseType') parse_type = Util.ExpandQName(parse_type_attr, refNode=node) #FIXME: Only necessary until we fix no ns == None everywhere #if not parse_type[0]: parse_type[0] = None if parse_type not in VALID_PARSETYPES: # See paragarph 3 following BNF in section 6 # for defaulting of parseType parse_type = (EMPTY_NAMESPACE, u'Literal') return parse_type
def uriFromParts(self, baseUri, part1, part2): """ From RDF-MS, part 6:
'...the expansion of the namespace-qualified tag name (Generic Identifier) of E. This expansion is generated by concatenating the namespace name given in the namespace declaration with the LocalPart of the qualified name.' ... 'URI-References are resolved to resource identifiers by first resolving the URI-reference to absolute form as specified by [RFC 2396] using the base URI of the document in which the RDF statements appear.' """ initial = (part1 or "") + (part2 or "") # For now, we'll use BaseJoin just in case suri is not absolute. resolved = Uri.BaseJoin((baseUri or ''), initial) #resolved = urlparse.urljoin((baseUri or ""), initial) return resolved
def splitUri(self, uri): """ If there's a fragment, returns (base+'#', fragment); otherwise returns ('', uri) """ index = uri.find('#') if index == -1: return ('', uri) return (uri[:index+1], uri[index+1:])
def validateIdSymbol(self, idSym): #FIXME Validate? return 1
def validateUriReference(self, ref): #FIXME Validate? return 1
def validateString(self, st): #FIXME Validate? return 1
|