pyRdfa.property

Implementation of the C{@property} value handling.

RDFa 1.0 and RDFa 1.1 are fairly different. RDFa 1.0 generates only literals, see U{RDFa Task Force's wiki pagehttp://www.w3.org/2006/07/SWD/wiki/RDFa/LiteralObject} for the details. On the other hand, RDFa 1.1, beyond literals, can also generate URI references. Hence the duplicate method in the L{ProcessProperty} class, one for RDFa 1.0 and the other for RDFa 1.1.

@summary: RDFa Literal generation @requires: U{RDFLib packagehttp://rdflib.net} @organization: U{World Wide Web Consortiumhttp://www.w3.org} @author: U{Ivan Herman} @license: This software is available for use under the U{W3C® SOFTWARE NOTICE AND LICENSE}

  1# -*- coding: utf-8 -*-
  2"""
  3Implementation of the C{@property} value handling.
  4
  5RDFa 1.0 and RDFa 1.1 are fairly different. RDFa 1.0 generates only literals, see
  6U{RDFa Task Force's wiki page<http://www.w3.org/2006/07/SWD/wiki/RDFa/LiteralObject>} for the details.
  7On the other hand, RDFa 1.1, beyond literals, can also generate URI references. Hence the duplicate method in the L{ProcessProperty} class, one for RDFa 1.0 and the other for RDFa 1.1.
  8
  9@summary: RDFa Literal generation
 10@requires: U{RDFLib package<http://rdflib.net>}
 11@organization: U{World Wide Web Consortium<http://www.w3.org>}
 12@author: U{Ivan Herman<a href="http://www.w3.org/People/Ivan/">}
 13@license: This software is available for use under the
 14U{W3C® SOFTWARE NOTICE AND LICENSE<href="http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231">}
 15"""
 16
 17"""
 18$Id: property.py,v 1.14 2013-07-26 16:10:16 ivan Exp $
 19$Date: 2013-07-26 16:10:16 $
 20"""
 21
 22from rdflib import BNode
 23from rdflib import Literal, URIRef
 24from rdflib import RDF as ns_rdf
 25from rdflib.term import XSDToPython
 26
 27from . import IncorrectBlankNodeUsage, IncorrectLiteral, err_no_blank_node
 28from .utils import has_one_of_attributes, return_XML
 29
 30import re
 31
 32XMLLiteral  = ns_rdf["XMLLiteral"]
 33HTMLLiteral = URIRef("http://www.w3.org/1999/02/22-rdf-syntax-ns#HTML")
 34
 35class ProcessProperty:
 36    """Generate the value for C{@property} taking into account datatype, etc.
 37    Note: this class is created only if the C{@property} is indeed present, no need to check.
 38    
 39    @ivar node: DOM element node
 40    @ivar graph: the (RDF) graph to add the properies to
 41    @ivar subject: the RDFLib URIRef serving as a subject for the generated triples
 42    @ivar state: the current state to be used for the CURIE-s
 43    @type state: L{state.ExecutionContext}
 44    @ivar typed_resource: Typically the bnode generated by a @typeof
 45    """
 46    def __init__(self, node, graph, subject, state, typed_resource=None):
 47        """
 48        @param node: DOM element node
 49        @param graph: the (RDF) graph to add the properies to
 50        @param subject: the RDFLib URIRef serving as a subject for the generated triples
 51        @param state: the current state to be used for the CURIE-s
 52        @param state: L{state.ExecutionContext}
 53        @param typed_resource: Typically the bnode generated by a @typeof; in RDFa 1.1, that becomes the object for C{@property}
 54        """
 55        self.node =           node
 56        self.graph =          graph
 57        self.subject =        subject
 58        self.state =          state
 59        self.typed_resource = typed_resource
 60        
 61    def generate(self):
 62        """
 63        Common entry point for the RDFa 1.0 and RDFa 1.1 versions; bifurcates based on the RDFa version, as retrieved from the state object.
 64        """
 65        if self.state.rdfa_version >= "1.1":
 66            self.generate_1_1()
 67        else:
 68            self.generate_1_0()
 69
 70    def generate_1_1(self):
 71        """Generate the property object, 1.1 version"""
 72
 73        #########################################################################        
 74        # See if the target is _not_ a literal
 75        irirefs =    ("resource", "href", "src")
 76        noiri =      ("content", "datatype", "rel", "rev")
 77        notypediri = ("content", "datatype", "rel", "rev", "about", "about_pruned")
 78        if has_one_of_attributes(self.node, irirefs) and not has_one_of_attributes(self.node, noiri):
 79            # @href/@resource/@src takes the lead here...
 80            obj = self.state.getResource(irirefs)
 81        elif self.node.hasAttribute("typeof") and not has_one_of_attributes(self.node, notypediri) and self.typed_resource != None:
 82                # a @typeof creates a special branch in case the typed resource was set during parsing
 83                obj = self.typed_resource
 84        else:
 85            # We have to generate a literal
 86            
 87            # Get, if exists, the value of @datatype
 88            datatype = ''
 89            dtset = False
 90            if self.node.hasAttribute("datatype"):
 91                dtset = True
 92                dt = self.node.getAttribute("datatype")
 93                if dt != "":
 94                    datatype = self.state.getURI("datatype")
 95
 96            # Supress lange is set in case some elements explicitly want to supress the effect of language
 97            # There were discussions, for example, that the <time> element should do so. Although,
 98            # after all, this was reversed, the functionality is kept in the code in case another
 99            # element might need it...
100            if self.state.lang != None and self.state.supress_lang == False:
101                lang = self.state.lang
102            else:
103                lang = ''
104
105            # The simple case: separate @content attribute
106            if self.node.hasAttribute("content"):
107                val = self.node.getAttribute("content")
108                # Handling the automatic uri conversion case
109                if dtset == False:
110                    obj = Literal(val, lang=lang)
111                else:
112                    obj = self._create_Literal(val, datatype=datatype, lang=lang)
113                # The value of datatype has been set, and the keyword paramaters take care of the rest
114            else:
115                # see if there *is* a datatype (even if it is empty!)
116                if dtset:
117                    if datatype == XMLLiteral:
118                        litval = self._get_XML_literal(self.node)
119                        obj = Literal(litval,datatype=XMLLiteral)
120                    elif datatype == HTMLLiteral:
121                        # I am not sure why this hack is necessary, but otherwise an encoding error occurs
122                        # In Python3 all this should become moot, due to the unicode everywhere approach...
123                        obj = Literal(self._get_HTML_literal(self.node), datatype=HTMLLiteral)
124                    else:
125                        obj = self._create_Literal(self._get_literal(self.node), datatype=datatype, lang=lang)
126                else:
127                    obj = self._create_Literal(self._get_literal(self.node), lang=lang)
128
129        if obj != None:
130            for prop in self.state.getURI("property"):
131                if not isinstance(prop, BNode):
132                    if self.node.hasAttribute("inlist"):
133                        self.state.add_to_list_mapping(prop, obj)
134                    else :            
135                        self.graph.add( (self.subject, prop, obj) )
136                else:
137                    self.state.options.add_warning(err_no_blank_node % "property", warning_type=IncorrectBlankNodeUsage, node=self.node.nodeName)
138    
139        # return
140
141    def generate_1_0(self):
142        """Generate the property object, 1.0 version"""
143                
144        #########################################################################        
145        # We have to generate a literal indeed.
146        # Get, if exists, the value of @datatype
147        datatype = ''
148        dtset = False
149        if self.node.hasAttribute("datatype"):
150            dtset = True
151            dt = self.node.getAttribute("datatype")
152            if dt != "":
153                datatype = self.state.getURI("datatype")
154    
155        if self.state.lang != None:
156            lang = self.state.lang
157        else:
158            lang = ''
159
160        # The simple case: separate @content attribute
161        if self.node.hasAttribute("content"):
162            val = self.node.getAttribute("content")
163            # Handling the automatic uri conversion case
164            if dtset == False:
165                obj = Literal(val, lang=lang)
166            else:
167                obj = self._create_Literal(val, datatype=datatype, lang=lang)
168            # The value of datatype has been set, and the keyword paramaters take care of the rest
169        else:
170            # see if there *is* a datatype (even if it is empty!)
171            if dtset:
172                # yep. The Literal content is the pure text part of the current element:
173                # We have to check whether the specified datatype is, in fact, an
174                # explicit XML Literal
175                if datatype == XMLLiteral:
176                    litval = self._get_XML_literal(self.node)
177                    obj = Literal(litval,datatype=XMLLiteral)
178                elif datatype == HTMLLiteral:
179                    # I am not sure why this hack is necessary, but otherwise an encoding error occurs
180                    # In Python3 all this should become moot, due to the unicode everywhere approach...
181                    obj = Literal(self._get_HTML_literal(self.node), datatype=HTMLLiteral)
182                else:
183                    obj = self._create_Literal(self._get_literal(self.node), datatype=datatype, lang=lang)
184            else:
185                # no controlling @datatype. We have to see if there is markup in the contained
186                # element
187                if True in [ n.nodeType == self.node.ELEMENT_NODE for n in self.node.childNodes ]:
188                    # yep, and XML Literal should be generated
189                    obj = self._create_Literal(self._get_XML_literal(self.node), datatype=XMLLiteral)
190                else:
191                    # At this point, there might be entities in the string that are returned as real characters by the dom
192                    # implementation. That should be turned back
193                    obj = self._create_Literal(self._get_literal(self.node), lang=lang)
194    
195        for prop in self.state.getURI("property"):
196            if not isinstance(prop,BNode):
197                self.graph.add( (self.subject,prop,obj) )
198            else:
199                self.state.options.add_warning(err_no_blank_node % "property", warning_type=IncorrectBlankNodeUsage, node=self.node.nodeName)
200    
201        # return
202    
203    ######################################################################################################################################
204    
205    
206    def _putBackEntities(self, data):
207        """Put 'back' entities for the '&','<', and '>' characters, to produce a proper XML string.
208        Used by the XML Literal extraction.
209        @param data: string to be converted
210        @return: string with entities
211        @rtype: string
212        """
213        return data.replace('&','&amp;').replace('<','&lt;').replace('>','&gt;')
214        
215    def _get_literal(self, Pnode):
216        """
217        Get (recursively) the full text from a DOM Node.
218    
219        @param Pnode: DOM Node
220        @return: string
221        """
222        rc = ""
223        for node in Pnode.childNodes:
224            if node.nodeType == node.TEXT_NODE:
225                rc = rc + node.data
226            elif node.nodeType == node.ELEMENT_NODE:
227                rc = rc + self._get_literal(node)
228    
229        # The decision of the group in February 2008 is not to normalize the result by default.
230        # This is reflected in the default value of the option        
231        
232        if self.state.options.space_preserve:
233            return rc
234        else:
235            return re.sub(r'(\r| |\n|\t)+'," ",rc).strip()
236    # end getLiteral
237    
238    def _get_XML_literal(self, Pnode):
239        """
240        Get (recursively) the XML Literal content of a DOM Node. 
241    
242        @param Pnode: DOM Node
243        @return: string
244        """    
245        rc = ""        
246        for node in Pnode.childNodes:
247            if node.nodeType == node.TEXT_NODE:
248                rc = rc + self._putBackEntities(node.data)
249            elif node.nodeType == node.ELEMENT_NODE:
250                rc = rc + return_XML(self.state, node, base = False)
251        return rc
252    # end getXMLLiteral
253
254    def _get_HTML_literal(self, Pnode):
255        """
256        Get (recursively) the XML Literal content of a DOM Node. 
257    
258        @param Pnode: DOM Node
259        @return: string
260        """    
261        rc = ""        
262        for node in Pnode.childNodes:
263            if node.nodeType == node.TEXT_NODE:
264                rc = rc + self._putBackEntities(node.data)
265            elif node.nodeType == node.ELEMENT_NODE:
266                rc = rc + return_XML(self.state, node, base = False, xmlns = False )
267        return rc
268    # end getHTMLLLiteral
269    
270    def _create_Literal(self, val, datatype = '', lang = ''):
271        """
272        Create a literal, taking into account the datatype and language.
273        @return: Literal
274        """
275        if datatype == None or datatype == '':
276            return Literal(val, lang=lang)
277        #elif datatype == ns_xsd["string"]:
278        #    return Literal(val)
279        else:
280            # This is a bit convoluted... the default setup of rdflib does not gracefully react if the
281            # datatype cannot properly be converted to Python. I have to copy and reuse some of the
282            # rdflib code to get this working...
283            # To make things worse: rdlib 3.1.0 does not handle the various xsd date types properly, ie,
284            # the conversion function below will generate errors. Ie, the check should be skipped for those
285            convFunc = XSDToPython.get(datatype, None)
286            if convFunc:
287                try:
288                    _pv = convFunc(val)
289                    # If we got there the literal value and its datatype match
290                except:
291                    self.state.options.add_warning("Incompatible value (%s) and datatype (%s) in Literal definition." % (val, datatype), warning_type=IncorrectLiteral, node=self.node.nodeName)
292            return Literal(val, datatype=datatype)
XMLLiteral = rdflib.term.URIRef('http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral')
HTMLLiteral = rdflib.term.URIRef('http://www.w3.org/1999/02/22-rdf-syntax-ns#HTML')
class ProcessProperty:
 36class ProcessProperty:
 37    """Generate the value for C{@property} taking into account datatype, etc.
 38    Note: this class is created only if the C{@property} is indeed present, no need to check.
 39    
 40    @ivar node: DOM element node
 41    @ivar graph: the (RDF) graph to add the properies to
 42    @ivar subject: the RDFLib URIRef serving as a subject for the generated triples
 43    @ivar state: the current state to be used for the CURIE-s
 44    @type state: L{state.ExecutionContext}
 45    @ivar typed_resource: Typically the bnode generated by a @typeof
 46    """
 47    def __init__(self, node, graph, subject, state, typed_resource=None):
 48        """
 49        @param node: DOM element node
 50        @param graph: the (RDF) graph to add the properies to
 51        @param subject: the RDFLib URIRef serving as a subject for the generated triples
 52        @param state: the current state to be used for the CURIE-s
 53        @param state: L{state.ExecutionContext}
 54        @param typed_resource: Typically the bnode generated by a @typeof; in RDFa 1.1, that becomes the object for C{@property}
 55        """
 56        self.node =           node
 57        self.graph =          graph
 58        self.subject =        subject
 59        self.state =          state
 60        self.typed_resource = typed_resource
 61        
 62    def generate(self):
 63        """
 64        Common entry point for the RDFa 1.0 and RDFa 1.1 versions; bifurcates based on the RDFa version, as retrieved from the state object.
 65        """
 66        if self.state.rdfa_version >= "1.1":
 67            self.generate_1_1()
 68        else:
 69            self.generate_1_0()
 70
 71    def generate_1_1(self):
 72        """Generate the property object, 1.1 version"""
 73
 74        #########################################################################        
 75        # See if the target is _not_ a literal
 76        irirefs =    ("resource", "href", "src")
 77        noiri =      ("content", "datatype", "rel", "rev")
 78        notypediri = ("content", "datatype", "rel", "rev", "about", "about_pruned")
 79        if has_one_of_attributes(self.node, irirefs) and not has_one_of_attributes(self.node, noiri):
 80            # @href/@resource/@src takes the lead here...
 81            obj = self.state.getResource(irirefs)
 82        elif self.node.hasAttribute("typeof") and not has_one_of_attributes(self.node, notypediri) and self.typed_resource != None:
 83                # a @typeof creates a special branch in case the typed resource was set during parsing
 84                obj = self.typed_resource
 85        else:
 86            # We have to generate a literal
 87            
 88            # Get, if exists, the value of @datatype
 89            datatype = ''
 90            dtset = False
 91            if self.node.hasAttribute("datatype"):
 92                dtset = True
 93                dt = self.node.getAttribute("datatype")
 94                if dt != "":
 95                    datatype = self.state.getURI("datatype")
 96
 97            # Supress lange is set in case some elements explicitly want to supress the effect of language
 98            # There were discussions, for example, that the <time> element should do so. Although,
 99            # after all, this was reversed, the functionality is kept in the code in case another
100            # element might need it...
101            if self.state.lang != None and self.state.supress_lang == False:
102                lang = self.state.lang
103            else:
104                lang = ''
105
106            # The simple case: separate @content attribute
107            if self.node.hasAttribute("content"):
108                val = self.node.getAttribute("content")
109                # Handling the automatic uri conversion case
110                if dtset == False:
111                    obj = Literal(val, lang=lang)
112                else:
113                    obj = self._create_Literal(val, datatype=datatype, lang=lang)
114                # The value of datatype has been set, and the keyword paramaters take care of the rest
115            else:
116                # see if there *is* a datatype (even if it is empty!)
117                if dtset:
118                    if datatype == XMLLiteral:
119                        litval = self._get_XML_literal(self.node)
120                        obj = Literal(litval,datatype=XMLLiteral)
121                    elif datatype == HTMLLiteral:
122                        # I am not sure why this hack is necessary, but otherwise an encoding error occurs
123                        # In Python3 all this should become moot, due to the unicode everywhere approach...
124                        obj = Literal(self._get_HTML_literal(self.node), datatype=HTMLLiteral)
125                    else:
126                        obj = self._create_Literal(self._get_literal(self.node), datatype=datatype, lang=lang)
127                else:
128                    obj = self._create_Literal(self._get_literal(self.node), lang=lang)
129
130        if obj != None:
131            for prop in self.state.getURI("property"):
132                if not isinstance(prop, BNode):
133                    if self.node.hasAttribute("inlist"):
134                        self.state.add_to_list_mapping(prop, obj)
135                    else :            
136                        self.graph.add( (self.subject, prop, obj) )
137                else:
138                    self.state.options.add_warning(err_no_blank_node % "property", warning_type=IncorrectBlankNodeUsage, node=self.node.nodeName)
139    
140        # return
141
142    def generate_1_0(self):
143        """Generate the property object, 1.0 version"""
144                
145        #########################################################################        
146        # We have to generate a literal indeed.
147        # Get, if exists, the value of @datatype
148        datatype = ''
149        dtset = False
150        if self.node.hasAttribute("datatype"):
151            dtset = True
152            dt = self.node.getAttribute("datatype")
153            if dt != "":
154                datatype = self.state.getURI("datatype")
155    
156        if self.state.lang != None:
157            lang = self.state.lang
158        else:
159            lang = ''
160
161        # The simple case: separate @content attribute
162        if self.node.hasAttribute("content"):
163            val = self.node.getAttribute("content")
164            # Handling the automatic uri conversion case
165            if dtset == False:
166                obj = Literal(val, lang=lang)
167            else:
168                obj = self._create_Literal(val, datatype=datatype, lang=lang)
169            # The value of datatype has been set, and the keyword paramaters take care of the rest
170        else:
171            # see if there *is* a datatype (even if it is empty!)
172            if dtset:
173                # yep. The Literal content is the pure text part of the current element:
174                # We have to check whether the specified datatype is, in fact, an
175                # explicit XML Literal
176                if datatype == XMLLiteral:
177                    litval = self._get_XML_literal(self.node)
178                    obj = Literal(litval,datatype=XMLLiteral)
179                elif datatype == HTMLLiteral:
180                    # I am not sure why this hack is necessary, but otherwise an encoding error occurs
181                    # In Python3 all this should become moot, due to the unicode everywhere approach...
182                    obj = Literal(self._get_HTML_literal(self.node), datatype=HTMLLiteral)
183                else:
184                    obj = self._create_Literal(self._get_literal(self.node), datatype=datatype, lang=lang)
185            else:
186                # no controlling @datatype. We have to see if there is markup in the contained
187                # element
188                if True in [ n.nodeType == self.node.ELEMENT_NODE for n in self.node.childNodes ]:
189                    # yep, and XML Literal should be generated
190                    obj = self._create_Literal(self._get_XML_literal(self.node), datatype=XMLLiteral)
191                else:
192                    # At this point, there might be entities in the string that are returned as real characters by the dom
193                    # implementation. That should be turned back
194                    obj = self._create_Literal(self._get_literal(self.node), lang=lang)
195    
196        for prop in self.state.getURI("property"):
197            if not isinstance(prop,BNode):
198                self.graph.add( (self.subject,prop,obj) )
199            else:
200                self.state.options.add_warning(err_no_blank_node % "property", warning_type=IncorrectBlankNodeUsage, node=self.node.nodeName)
201    
202        # return
203    
204    ######################################################################################################################################
205    
206    
207    def _putBackEntities(self, data):
208        """Put 'back' entities for the '&','<', and '>' characters, to produce a proper XML string.
209        Used by the XML Literal extraction.
210        @param data: string to be converted
211        @return: string with entities
212        @rtype: string
213        """
214        return data.replace('&','&amp;').replace('<','&lt;').replace('>','&gt;')
215        
216    def _get_literal(self, Pnode):
217        """
218        Get (recursively) the full text from a DOM Node.
219    
220        @param Pnode: DOM Node
221        @return: string
222        """
223        rc = ""
224        for node in Pnode.childNodes:
225            if node.nodeType == node.TEXT_NODE:
226                rc = rc + node.data
227            elif node.nodeType == node.ELEMENT_NODE:
228                rc = rc + self._get_literal(node)
229    
230        # The decision of the group in February 2008 is not to normalize the result by default.
231        # This is reflected in the default value of the option        
232        
233        if self.state.options.space_preserve:
234            return rc
235        else:
236            return re.sub(r'(\r| |\n|\t)+'," ",rc).strip()
237    # end getLiteral
238    
239    def _get_XML_literal(self, Pnode):
240        """
241        Get (recursively) the XML Literal content of a DOM Node. 
242    
243        @param Pnode: DOM Node
244        @return: string
245        """    
246        rc = ""        
247        for node in Pnode.childNodes:
248            if node.nodeType == node.TEXT_NODE:
249                rc = rc + self._putBackEntities(node.data)
250            elif node.nodeType == node.ELEMENT_NODE:
251                rc = rc + return_XML(self.state, node, base = False)
252        return rc
253    # end getXMLLiteral
254
255    def _get_HTML_literal(self, Pnode):
256        """
257        Get (recursively) the XML Literal content of a DOM Node. 
258    
259        @param Pnode: DOM Node
260        @return: string
261        """    
262        rc = ""        
263        for node in Pnode.childNodes:
264            if node.nodeType == node.TEXT_NODE:
265                rc = rc + self._putBackEntities(node.data)
266            elif node.nodeType == node.ELEMENT_NODE:
267                rc = rc + return_XML(self.state, node, base = False, xmlns = False )
268        return rc
269    # end getHTMLLLiteral
270    
271    def _create_Literal(self, val, datatype = '', lang = ''):
272        """
273        Create a literal, taking into account the datatype and language.
274        @return: Literal
275        """
276        if datatype == None or datatype == '':
277            return Literal(val, lang=lang)
278        #elif datatype == ns_xsd["string"]:
279        #    return Literal(val)
280        else:
281            # This is a bit convoluted... the default setup of rdflib does not gracefully react if the
282            # datatype cannot properly be converted to Python. I have to copy and reuse some of the
283            # rdflib code to get this working...
284            # To make things worse: rdlib 3.1.0 does not handle the various xsd date types properly, ie,
285            # the conversion function below will generate errors. Ie, the check should be skipped for those
286            convFunc = XSDToPython.get(datatype, None)
287            if convFunc:
288                try:
289                    _pv = convFunc(val)
290                    # If we got there the literal value and its datatype match
291                except:
292                    self.state.options.add_warning("Incompatible value (%s) and datatype (%s) in Literal definition." % (val, datatype), warning_type=IncorrectLiteral, node=self.node.nodeName)
293            return Literal(val, datatype=datatype)

Generate the value for C{@property} taking into account datatype, etc. Note: this class is created only if the C{@property} is indeed present, no need to check.

@ivar node: DOM element node @ivar graph: the (RDF) graph to add the properies to @ivar subject: the RDFLib URIRef serving as a subject for the generated triples @ivar state: the current state to be used for the CURIE-s @type state: L{state.ExecutionContext} @ivar typed_resource: Typically the bnode generated by a @typeof

ProcessProperty(node, graph, subject, state, typed_resource=None)
47    def __init__(self, node, graph, subject, state, typed_resource=None):
48        """
49        @param node: DOM element node
50        @param graph: the (RDF) graph to add the properies to
51        @param subject: the RDFLib URIRef serving as a subject for the generated triples
52        @param state: the current state to be used for the CURIE-s
53        @param state: L{state.ExecutionContext}
54        @param typed_resource: Typically the bnode generated by a @typeof; in RDFa 1.1, that becomes the object for C{@property}
55        """
56        self.node =           node
57        self.graph =          graph
58        self.subject =        subject
59        self.state =          state
60        self.typed_resource = typed_resource

@param node: DOM element node @param graph: the (RDF) graph to add the properies to @param subject: the RDFLib URIRef serving as a subject for the generated triples @param state: the current state to be used for the CURIE-s @param state: L{state.ExecutionContext} @param typed_resource: Typically the bnode generated by a @typeof; in RDFa 1.1, that becomes the object for C{@property}

node
graph
subject
state
typed_resource
def generate(self):
62    def generate(self):
63        """
64        Common entry point for the RDFa 1.0 and RDFa 1.1 versions; bifurcates based on the RDFa version, as retrieved from the state object.
65        """
66        if self.state.rdfa_version >= "1.1":
67            self.generate_1_1()
68        else:
69            self.generate_1_0()

Common entry point for the RDFa 1.0 and RDFa 1.1 versions; bifurcates based on the RDFa version, as retrieved from the state object.

def generate_1_1(self):
 71    def generate_1_1(self):
 72        """Generate the property object, 1.1 version"""
 73
 74        #########################################################################        
 75        # See if the target is _not_ a literal
 76        irirefs =    ("resource", "href", "src")
 77        noiri =      ("content", "datatype", "rel", "rev")
 78        notypediri = ("content", "datatype", "rel", "rev", "about", "about_pruned")
 79        if has_one_of_attributes(self.node, irirefs) and not has_one_of_attributes(self.node, noiri):
 80            # @href/@resource/@src takes the lead here...
 81            obj = self.state.getResource(irirefs)
 82        elif self.node.hasAttribute("typeof") and not has_one_of_attributes(self.node, notypediri) and self.typed_resource != None:
 83                # a @typeof creates a special branch in case the typed resource was set during parsing
 84                obj = self.typed_resource
 85        else:
 86            # We have to generate a literal
 87            
 88            # Get, if exists, the value of @datatype
 89            datatype = ''
 90            dtset = False
 91            if self.node.hasAttribute("datatype"):
 92                dtset = True
 93                dt = self.node.getAttribute("datatype")
 94                if dt != "":
 95                    datatype = self.state.getURI("datatype")
 96
 97            # Supress lange is set in case some elements explicitly want to supress the effect of language
 98            # There were discussions, for example, that the <time> element should do so. Although,
 99            # after all, this was reversed, the functionality is kept in the code in case another
100            # element might need it...
101            if self.state.lang != None and self.state.supress_lang == False:
102                lang = self.state.lang
103            else:
104                lang = ''
105
106            # The simple case: separate @content attribute
107            if self.node.hasAttribute("content"):
108                val = self.node.getAttribute("content")
109                # Handling the automatic uri conversion case
110                if dtset == False:
111                    obj = Literal(val, lang=lang)
112                else:
113                    obj = self._create_Literal(val, datatype=datatype, lang=lang)
114                # The value of datatype has been set, and the keyword paramaters take care of the rest
115            else:
116                # see if there *is* a datatype (even if it is empty!)
117                if dtset:
118                    if datatype == XMLLiteral:
119                        litval = self._get_XML_literal(self.node)
120                        obj = Literal(litval,datatype=XMLLiteral)
121                    elif datatype == HTMLLiteral:
122                        # I am not sure why this hack is necessary, but otherwise an encoding error occurs
123                        # In Python3 all this should become moot, due to the unicode everywhere approach...
124                        obj = Literal(self._get_HTML_literal(self.node), datatype=HTMLLiteral)
125                    else:
126                        obj = self._create_Literal(self._get_literal(self.node), datatype=datatype, lang=lang)
127                else:
128                    obj = self._create_Literal(self._get_literal(self.node), lang=lang)
129
130        if obj != None:
131            for prop in self.state.getURI("property"):
132                if not isinstance(prop, BNode):
133                    if self.node.hasAttribute("inlist"):
134                        self.state.add_to_list_mapping(prop, obj)
135                    else :            
136                        self.graph.add( (self.subject, prop, obj) )
137                else:
138                    self.state.options.add_warning(err_no_blank_node % "property", warning_type=IncorrectBlankNodeUsage, node=self.node.nodeName)
139    
140        # return

Generate the property object, 1.1 version

def generate_1_0(self):
142    def generate_1_0(self):
143        """Generate the property object, 1.0 version"""
144                
145        #########################################################################        
146        # We have to generate a literal indeed.
147        # Get, if exists, the value of @datatype
148        datatype = ''
149        dtset = False
150        if self.node.hasAttribute("datatype"):
151            dtset = True
152            dt = self.node.getAttribute("datatype")
153            if dt != "":
154                datatype = self.state.getURI("datatype")
155    
156        if self.state.lang != None:
157            lang = self.state.lang
158        else:
159            lang = ''
160
161        # The simple case: separate @content attribute
162        if self.node.hasAttribute("content"):
163            val = self.node.getAttribute("content")
164            # Handling the automatic uri conversion case
165            if dtset == False:
166                obj = Literal(val, lang=lang)
167            else:
168                obj = self._create_Literal(val, datatype=datatype, lang=lang)
169            # The value of datatype has been set, and the keyword paramaters take care of the rest
170        else:
171            # see if there *is* a datatype (even if it is empty!)
172            if dtset:
173                # yep. The Literal content is the pure text part of the current element:
174                # We have to check whether the specified datatype is, in fact, an
175                # explicit XML Literal
176                if datatype == XMLLiteral:
177                    litval = self._get_XML_literal(self.node)
178                    obj = Literal(litval,datatype=XMLLiteral)
179                elif datatype == HTMLLiteral:
180                    # I am not sure why this hack is necessary, but otherwise an encoding error occurs
181                    # In Python3 all this should become moot, due to the unicode everywhere approach...
182                    obj = Literal(self._get_HTML_literal(self.node), datatype=HTMLLiteral)
183                else:
184                    obj = self._create_Literal(self._get_literal(self.node), datatype=datatype, lang=lang)
185            else:
186                # no controlling @datatype. We have to see if there is markup in the contained
187                # element
188                if True in [ n.nodeType == self.node.ELEMENT_NODE for n in self.node.childNodes ]:
189                    # yep, and XML Literal should be generated
190                    obj = self._create_Literal(self._get_XML_literal(self.node), datatype=XMLLiteral)
191                else:
192                    # At this point, there might be entities in the string that are returned as real characters by the dom
193                    # implementation. That should be turned back
194                    obj = self._create_Literal(self._get_literal(self.node), lang=lang)
195    
196        for prop in self.state.getURI("property"):
197            if not isinstance(prop,BNode):
198                self.graph.add( (self.subject,prop,obj) )
199            else:
200                self.state.options.add_warning(err_no_blank_node % "property", warning_type=IncorrectBlankNodeUsage, node=self.node.nodeName)
201    
202        # return

Generate the property object, 1.0 version