diff options
| author | Ivan Herman <ivan@ivan-herman.net> | 2014-12-08 12:53:28 +0100 |
|---|---|---|
| committer | Ivan Herman <ivan@ivan-herman.net> | 2014-12-08 12:53:28 +0100 |
| commit | b082c4851840f4c2c83910f84331fb07fca16f4c (patch) | |
| tree | b73b000661b528f2ce1f41d8e66c275931169c51 | |
| parent | f21e62d2cc6406870685faaeeffc0ef2afc1a499 (diff) | |
| download | rdflib-microdata-to-rdf-second-edition-bak.tar.gz | |
Microdata parser: updated the parser to the latest version of the microdata->rdf note (published in December 2014)microdata-to-rdf-second-edition-bak
| -rw-r--r-- | rdflib/plugins/parsers/pyMicrodata/__init__.py | 136 | ||||
| -rw-r--r-- | rdflib/plugins/parsers/pyMicrodata/microdata.py | 523 | ||||
| -rw-r--r-- | rdflib/plugins/parsers/pyMicrodata/registry.py | 112 | ||||
| -rw-r--r-- | rdflib/plugins/parsers/pyMicrodata/utils.py | 73 | ||||
| -rw-r--r-- | rdflib/plugins/parsers/structureddata.py | 32 |
5 files changed, 306 insertions, 570 deletions
diff --git a/rdflib/plugins/parsers/pyMicrodata/__init__.py b/rdflib/plugins/parsers/pyMicrodata/__init__.py index 58fd29d0..2d8c8ccd 100644 --- a/rdflib/plugins/parsers/pyMicrodata/__init__.py +++ b/rdflib/plugins/parsers/pyMicrodata/__init__.py @@ -48,14 +48,13 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -__version__ = "1.2" +__version__ = "2.0" __author__ = 'Ivan Herman' __contact__ = 'Ivan Herman, ivan@w3.org' import sys import datetime -import os import rdflib from rdflib import URIRef @@ -92,7 +91,7 @@ class MicrodataError(Exception) : def __init__(self, msg) : self.msg = msg Exception.__init__(self) - + class HTTPError(MicrodataError) : """Raised when HTTP problems are detected. It does not add any new functionality to the Exception class.""" @@ -105,19 +104,15 @@ class HTTPError(MicrodataError) : # Default bindings. This is just for the beauty of things: bindings are added to the graph to make the output nicer. If this is not done, RDFlib defines prefixes like "_1:", "_2:" which is, though correct, ugly... _bindings = { - 'owl' : 'http://www.w3.org/2002/07/owl#', 'gr' : 'http://purl.org/goodrelations/v1#', 'cc' : 'http://creativecommons.org/ns#', 'sioc' : 'http://rdfs.org/sioc/ns#', 'skos' : 'http://www.w3.org/2004/02/skos/core#', 'rdfs' : 'http://www.w3.org/2000/01/rdf-schema#', 'foaf' : 'http://xmlns.com/foaf/0.1/', - 'void' : 'http://rdfs.org/ns/void#', - 'ical' : 'http://www.w3.org/2002/12/cal/icaltzd#', 'vcard' : 'http://www.w3.org/2006/vcard/ns#', - 'og' : 'http://ogp.me/ns#', 'rdf' : 'http://www.w3.org/1999/02/22-rdf-syntax-ns#', - 'ma' : 'http://www.w3.org/ns/ma-ont#', + 'xsd' : 'http://www.w3.org/2001/XMLSchema#' } ######################################################################################################### @@ -126,65 +121,64 @@ class pyMicrodata : @ivar base: the base value for processing @ivar http_status: HTTP Status, to be returned when the package is used via a CGI entry. Initially set to 200, may be modified by exception handlers """ - def __init__(self, base = "", vocab_expansion = False, vocab_cache = True) : + def __init__(self, base = "") : """ @keyword base: URI for the default "base" value (usually the URI of the file to be processed) - @keyword vocab_expansion: whether vocab expansion should be performed or not - @type vocab_expansion: Boolean - @keyword vocab_cache: if vocabulary expansion is done, then perform caching of the vocabulary data - @type vocab_cache: Boolean """ self.http_status = 200 self.base = base - self.vocab_expansion = vocab_expansion - self.vocab_cache = vocab_cache def _generate_error_graph(self, pgraph, full_msg, uri = None) : """ Generate an error message into the graph. This method is usually used reacting on exceptions. - + Later versions of pyMicrodata may have more detailed error conditions on which it wishes to react. At the moment, this is fairly crude... """ - if pgraph == None : + if pgraph is None : retval = Graph() else : retval = pgraph - - pgraph.bind( "dc","http://purl.org/dc/terms/" ) - pgraph.bind( "xsd",'http://www.w3.org/2001/XMLSchema#' ) - pgraph.bind( "ht",'http://www.w3.org/2006/http#' ) - pgraph.bind( "pyMicrodata",'http://www.w3.org/2012/pyMicrodata/vocab#' ) + + pgraph.bind("dc", "http://purl.org/dc/terms/") + pgraph.bind("xsd", 'http://www.w3.org/2001/XMLSchema#') + pgraph.bind("ht", 'http://www.w3.org/2006/http#') + pgraph.bind("pyMicrodata", 'http://www.w3.org/2012/pyMicrodata/vocab#') bnode = BNode() retval.add((bnode, ns_rdf["type"], ns_micro["Error"])) retval.add((bnode, ns_dc["description"], Literal(full_msg))) retval.add((bnode, ns_dc["date"], Literal(datetime.datetime.utcnow().isoformat(),datatype=ns_xsd["dateTime"]))) - - if uri != None : + + if uri is not None : htbnode = BNode() - retval.add( (bnode, ns_micro["context"],htbnode) ) - retval.add( (htbnode, ns_rdf["type"], ns_ht["Request"]) ) - retval.add( (htbnode, ns_ht["requestURI"], Literal(uri)) ) - - if self.http_status != None and self.http_status != 200: + retval.add((bnode, ns_micro["context"],htbnode)) + retval.add((htbnode, ns_rdf["type"], ns_ht["Request"])) + retval.add((htbnode, ns_ht["requestURI"], Literal(uri))) + + if self.http_status is not None and self.http_status != 200 : htbnode = BNode() - retval.add( (bnode, ns_micro["context"],htbnode) ) - retval.add( (htbnode, ns_rdf["type"], ns_ht["Response"]) ) - retval.add( (htbnode, ns_ht["responseCode"], URIRef("http://www.w3.org/2006/http#%s" % self.http_status)) ) + retval.add((bnode, ns_micro["context"],htbnode)) + retval.add((htbnode, ns_rdf["type"], ns_ht["Response"])) + retval.add((htbnode, ns_ht["responseCode"], URIRef("http://www.w3.org/2006/http#%s" % self.http_status))) return retval - + def _get_input(self, name) : """ Trying to guess whether "name" is a URI, a string; it then tries to open these as such accordingly, returning a file-like object. If name is a plain string then it returns the input argument (that should - be, supposidly, a file-like object already) + be, supposedly, a file-like object already) @param name: identifier of the input source @type name: string or a file-like object @return: a file like object if opening "name" is possible and successful, "name" otherwise """ - isstring = isinstance(name, string_types) + try : + # Python 2 branch + isstring = isinstance(name, basestring) + except : + # Python 3 branch + isstring = isinstance(name, str) if isstring : # check if this is a URI, ie, if there is a valid 'scheme' part @@ -194,11 +188,11 @@ class pyMicrodata : self.base = url_request.location return url_request.data else : - self.base = 'file://'+name - return open(name, 'rb') + self.base = name + return file(name) else : return name - + #################################################################################################################### # Externally used methods # @@ -212,23 +206,19 @@ class pyMicrodata : @return: an RDF Graph @rtype: rdflib Graph instance """ - if graph == None : + if graph is None : # Create the RDF Graph, that will contain the return triples... - graph = Graph() + graph = Graph() - conversion = MicrodataConversion(dom.documentElement, - graph, - base = self.base, - vocab_expansion = self.vocab_expansion, - vocab_cache = self.vocab_cache) + conversion = MicrodataConversion(dom.documentElement, graph, base = self.base) conversion.convert() return graph - + def graph_from_source(self, name, graph = None, rdfOutput = False) : """ Extract an RDF graph from an microdata source. The source is parsed, the RDF extracted, and the RDF Graph is returned. This is a front-end to the L{pyMicrodata.graph_from_DOM} method. - + @param name: a URI, a file name, or a file-like object @return: an RDF Graph @rtype: rdflib Graph instance @@ -250,7 +240,7 @@ class pyMicrodata : self.http_status = 500 if not rdfOutput : raise e return self._generate_error_graph(graph, str(e), uri=name) - + dom = None try : import warnings @@ -267,7 +257,7 @@ class pyMicrodata : e = sys.exc_info()[1] self.http_status = 400 if not rdfOutput : raise e - return self._generate_error_graph(graph, str(e), uri=name) + return self._generate_error_graph(graph, str(e), uri=name) except Exception : # Something nasty happened:-( @@ -278,8 +268,8 @@ class pyMicrodata : self.http_status = 500 if not rdfOutput : raise e return self._generate_error_graph(graph, str(e), uri=name) - - def rdf_from_sources(self, names, outputFormat = "pretty-xml", rdfOutput = False) : + + def rdf_from_sources(self, names, outputFormat = "turtle", rdfOutput = False) : """ Extract and RDF graph from a list of RDFa sources and serialize them in one graph. The sources are parsed, the RDF extracted, and serialization is done in the specified format. @@ -295,14 +285,14 @@ class pyMicrodata : graph = Graph() for prefix in _bindings : - graph.bind(prefix,Namespace(_bindings[prefix])) + graph.bind(prefix, Namespace(_bindings[prefix])) # the value of rdfOutput determines the reaction on exceptions... for name in names : self.graph_from_source(name, graph, rdfOutput) return graph.serialize(format=outputFormat) - def rdf_from_source(self, name, outputFormat = "pretty-xml", rdfOutput = False) : + def rdf_from_source(self, name, outputFormat = "turtle", rdfOutput = False) : """ Extract and RDF graph from an RDFa source and serialize it in one graph. The source is parsed, the RDF extracted, and serialization is done in the specified format. @@ -318,7 +308,7 @@ def processURI(uri, outputFormat, form) : """The standard processing of a microdata uri options in a form, ie, as an entry point from a CGI call. The call accepts extra form options (eg, HTTP GET options) as follows: - + @param uri: URI to access. Note that the "text:" and "uploaded:" values are treated separately; the former is for textual intput (in which case a StringIO is used to get the data) and the latter is for uploaded file, where the form gives access to the file directly. @param outputFormat: serialization formats, as understood by RDFLib. Note that though "turtle" is a possible parameter value, some versions of the RDFLib turtle generation does funny (though legal) things with @@ -328,39 +318,25 @@ def processURI(uri, outputFormat, form) : @return: serialized graph @rtype: string """ - def _get_option(param, compare_value, default) : - param_old = param.replace('_','-') - if param in list(form.keys()) : - val = form.getfirst(param).lower() - return val == compare_value - elif param_old in list(form.keys()) : - # this is to ensure the old style parameters are still valid... - # in the old days I used '-' in the parameters, the standard favours '_' - val = form.getfirst(param_old).lower() - return val == compare_value - else : - return default if uri == "uploaded:" : - input = form["uploaded"].file - base = "" + input = form["uploaded"].file + base = "" elif uri == "text:" : - input = StringIO(form.getfirst("text")) - base = "" + input = StringIO(form.getfirst("text")) + base = "" else : - input = uri - base = uri - - vocab_cache = _get_option( "vocab_cache", "true", True) - vocab_expansion = _get_option( "vocab_expansion", "true", False) + input = uri + base = uri - processor = pyMicrodata(base = base, vocab_expansion = vocab_expansion, vocab_cache = vocab_cache) + processor = pyMicrodata(base = base) # Decide the output format; the issue is what should happen in case of a top level error like an inaccessibility of # the html source: should a graph be returned or an HTML page with an error message? - # decide whether HTML or RDF should be sent. + # decide whether HTML or RDF should be sent. htmlOutput = False + #import os #if 'HTTP_ACCEPT' in os.environ : # acc = os.environ['HTTP_ACCEPT'] # possibilities = ['text/html', @@ -393,7 +369,7 @@ def processURI(uri, outputFormat, form) : import cgi h = sys.exc_info()[1] retval = 'Content-type: text/html; charset=utf-8\nStatus: %s \n\n' % h.http_code - retval += "<html>\n" + retval += "<html>\n" retval += "<head>\n" retval += "<title>HTTP Error in Microdata processing</title>\n" retval += "</head><body>\n" @@ -411,7 +387,7 @@ def processURI(uri, outputFormat, form) : import traceback, cgi retval = 'Content-type: text/html; charset=utf-8\nStatus: %s\n\n' % processor.http_status - retval += "<html>\n" + retval += "<html>\n" retval += "<head>\n" retval += "<title>Exception in Microdata processing</title>\n" retval += "</head><body>\n" @@ -424,7 +400,7 @@ def processURI(uri, outputFormat, form) : retval +="<pre>%s</pre>\n" % value retval +="<h1>Distiller request details</h1>\n" retval +="<dl>\n" - if uri == "text:" and "text" in form and form["text"].value != None and len(form["text"].value.strip()) != 0 : + if uri == "text:" and "text" in form and form["text"].value is not None and len(form["text"].value.strip()) != 0 : retval +="<dt>Text input:</dt><dd>%s</dd>\n" % cgi.escape(form["text"].value).replace('\n','<br/>') elif uri == "uploaded:" : retval +="<dt>Uploaded file</dt>\n" diff --git a/rdflib/plugins/parsers/pyMicrodata/microdata.py b/rdflib/plugins/parsers/pyMicrodata/microdata.py index a783839c..611585cd 100644 --- a/rdflib/plugins/parsers/pyMicrodata/microdata.py +++ b/rdflib/plugins/parsers/pyMicrodata/microdata.py @@ -34,41 +34,26 @@ from rdflib import Literal from rdflib import BNode from rdflib import Namespace if rdflib.__version__ >= "3.0.0" : - from rdflib import Graph from rdflib import RDF as ns_rdf - from rdflib import RDFS as ns_rdfs from rdflib import XSD as ns_xsd else : - from rdflib.Graph import Graph - from rdflib.RDFS import RDFSNS as ns_rdfs - from rdflib.Literal import _XSD_NS as ns_xsd from rdflib.RDF import RDFNS as ns_rdf + from rdflib.Literal import _XSD_NS as ns_xsd ns_owl = Namespace("http://www.w3.org/2002/07/owl#") from .registry import registry, vocab_names -from .utils import generate_RDF_collection, get_Literal, get_time_type +from .utils import get_Literal, get_time_type from .utils import get_lang_from_hierarchy, is_absolute_URI, generate_URI, fragment_escape -MD_VOCAB = "http://www.w3.org/ns/md#" -RDFA_VOCAB = URIRef("http://www.w3.org/ns/rdfa#usesVocabulary") - from . import debug -# Existing predicate schemes -class PropertySchemes : - vocabulary = "vocabulary" - contextual = "contextual" - -class ValueMethod : - unordered = "unordered" - list = "list" - # ---------------------------------------------------------------------------- -class Evaluation_Context : + +class EvaluationContext : """ - Evaluation context structure. See Section 4.1 of the U{W3C IG Note<http://www.w3.org/TR/microdata-rdf/>}for the details. + Evaluation context structure. See Section 6.1 of the U{W3C IG Note<http://www.w3.org/TR/microdata-rdf/>}for the details. @ivar current_type : an absolute URL for the current type, used when an item does not contain an item type @ivar memory: mapping from items to RDF subjects @@ -76,13 +61,13 @@ class Evaluation_Context : @ivar current_name: an absolute URL for the in-scope name, used for generating URIs for properties of items without an item type @ivar current_vocabulary: an absolute URL for the current vocabulary, from the registry """ - def __init__( self ) : + def __init__(self) : self.current_type = None self.memory = {} self.current_name = None self.current_vocabulary = None - def get_memory( self, item ) : + def get_memory(self, item) : """ Get the memory content (ie, RDF subject) for 'item', or None if not stored yet @param item: an 'item', in microdata terminology @@ -94,7 +79,7 @@ class Evaluation_Context : else : return None - def set_memory( self, item, subject ) : + def set_memory(self, item, subject) : """ Set the memory content, ie, the subject, for 'item'. @param item: an 'item', in microdata terminology @@ -113,7 +98,7 @@ class Evaluation_Context : @param itype : an absolute URL for the current type @return: a new evaluation context instance """ - retval = Evaluation_Context() + retval = EvaluationContext() for k in self.memory : retval.memory[k] = self.memory[k] @@ -130,23 +115,22 @@ class Evaluation_Context : retval += " memory: %s\n" % self.memory retval += "----\n" return retval - + + class Microdata : """ - This class encapsulates methods that are defined by the U{microdata spec<http://dev.w3.org/html5/md/Overview.html>}, + This class encapsulates methods that are defined by the U{microdata spec<http://www.w3.org/TR/microdata/>}, as opposed to the RDF conversion note. @ivar document: top of the DOM tree, as returned by the HTML5 parser @ivar base: the base URI of the Dom tree, either set from the outside or via a @base element """ - def __init__( self, document, base = None) : + def __init__(self, document, base = None) : """ @param document: top of the DOM tree, as returned by the HTML5 parser @param base: the base URI of the Dom tree, either set from the outside or via a @base element """ self.document = document - - #----------------------------------------------------------------- # set the document base, will be used to generate top level URIs self.base = None # handle the base element case for HTML @@ -158,14 +142,14 @@ class Microdata : # If got here, ie, if no local setting for base occurs, the input argument has it self.base = base - def get_top_level_items( self ) : + def get_top_level_items(self) : """ - A top level item is and element that has the @itemscope set, but no @itemtype. They have to - be collected in pre-order and depth-first fashion. + A top level item is and element that has the @itemscope set, but no @itemtype. They are + collected in pre-order and depth-first fashion. @return: list of items (ie, DOM Nodes) """ - def collect_items( node ) : + def collect_items(node) : items = [] for child in node.childNodes : if child.nodeType == node.ELEMENT_NODE : @@ -177,29 +161,29 @@ class Microdata : return items - return collect_items( self.document ) - - def get_item_properties( self, item ) : + return collect_items(self.document) + + def get_item_properties(self, item) : """ - Collect the item's properties, ie, all DOM descendent nodes with @itemprop until the subtree hits another - @itemscope. @itemrefs are also added at this point. + Collect the item's properties, ie, all DOM descendant nodes with @itemprop until the subtree hits another @itemscope. @itemrefs are also added at this point. @param item: current item @type item: DOM Node @return: array of items, ie, DOM Nodes """ # go down the tree until another itemprop is hit, take care of the itemrefs, too; see the microdata doc - # probably the ugliest stuff + # probably the ugliest stuff around! # returns a series of element nodes. # Is it worth filtering the ones with itemprop at that level??? results = [] - memory = [ item ] - pending = [ child for child in item.childNodes if child.nodeType == item.ELEMENT_NODE ] - + memory = [item] + pending = [child for child in item.childNodes if child.nodeType == item.ELEMENT_NODE] + + # Add the possible "@itemref" targets to the nodes to work on if item.hasAttribute("itemref") : - for id in item.getAttribute("itemref").strip().split() : - obj = self.getElementById(id) - if obj != None : pending.append(obj) + for it in item.getAttribute("itemref").strip().split() : + obj = self.getElementById(it) + if obj is not None : pending.append(obj) while len(pending) > 0 : current = pending.pop(0) @@ -213,10 +197,12 @@ class Microdata : # @itemscope is the barrier... if not current.hasAttribute("itemscope") : - pending = [ child for child in current.childNodes if child.nodeType == child.ELEMENT_NODE ] + pending + pending = [child for child in current.childNodes if child.nodeType == child.ELEMENT_NODE] + pending if current.hasAttribute("itemprop") and current.getAttribute("itemprop").strip() != "" : results.append(current) + elif current.hasAttribute("itemprop-reverse") and current.getAttribute("itemprop-reverse").strip() != "" : + results.append(current) return results @@ -225,24 +211,25 @@ class Microdata : @param id: value of an @id attribute to look for @return: array of nodes whose @id attribute matches C{id} (formally, there should be only one...) """ - def collect_ids( node ) : - ids = [] + def collect_ids(node) : + lids = [] for child in node.childNodes : if child.nodeType == node.ELEMENT_NODE : - ids += collect_ids( child ) + lids += collect_ids(child) if node.hasAttribute("id") and node.getAttribute("id") == id : # This is also a top level item - ids.append(node) + lids.append(node) - return ids + return lids ids = collect_ids(self.document) if len(ids) > 0 : return ids[0] else : return None - + + class MicrodataConversion(Microdata) : """ Top level class encapsulating the conversion algorithms as described in the W3C note. @@ -250,42 +237,23 @@ class MicrodataConversion(Microdata) : @ivar graph: an RDF graph; an RDFLib Graph @type graph: RDFLib Graph @ivar document: top of the DOM tree, as returned by the HTML5 parser - @ivar ns_md: the Namespace for the microdata vocabulary @ivar base: the base of the Dom tree, either set from the outside or via a @base element + @ivar subs: dictionary mapping predicates to possible superproperties + @ivar bnodes: dictionary mapping items to bnodes (to be used when an item is the target of an @itemref) """ - def __init__( self, document, graph, base = None, vocab_expansion = False, vocab_cache = True ) : + def __init__(self, document, graph, base = None) : """ @param graph: an RDF graph; an RDFLib Graph @type graph: RDFLib Graph @param document: top of the DOM tree, as returned by the HTML5 parser @keyword base: the base of the Dom tree, either set from the outside or via a @base element - @keyword vocab_expansion: whether vocab expansion should be performed or not - @type vocab_expansion: Boolean - @keyword vocab_cache: if vocabulary expansion is done, then perform caching of the vocabulary data - @type vocab_cache: Boolean """ Microdata.__init__(self, document, base) - self.vocab_expansion = vocab_expansion - self.vocab_cache = vocab_cache - self.graph = graph - self.ns_md = Namespace( MD_VOCAB ) - self.graph.bind( "md",MD_VOCAB ) - self.vocabularies_used = False + self.graph = graph + self.subs = {} + self.bnodes = {} # Get the vocabularies defined in the registry bound to proper names, if any... - - def _use_rdfa_context () : - try : - from ..pyRdfa.initialcontext import initial_context - except : - from pyRdfa.initialcontext import initial_context - retval = {} - vocabs = initial_context["http://www.w3.org/2011/rdfa-context/rdfa-1.1"].ns - for prefix in list(vocabs.keys()) : - uri = vocabs[prefix] - if uri not in vocab_names and uri not in registry : retval[uri] = prefix - return retval - for vocab in registry : if vocab in vocab_names : self.graph.bind( vocab_names[vocab],vocab ) @@ -296,241 +264,210 @@ class MicrodataConversion(Microdata) : # Add the prefixes defined in the RDFa initial context to improve the outlook of the output # I put this into a try: except: in case the pyRdfa package is not available... - try : - try : - from ..pyRdfa.initialcontext import initial_context - except : - from pyRdfa.initialcontext import initial_context - vocabs = initial_context["http://www.w3.org/2011/rdfa-context/rdfa-1.1"].ns - for prefix in list(vocabs.keys()) : - uri = vocabs[prefix] - if uri not in registry : - # if it is in the registry, then it may have needed some special microdata massage... - self.graph.bind( prefix,uri ) - except : - pass - - def convert( self ) : + # This is put in a debug branch; in general, the RDFLib Turtle serializer adds all the + # namespace declarations, which can be a bit of a problem for reading the results... + + # try : + # try : + # from ..pyRdfa.initialcontext import initial_context + # except : + # from pyRdfa.initialcontext import initial_context + # vocabs = initial_context["http://www.w3.org/2011/rdfa-context/rdfa-1.1"].ns + # for prefix in list(vocabs.keys()) : + # uri = vocabs[prefix] + # if uri not in registry : + # # if it is in the registry, then it may have needed some special microdata massage... + # self.graph.bind(prefix,uri) + # except : + # pass + + def convert(self) : """ Top level entry to convert and generate all the triples. It finds the top level items, - and generates triples for each of them; additionally, it generates a top level entry point - to the items from base in the form of an RDF list. + and generates triples for each of them. """ - item_list = [] for top_level_item in self.get_top_level_items() : - item_list.append( self.generate_triples(top_level_item, Evaluation_Context()) ) - list = generate_RDF_collection( self.graph, item_list ) - self.graph.add( (URIRef(self.base),self.ns_md["item"],list) ) - - # If the vocab expansion is also switched on, this is the time to do it. + self.generate_triples(top_level_item, EvaluationContext()) - # This is the version with my current proposal: the basic expansion is always there; - # the follow-your-nose inclusion of vocabulary is optional - if self.vocabularies_used : - try : - try : - from ..pyRdfa.rdfs.process import MiniOWL, process_rdfa_sem - from ..pyRdfa.options import Options - except : - from pyRdfa.rdfs.process import MiniOWL, process_rdfa_sem - from pyRdfa.options import Options - # if we did not get here, the pyRdfa package could not be - # imported. Too bad, but life should go on in the except branch... - if self.vocab_expansion : - # This is the full deal - options = Options(vocab_expansion = self.vocab_expansion, vocab_cache = self.vocab_cache) - process_rdfa_sem(self.graph, options) - else : - MiniOWL(self.graph).closure() - except : - pass - - def generate_triples( self, item, context ) : + def generate_triples(self, item, context) : """ Generate the triples for a specific item. See the W3C Note for the details. @param item: the DOM Node for the specific item @type item: DOM Node @param context: an instance of an evaluation context - @type context: L{Evaluation_Context} + @type context: L{EvaluationContext} @return: a URIRef or a BNode for the (RDF) subject """ + def _get_predicate_object(prop, name, item_type) : + """ + Generate the predicate and the object for an item that contains either "itemprop" or "itemprop-reverse". + Steps 9.1.1 to 9.1.3 of the processing steps + + @param prop: the item that should produce a predicate + @type prop: a DOM Node for an element + @param name: an itemprop or itemprop-reverse item + @type name: string + @param item_type: the type of the item; necessary for the creation of a new context + @type item_type: a string with the absolute URI of the type + @return: a tuple consisting of the predicate (URI) and the object for the triple to be generated + """ + # 9.1.1. set a new context + new_context = context.new_copy(item_type) + # 9.1.2, generate the URI for the property name, that will be the predicate + # Also update the context + # Note that the method also checks, and stores, the possible superproperty/equivalent property values + new_context.current_name = predicate = self.generate_predicate_URI(name, new_context) + # 9.1.3, generate the property value. The extra flag signals that the value is a new item + # Note that 9.1.4 step is done in the method itself, ie, a recursion may occur there + # if a new item is hit (in which case the return value is a RDF resource chaining to a subject) + # Note that the value may be None (e.g, for an <img> element without a @src), in which case nothing + # is generated + value = self.get_property_value(prop, new_context) + return (predicate, value) + # Step 1,2: if the subject has to be set, store it in memory - subject = context.get_memory( item ) - if subject == None : + subject = context.get_memory(item) + + if subject is None : # nop, there is no subject set. If there is a valid @itemid, that carries it - if item.hasAttribute("itemid") and is_absolute_URI( item.getAttribute("itemid") ): - subject = URIRef( item.getAttribute("itemid").strip() ) + if item.hasAttribute("itemid") : + subject = URIRef(generate_URI(self.base, item.getAttribute("itemid").strip())) else : - subject = BNode() - context.set_memory( item, subject ) + if item in self.bnodes : + subject = self.bnodes[item] + else : + subject = BNode() + self.bnodes[item] = subject + context.set_memory(item,subject) # Step 3: set the type triples if any types = [] if item.hasAttribute("itemtype") : types = item.getAttribute("itemtype").strip().split() - for t in types : - if is_absolute_URI( t ) : - self.graph.add( (subject, ns_rdf["type"], URIRef(t)) ) + for t in types: + if is_absolute_URI(t) : + self.graph.add((subject, ns_rdf["type"], URIRef(t))) - # Step 4, 5 and 6 to set the typing variable + # Step 4, 5 to set the typing variable if len(types) == 0 : itype = None else : if is_absolute_URI(types[0]) : itype = types[0] context.current_name = None - elif context.current_type != None : + elif context.current_type is not None : itype = context.current_type else : itype = None - # Step 7, 8, 9: Check the registry for possible keys and set the vocab + # Step 6, 7: Check the registry for possible keys and set the vocab vocab = None - if itype != None : + if itype is not None : for key in list(registry.keys()) : if itype.startswith(key) : # There is a predefined vocabulary for this type... vocab = key - # Step 7: Issue an rdfa usesVocabulary triple - self.graph.add( (URIRef(self.base), RDFA_VOCAB, URIRef(vocab))) - self.vocabularies_used = True break - # The registry has not set the vocabulary; has to be extracted from the type - if vocab == None : + # The registry has not set the vocabulary; it has to be extracted from the type + if vocab is None : parsed = urlsplit(itype) if parsed.fragment != "" : - vocab = urlunsplit( (parsed.scheme,parsed.netloc,parsed.path,parsed.query,"") ) + '#' + vocab = urlunsplit((parsed.scheme, parsed.netloc, parsed.path, parsed.query,"")) + '#' elif parsed.path == "" and parsed.query == "" : vocab = itype if vocab[-1] != '/' : vocab += '/' else : - vocab = itype.rsplit('/',1)[0] + '/' + vocab = itype.rsplit('/', 1)[0] + '/' - # Step 9: update vocab in the context - if vocab != None : + # Step 8: update vocab in the context + if vocab is not None : context.current_vocabulary = vocab elif item.hasAttribute("itemtype") : context.current_vocabulary = None - # Step 10: set up a property list; this will be used to generate triples later. + # Step 9: Get the item properties and run a cycle on those # each entry in the dictionary is an array of RDF objects - property_list = {} - - # Step 11: Get the item properties and run a cycle on those for prop in self.get_item_properties(item) : for name in prop.getAttribute("itemprop").strip().split() : - # 11.1.1. set a new context - new_context = context.new_copy(itype) - # 11.1.2, generate the URI for the property name, that will be the predicate - # Also update the context - new_context.current_name = predicate = self.generate_predicate_URI( name,new_context ) - # 11.1.3, generate the property value. The extra flag signals that the value is a new item - # Note that 10.1.4 step is done in the method itself, ie, a recursion may occur there - # if a new item is hit (in which case the return value is a RDF resource chaining to a subject) - value = self.get_property_value( prop, new_context ) - # 11.1.5, store all the values - if predicate in property_list : - property_list[predicate].append(value) - else : - property_list[predicate] = [ value ] - - # step 12: generate the triples - for property in list(property_list.keys()) : - self.generate_property_values( subject, URIRef(property), property_list[property], context ) - - # Step 13: return the subject to the caller + # Steps 9.1.1 to 9.1.3 are done in a separate function + (predicate, value) = _get_predicate_object(prop, name, itype) + if value is None : continue + # 9.1.5, generate the triple + self.graph.add((subject, URIRef(predicate), value)) + # 9.1.6, take care of the possible subProperty/equivalentProperty + if name in self.subs and self.subs[name] is not None : + for sup in self.subs[name] : + self.graph.add((subject, sup, value)) + + # Step 10: Almost identical to step 9, except for itemprop-reverse + # The only difference is that a Literal value must be ignored + for prop in self.get_item_properties(item) : + for name in prop.getAttribute("itemprop-reverse").strip().split() : + # Steps 9.1.1 to 9.1.3 are done in a separate function + (predicate, value) = _get_predicate_object(prop, name, itype) + if value is None or isinstance(value, Literal) : + continue + # 9.1.5, generate the triple + self.graph.add((value, URIRef(predicate), subject)) + # 9.1.6, take care of the possible subProperty/equivalentProperty + if name in self.subs and self.subs[name] is not None : + for sup in self.subs[name] : + self.graph.add((value, sup, subject)) + + # Step 11: return the subject to the caller return subject - def generate_predicate_URI( self, name, context ) : + def generate_predicate_URI(self, name, context) : """ Generate a full URI for a predicate, using the type, the vocabulary, etc. For details of this entry, see Section 4.4 @param name: name of the property, ie, what appears in @itemprop @param context: an instance of an evaluation context - @type context: L{Evaluation_Context} + @type context: L{EvaluationContext} """ - if debug: print( "name: %s, %s" % (name,context) ) - + def add_to_subs(subpr) : + if subpr is not None : + if isinstance(subpr,list) : + self.subs[name] = [] + for p in subpr : + self.subs[name].append(URIRef(p)) + else : + self.subs[name] = [URIRef(subpr)] + # Step 1: absolute URI-s are fine, take them as they are if is_absolute_URI(name) : return name # Step 2: if type is none, that this is just used as a fragment # if not context.current_type : - if context.current_type == None and context.current_vocabulary == None : + if context.current_type is None and context.current_vocabulary is None : if self.base[-1] == '#' : b = self.base[:-1] else : b = self.base return b + '#' + fragment_escape(name) - #if context.current_type == None : - # return generate_URI( self.base, name ) - - # Step 3: set the scheme - try : - if context.current_vocabulary in registry and "propertyURI" in registry[context.current_vocabulary] : - scheme = registry[context.current_vocabulary]["propertyURI"] - else : - scheme = PropertySchemes.vocabulary - except : - # This is when the structure of the registry is broken - scheme = PropertySchemes.vocabulary - - name = fragment_escape( name ) - if scheme == PropertySchemes.contextual : - # Step 5.1 - s = context.current_name - # s = context.current_type - if s != None and s.startswith("http://www.w3.org/ns/md?type=") : - # Step 5.2 - expandedURI = s + '.' + name - else : - # Step 5.3 - expandedURI = "http://www.w3.org/ns/md?type=" + fragment_escape(context.current_type) + "&prop=" + name - else : - # Step 4 - if context.current_vocabulary[-1] == '#' or context.current_vocabulary[-1] == '/' : - expandedURI = context.current_vocabulary + name - else : - expandedURI = context.current_vocabulary + '#' + name - - # see if there are subproperty/equivalentproperty relations - try : - vocab_mapping = registry[context.current_vocabulary]["properties"][name] - # if we got that far, we may have some mappings - - expandedURIRef = URIRef(expandedURI) + # Extract the possible subproperty/equivalentProperty relations on the fly + # see if there are subproperty/equivalentProperty relations + if name not in self.subs : try : - subpr = vocab_mapping["subPropertyOf"] - if subpr != None : - if isinstance(subpr,list) : - for p in subpr : - self.graph.add( (expandedURIRef, ns_rdfs["subPropertyOf"], URIRef(p)) ) - else : - self.graph.add( (expandedURIRef, ns_rdfs["subPropertyOf"], URIRef(subpr)) ) + vocab_mapping = registry[context.current_vocabulary]["properties"][name] + for rel in ["subPropertyOf", "equivalentProperty"] : + if rel in vocab_mapping : + add_to_subs(vocab_mapping[rel]) except : - # Ok, no sub property - pass - try : - subpr = vocab_mapping["equivalentProperty"] - if subpr != None : - if isinstance(subpr,list) : - for p in subpr : - self.graph.add( (expandedURIRef, ns_owl["equivalentProperty"], URIRef(p)) ) - else : - self.graph.add( (expandedURIRef, ns_owl["equivalentProperty"], URIRef(subpr)) ) - except : - # Ok, no sub property - pass - except : - # no harm done, no extra vocabulary term - pass + # no harm done, no extra vocabulary term + self.subs[name] = None + else : + self.subs[name] = None + escaped_name = fragment_escape(name) + if context.current_vocabulary[-1] == '#' or context.current_vocabulary[-1] == '/' : + return context.current_vocabulary + escaped_name + else : + return context.current_vocabulary + '#' + escaped_name - return expandedURI - def get_property_value(self, node, context) : """ Generate an RDF object, ie, the value of a property. Note that if this element contains @@ -539,42 +476,53 @@ class MicrodataConversion(Microdata) : object. Otherwise, either URIRefs are created for <a>, <img>, etc, elements, or a Literal; the latter - gets a time-related type for the <time> element. + gets a time-related type for the <time> element, and possible numeric types for the @value + attribute of the <meter> and <data> elements. @param node: the DOM Node for which the property values should be generated @type node: DOM Node @param context: an instance of an evaluation context - @type context: L{Evaluation_Context} + @type context: L{EvaluationContext} @return: an RDF resource (URIRef, BNode, or Literal) """ URI_attrs = { + "a" : "href", "audio" : "src", + "area" : "href", "embed" : "src", "iframe" : "src", "img" : "src", + "link" : "href", + "object" : "data", "source" : "src", "track" : "src", - "video" : "src", - "data" : "src", - "a" : "href", - "area" : "href", - "link" : "href", - "object" : "data" + "video" : "src" } - lang = get_lang_from_hierarchy( self.document, node ) + lang = get_lang_from_hierarchy(self.document, node) if node.hasAttribute("itemscope") : # THIS IS A RECURSION ENTRY POINT! - return self.generate_triples( node, context ) + return self.generate_triples(node, context) - elif node.tagName in URI_attrs and node.hasAttribute(URI_attrs[node.tagName]) : - return URIRef( generate_URI( self.base, node.getAttribute(URI_attrs[node.tagName]).strip() ) ) + elif node.tagName in URI_attrs : + if node.hasAttribute(URI_attrs[node.tagName]) : + return URIRef(generate_URI(self.base, node.getAttribute(URI_attrs[node.tagName]).strip())) + else : + return None elif node.tagName == "meta" and node.hasAttribute("content") : if lang : - return Literal( node.getAttribute("content"), lang = lang ) + return Literal(node.getAttribute("content"), lang = lang) + else : + return Literal(node.getAttribute("content")) + + elif node.tagName == "time" and node.hasAttribute("datetime") : + litval = node.getAttribute("datetime") + dtype = get_time_type(litval) + if dtype : + return Literal(litval, datatype = dtype) else : - return Literal( node.getAttribute("content") ) + return Literal(litval) elif node.tagName == "meter" or node.tagName == "data" : if node.hasAttribute("value") : @@ -582,82 +530,21 @@ class MicrodataConversion(Microdata) : # check whether the attribute value can be defined as a float or an integer try : fval = int(val) - dt = ns_xsd["integer"] + return Literal(val, datatype = ns_xsd["integer"]) except : - # Well, not an int, try then a integer + # Well, not an int, try then a float try : fval = float(val) - dt = ns_xsd["float"] + return Literal(val, datatype = ns_xsd["double"]) except : # Sigh, this is not a valid value, but let it go through as a plain literal nevertheless - fval = val - dt = None - if dt : - return Literal( val, datatype = dt) - else : - return Literal( val ) + return Literal(val) else : - return Literal( "" ) - - elif node.tagName == "time" and node.hasAttribute("datetime") : - litval = node.getAttribute("datetime") - dtype = get_time_type(litval) - if dtype : - return Literal( litval, datatype = dtype ) - else : - return Literal( litval ) + return Literal("") else : if lang : - return Literal( get_Literal(node), lang = lang ) + return Literal(get_Literal(node), lang = lang) else : - return Literal( get_Literal(node) ) - - def generate_property_values( self, subject, predicate, objects, context) : - """ - Generate the property values for a specific subject and predicate. The context should specify whether - the objects should be added in an RDF list or each triples individually. - - @param subject: RDF subject - @type subject: RDFLib Node (URIRef or blank node) - @param predicate: RDF predicate - @type predicate: RDFLib URIRef - @param objects: RDF objects - @type objects: list of RDFLib nodes (URIRefs, Blank Nodes, or literals) - @param context: evaluation context - @type context: L{Evaluation_Context} - """ - # generate triples with a list, or a bunch of triples, depending on the context - # The biggest complication is to find the method... - method = ValueMethod.unordered - superproperties = None - - # This is necessary because predicate is a URIRef, and I am not sure the comparisons would work well - # to be tested, in fact... - pred_key = "%s" % predicate - for key in registry : - if predicate.startswith(key) : - # This the part of the registry corresponding to the predicate's vocabulary - registry_object = registry[key] - try : - if "multipleValues" in registry_object : method = registry_object["multipleValues"] - # The generic definition can be overwritten for a specific property. The simplest is to rely on a 'try' - # with the right structure... - try : - method = registry_object["properties"][pred_key[len(key):]]["multipleValues"] - except : - pass - except : - pass - - if method == ValueMethod.unordered : - for object in objects : - self.graph.add( (subject, predicate, object) ) - else : - self.graph.add( (subject,predicate,generate_RDF_collection( self.graph, objects )) ) - - - - - + return Literal(get_Literal(node)) diff --git a/rdflib/plugins/parsers/pyMicrodata/registry.py b/rdflib/plugins/parsers/pyMicrodata/registry.py index 22cec0ac..2e830eed 100644 --- a/rdflib/plugins/parsers/pyMicrodata/registry.py +++ b/rdflib/plugins/parsers/pyMicrodata/registry.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- """ -Hardcoded version of the current microdata->RDF registry. There is also a local registry to include some test cases. -Finally, there is a local dictionary for prefix mapping for the registry items; these are the preferred prefixes +Hardcoded version of the current microdata->RDF registry. +There is also a local dictionary for prefix mapping for the registry items; these are the preferred prefixes for those vocabularies, and are used to make the output nicer. @organization: U{World Wide Web Consortium<http://www.w3.org>} @@ -12,124 +12,34 @@ U{W3C® SOFTWARE NOTICE AND LICENSE<href="http://www.w3.org/Consortium/Legal/200 """ """ -$Id: registry.py,v 1.5 2012/09/05 16:40:43 ivan Exp $ -$Date: 2012/09/05 16:40:43 $ +$Id: registry.py,v 1.6 2012-12-01 22:46:57 ivan Exp $ +$Date: 2012-12-01 22:46:57 $ """ import sys (py_v_major, py_v_minor, py_v_micro, py_v_final, py_v_serial) = sys.version_info -# To be added soon: - # "Class" : {"subPropertyOf" : "http://www.w3.org/2000/01/rdf-schema#Class"}, - # "Property" : {"subPropertyOf" : "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property"} - _registry = """ { "http://schema.org/": { - "propertyURI": "vocabulary", - "multipleValues": "unordered", "properties": { - "additionalType": {"subPropertyOf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"}, - "blogPosts": {"multipleValues": "list"}, - "breadcrumb": {"multipleValues": "list"}, - "byArtist": {"multipleValues": "list"}, - "creator": {"multipleValues": "list"}, - "episode": {"multipleValues": "list"}, - "episodes": {"multipleValues": "list"}, - "event": {"multipleValues": "list"}, - "events": {"multipleValues": "list"}, - "founder": {"multipleValues": "list"}, - "founders": {"multipleValues": "list"}, - "itemListElement": {"multipleValues": "list"}, - "musicGroupMember": {"multipleValues": "list"}, - "performerIn": {"multipleValues": "list"}, - "actor": {"multipleValues": "list"}, - "actors": {"multipleValues": "list"}, - "performer": {"multipleValues": "list"}, - "performers": {"multipleValues": "list"}, - "producer": {"multipleValues": "list"}, - "recipeInstructions": {"multipleValues": "list"}, - "season": {"multipleValues": "list"}, - "seasons": {"multipleValues": "list"}, - "subEvent": {"multipleValues": "list"}, - "subEvents": {"multipleValues": "list"}, - "track": {"multipleValues": "list"}, - "tracks": {"multipleValues": "list"} + "additionalType": {"subPropertyOf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"} } }, - "http://microformats.org/profile/hcard": { - "propertyURI": "vocabulary", - "multipleValues": "unordered" - }, - "http://microformats.org/profile/hcalendar#": { - "propertyURI": "vocabulary", - "multipleValues": "unordered", - "properties": { - "categories": {"multipleValues": "list"} - } - } + + "http://microformats.org/profile/hcard": {} } """ vocab_names = { "http://schema.org/" : "schema", - "http://xmlns.com/foaf/0.1/" : "foaf", - "http://microformats.org/profile/hcard#" : "hcard", - "http://microformats.org/profile/hcalendar#" : "hcalendar" -} - -# This is the local version, added mainly for testing -_myRegistry = """ -{ - "http://vocabulary.list/": { - "propertyURI": "vocabulary", - "multipleValues": "list", - "properties": { - "list": {"multipleValues": "list"}, - "typed": {"datatype": "http://typed"} - } - }, - "http://vocabulary.unordered/": { - "propertyURI": "vocabulary", - "multipleValues": "unordered", - "properties": { - "list": {"multipleValues": "list"}, - "typed": {"datatype": "http://typed"} - } - }, - "http://contextual.unordered/": { - "propertyURI": "contextual", - "multipleValues": "unordered", - "properties": { - "list": {"multipleValues": "list"}, - "typed": {"datatype": "http://typed"} - } - }, - "http://contextual.list/": { - "propertyURI": "contextual", - "multipleValues": "list", - "properties": { - "list": {"multipleValues": "list"}, - "typed": {"datatype": "http://typed"} - } - }, - "http://n.whatwg.org/work": { - "propertyURI" : "contextual", - "multipleValues" : "list" - } + "http://microformats.org/profile/hcard#" : "hcard" } -""" - -registry = [] -myRegistry = [] +registry = [] if py_v_major >= 3 or (py_v_major == 2 and py_v_minor >= 6) : import json - registry = json.loads(_registry) - myRegistry = json.loads(_myRegistry) + registry = json.loads(_registry) else : import simplejson - registry = simplejson.loads(_registry) - myRegistry = simplejson.loads(_myRegistry) - -for (k,v) in list(myRegistry.items()) : registry[k] = v + registry = simplejson.loads(_registry) diff --git a/rdflib/plugins/parsers/pyMicrodata/utils.py b/rdflib/plugins/parsers/pyMicrodata/utils.py index 9ac25835..9ee905a4 100644 --- a/rdflib/plugins/parsers/pyMicrodata/utils.py +++ b/rdflib/plugins/parsers/pyMicrodata/utils.py @@ -9,41 +9,40 @@ U{W3C® SOFTWARE NOTICE AND LICENSE<href="http://www.w3.org/Consortium/Legal/200 """ """ -$Id: utils.py,v 1.7 2012/09/01 15:17:28 ivan Exp $ -$Date: 2012/09/01 15:17:28 $ +$Id: utils.py,v 1.8 2014-02-21 16:26:59 ivan Exp $ +$Date: 2014-02-21 16:26:59 $ """ -import os, os.path, sys +import sys, socket (py_v_major, py_v_minor, py_v_micro, py_v_final, py_v_serial) = sys.version_info +# The separate W3C branch is necessary for the local security setup at W3C. It is ugly to have this +# in the code, but I was lazy to make it more generic... +# With the inclusion of pyMicrodata into RDFLib, this service looses its importance anyway... if py_v_major >= 3 : - from urllib.request import Request, urlopen + import urllib.request + url_opener = urllib.request.build_opener() + from urllib.request import Request from urllib.parse import urljoin, quote, urlparse from http.server import BaseHTTPRequestHandler from urllib.error import HTTPError as urllib_HTTPError else : - from urllib2 import Request, urlopen + import urllib2 + url_opener = urllib2.build_opener() + from urllib2 import Request from urllib2 import HTTPError as urllib_HTTPError from urlparse import urljoin, urlparse from urllib import quote from BaseHTTPServer import BaseHTTPRequestHandler -import re from datetime import datetime -from rdflib import BNode -import rdflib -if rdflib.__version__ >= "3.0.0" : - from rdflib import RDF as ns_rdf -else : - from rdflib.RDF import RDFNS as ns_rdf - ################################################################################# -def is_absolute_URI( uri ) : +def is_absolute_URI(uri) : return urlparse(uri)[0] != "" ################################################################################# -def fragment_escape( name ) : +def fragment_escape(name) : return quote(name, '/~:-.') ################################################################################# @@ -55,7 +54,7 @@ def generate_URI(base, v) : @param base: Absolute URI for base @param v: relative or absolute URI """ - if is_absolute_URI( v ) : + if is_absolute_URI(v) : return v else : # UGLY!!! There is a bug for a corner case in python version <= 2.5.X @@ -78,24 +77,7 @@ def generate_URI(base, v) : return joined ################################################################################# -def generate_RDF_collection( graph, vals ) : - """ - Generate an RDF List from vals, returns the head of the list - @param graph: RDF graph - @type graph: RDFLib Graph - @param vals: array of RDF Resources - @return: head of the List (an RDF Resource) - """ - # generate an RDF List, returns the head - # list has all the elements in RDF format already - heads = [ BNode() for r in vals ] + [ ns_rdf["nil"] ] - for i in range(0, len(vals)) : - graph.add( (heads[i], ns_rdf["first"], vals[i]) ) - graph.add( (heads[i], ns_rdf["rest"], heads[i+1]) ) - return heads[0] - -################################################################################# -def get_Literal(Pnode): +def get_Literal(Pnode) : """ Get (recursively) the full text from a DOM Node. @@ -119,21 +101,21 @@ def get_Literal(Pnode): ################################################################################# def get_lang(node) : # we may have lang and xml:lang - retval = None + retval = None if node.hasAttribute("lang") : retval = node.getAttribute("lang") if retval and node.hasAttribute("xml:lang") : xmllang = node.getAttribute("xml:lang").lower() - if not( xmllang != None and xmllang == retval.lower() ) : + if not(xmllang is not None and xmllang == retval.lower()) : # This is an error, in which case retval must be invalidated... retval = None return retval def get_lang_from_hierarchy(document, node) : lang = get_lang(node) - if lang == None : + if lang is None : parent = node.parentNode - if parent != None and parent != document : + if parent is not None and parent != document : return get_lang_from_hierarchy(document, parent) else : return get_lang(document) @@ -174,7 +156,7 @@ _formats = { ], } -_dur_times = [ "%HH%MM%SS", "%HH", "%MM", "%SS", "%HH%MM", "%HH%SS", "%MM%SS" ] +_dur_times = ["%HH%MM%SS", "%HH", "%MM", "%SS", "%HH%MM", "%HH%SS", "%MM%SS"] def get_time_type(string) : """ @@ -223,7 +205,7 @@ def get_time_type(string) : break except ValueError : pass - if td == True : + if td : # Getting there... for format in _dur_times : try : @@ -240,7 +222,7 @@ def get_time_type(string) : return None # If we got here, we should check the time zone - # there is a discrepancy betwen the python and the HTML5/XSD lexical string, + # there is a discrepancy between the python and the HTML5/XSD lexical string, # which means that this has to handled separately for the date and the timezone portion try : # The time-zone-less portion of the string @@ -278,7 +260,7 @@ class URIOpener : @ivar headers: the return headers as sent back by the server @ivar location: the real location of the data (ie, after possible redirection and content negotiation) """ - CONTENT_LOCATION = 'Content-Location' + CONTENT_LOCATION = 'Content-Location' def __init__(self, name) : """ @param name: URL to be opened @@ -287,14 +269,13 @@ class URIOpener : try : # Note the removal of the fragment ID. This is necessary, per the HTTP spec req = Request(url=name.split('#')[0]) - req.add_header('Accept', 'text/html, application/xhtml+xml') - self.data = urlopen(req) - self.headers = self.data.info() + self.data = url_opener.open(req) + self.headers = self.data.info() if URIOpener.CONTENT_LOCATION in self.headers : - self.location = urlparse.urljoin(self.data.geturl(),self.headers[URIOpener.CONTENT_LOCATION]) + self.location = urlparse.urljoin(self.data.geturl(), self.headers[URIOpener.CONTENT_LOCATION]) else : self.location = name diff --git a/rdflib/plugins/parsers/structureddata.py b/rdflib/plugins/parsers/structureddata.py index fb96efda..e4058cd4 100644 --- a/rdflib/plugins/parsers/structureddata.py +++ b/rdflib/plugins/parsers/structureddata.py @@ -220,18 +220,10 @@ class MicrodataParser(Parser): @param graph: target graph for the triples; output graph, in RDFa spec. parlance @type graph: RDFLib Graph - @keyword vocab_expansion: whether the RDFa @vocab attribute should - also mean vocabulary expansion (see the RDFa 1.1 spec for further - details) + @keyword vocab_expansion: this argument is not used any more, maintained for backward compatibility reasons only @type vocab_expansion: Boolean - @keyword vocab_cache: in case vocab expansion is used, whether the - expansion data (i.e., vocabulary) should be cached locally. This - requires the ability for the local application to write on the - local file system + @keyword vocab_cache: this argument is not used any more, maintained for backward compatibility reasons only @type vocab_chache: Boolean - @keyword rdfOutput: whether Exceptions should be catched and added, - as triples, to the processor graph, or whether they should be raised. - @type rdfOutput: Boolean """ if html5lib is False: raise ImportError( @@ -239,17 +231,12 @@ class MicrodataParser(Parser): 'and Microdata parsers.') (baseURI, orig_source) = _get_orig_source(source) - self._process(graph, baseURI, orig_source, - vocab_expansion=vocab_expansion, - vocab_cache=vocab_cache) + self._process(graph, baseURI, orig_source) - def _process(self, graph, baseURI, orig_source, - vocab_expansion=False, vocab_cache=False): + def _process(self, graph, baseURI, orig_source): from .pyMicrodata import pyMicrodata - processor = pyMicrodata(base=baseURI, vocab_expansion=vocab_expansion, - vocab_cache=vocab_cache) - processor.graph_from_source( - orig_source, graph=graph, rdfOutput=False) + processor = pyMicrodata(base=baseURI) + processor.graph_from_source(orig_source, graph=graph, rdfOutput=False) class StructuredDataParser(Parser): @@ -288,9 +275,6 @@ class StructuredDataParser(Parser): requires the ability for the local application to write on the local file system @type vocab_chache: Boolean - @keyword rdfOutput: whether Exceptions should be catched and added, - as triples, to the processor graph, or whether they should be raised. - @type rdfOutput: Boolean """ # Note that the media_type argument is ignored, and is here only to avoid an 'unexpected argument' error. # This parser works for text/html only anyway... @@ -301,8 +285,6 @@ class StructuredDataParser(Parser): rdfa_version=rdfa_version, vocab_expansion=vocab_expansion, vocab_cache=vocab_cache) - MicrodataParser()._process(graph, baseURI, orig_source, - vocab_expansion=vocab_expansion, - vocab_cache=vocab_cache) + MicrodataParser()._process(graph, baseURI, orig_source) from .hturtle import HTurtleParser HTurtleParser()._process(graph, baseURI, orig_source, media_type='text/html') |
