1 """CSSNamespaceRule currently implements
2 http://www.w3.org/TR/2006/WD-css3-namespace-20060828/
3
4 The following changes have been done:
5 1. the url() syntax is not implemented as it may (?) be deprecated
6 anyway
7 """
8 __all__ = ['CSSNamespaceRule']
9 __docformat__ = 'restructuredtext'
10 __author__ = '$LastChangedBy: cthedot $'
11 __date__ = '$LastChangedDate: 2008-02-02 21:24:21 +0100 (Sa, 02 Feb 2008) $'
12 __version__ = '$LastChangedRevision: 963 $'
13
14 import xml.dom
15 import cssrule
16 import cssutils
17 from cssutils.util import Deprecated
18
20 """
21 Represents an @namespace rule within a CSS style sheet.
22
23 The @namespace at-rule declares a namespace prefix and associates
24 it with a given namespace (a string). This namespace prefix can then be
25 used in namespace-qualified names such as those described in the
26 Selectors Module [SELECT] or the Values and Units module [CSS3VAL].
27
28 Properties
29 ==========
30 cssText: of type DOMString
31 The parsable textual representation of this rule
32 namespaceURI: of type DOMString
33 The namespace URI (a simple string!) which is bound to the given
34 prefix. If no prefix is set (``CSSNamespaceRule.prefix==''``)
35 the namespace defined by ``namespaceURI`` is set as the default
36 namespace.
37 prefix: of type DOMString
38 The prefix used in the stylesheet for the given
39 ``CSSNamespaceRule.nsuri``. If prefix is empty namespaceURI sets a
40 default namespace for the stylesheet.
41
42 cssutils only
43 -------------
44 atkeyword:
45 the literal keyword used
46
47 Inherits properties from CSSRule
48
49 Format
50 ======
51 namespace
52 : NAMESPACE_SYM S* [namespace_prefix S*]? [STRING|URI] S* ';' S*
53 ;
54 namespace_prefix
55 : IDENT
56 ;
57 """
58 type = cssrule.CSSRule.NAMESPACE_RULE
59
60 - def __init__(self, namespaceURI=None, prefix=None, cssText=None,
61 parentRule=None, parentStyleSheet=None, readonly=False):
62 """
63 :Parameters:
64 namespaceURI
65 The namespace URI (a simple string!) which is bound to the
66 given prefix. If no prefix is set
67 (``CSSNamespaceRule.prefix==''``) the namespace defined by
68 namespaceURI is set as the default namespace
69 prefix
70 The prefix used in the stylesheet for the given
71 ``CSSNamespaceRule.uri``.
72 cssText
73 if no namespaceURI is given cssText must be given to set
74 a namespaceURI as this is readonly later on
75 parentStyleSheet
76 sheet where this rule belongs to
77
78 Do not use as positional but as keyword parameters only!
79
80 If readonly allows setting of properties in constructor only
81
82 format namespace::
83
84 : NAMESPACE_SYM S* [namespace_prefix S*]? [STRING|URI] S* ';' S*
85 ;
86 """
87 super(CSSNamespaceRule, self).__init__(parentRule=parentRule,
88 parentStyleSheet=parentStyleSheet)
89 self.atkeyword = u'@namespace'
90 self._prefix = u''
91 self._namespaceURI = None
92
93 if namespaceURI:
94 self.namespaceURI = namespaceURI
95 self.prefix = prefix
96 self.seq = [self.prefix, self.namespaceURI]
97 elif cssText:
98 self.cssText = cssText
99
100 if parentStyleSheet:
101 self._parentStyleSheet = parentStyleSheet
102
103 self._readonly = readonly
104
106 """
107 DOMException on setting
108
109 :param namespaceURI: the initial value for this rules namespaceURI
110 :Exceptions:
111 - `NO_MODIFICATION_ALLOWED_ERR`:
112 (CSSRule) Raised if this rule is readonly or a namespaceURI is
113 already set in this rule.
114 """
115 self._checkReadonly()
116 if not self._namespaceURI:
117
118 self._namespaceURI = namespaceURI
119 self.seq = [namespaceURI]
120 elif self._namespaceURI != namespaceURI:
121 self._log.error(u'CSSNamespaceRule: namespaceURI is readonly.',
122 error=xml.dom.NoModificationAllowedErr)
123
124 namespaceURI = property(lambda self: self._namespaceURI, _setNamespaceURI,
125 doc="URI (string!) of the defined namespace.")
126
128 """
129 DOMException on setting
130
131 :param prefix: the new prefix
132 :Exceptions:
133 - `SYNTAX_ERR`: (TODO)
134 Raised if the specified CSS string value has a syntax error and
135 is unparsable.
136 - `NO_MODIFICATION_ALLOWED_ERR`: CSSRule)
137 Raised if this rule is readonly.
138 """
139 self._checkReadonly()
140 if not prefix:
141 prefix = u''
142 else:
143 tokenizer = self._tokenize2(prefix)
144 prefixtoken = self._nexttoken(tokenizer, None)
145 if not prefixtoken or self._type(prefixtoken) != self._prods.IDENT:
146 self._log.error(u'CSSNamespaceRule: No valid prefix "%s".' %
147 self._valuestr(prefix),
148 error=xml.dom.SyntaxErr)
149 return
150 else:
151 prefix = self._tokenvalue(prefixtoken)
152
153 for i, x in enumerate(self.seq):
154 if x == self._prefix:
155 self.seq[i] = prefix
156 break
157 else:
158 self.seq[0] = prefix
159
160
161 self._prefix = prefix
162
163 prefix = property(lambda self: self._prefix, _setPrefix,
164 doc="Prefix used for the defined namespace.")
165
168
169 parentStyleSheet = property(lambda self: self._parentStyleSheet,
170 _setParentStyleSheet,
171 doc=u"Containing CSSStyleSheet.")
172
173 - def _getCssText(self):
174 """
175 returns serialized property cssText
176 """
177 return cssutils.ser.do_CSSNamespaceRule(self)
178
179 - def _setCssText(self, cssText):
180 """
181 DOMException on setting
182
183 :param cssText: initial value for this rules cssText which is parsed
184 :Exceptions:
185 - `HIERARCHY_REQUEST_ERR`: (CSSStylesheet)
186 Raised if the rule cannot be inserted at this point in the
187 style sheet.
188 - `INVALID_MODIFICATION_ERR`: (self)
189 Raised if the specified CSS string value represents a different
190 type of rule than the current one.
191 - `NO_MODIFICATION_ALLOWED_ERR`: (CSSRule)
192 Raised if the rule is readonly.
193 - `SYNTAX_ERR`: (self)
194 Raised if the specified CSS string value has a syntax error and
195 is unparsable.
196 """
197 super(CSSNamespaceRule, self)._setCssText(cssText)
198 tokenizer = self._tokenize2(cssText)
199 attoken = self._nexttoken(tokenizer, None)
200 if not attoken or self._type(attoken) != self._prods.NAMESPACE_SYM:
201 self._log.error(u'CSSNamespaceRule: No CSSNamespaceRule found: %s' %
202 self._valuestr(cssText),
203 error=xml.dom.InvalidModificationErr)
204 else:
205
206 new = {
207 'keyword': self._tokenvalue(attoken),
208 'prefix': u'',
209 'uri': None,
210 'valid': True
211 }
212
213 def _ident(expected, seq, token, tokenizer=None):
214
215 if 'prefix or uri' == expected:
216 new['prefix'] = self._tokenvalue(token)
217 seq.append(new['prefix'])
218 return 'uri'
219 else:
220 new['valid'] = False
221 self._log.error(
222 u'CSSNamespaceRule: Unexpected ident.', token)
223 return expected
224
225 def _string(expected, seq, token, tokenizer=None):
226
227 if expected.endswith('uri'):
228 new['uri'] = self._tokenvalue(token)[1:-1]
229 seq.append(new['uri'])
230 return ';'
231
232 else:
233 new['valid'] = False
234 self._log.error(
235 u'CSSNamespaceRule: Unexpected string.', token)
236 return expected
237
238 def _uri(expected, seq, token, tokenizer=None):
239
240 if expected.endswith('uri'):
241 uri = self._tokenvalue(token)[4:-1].strip()
242 if uri[0] == uri[-1] == '"' or\
243 uri[0] == uri[-1] == "'":
244 uri = uri[1:-1]
245 self._log.warn(
246 u'CSSNamespaceRule: Found namespace definition with url(uri), this may be deprecated in the future, use string format "uri" instead.',
247 token, error = None, neverraise=True)
248 new['uri'] = uri
249 seq.append(new['uri'])
250 return ';'
251 else:
252 new['valid'] = False
253 self._log.error(
254 u'CSSNamespaceRule: Unexpected URI.', token)
255 return expected
256
257 def _char(expected, seq, token, tokenizer=None):
258
259 val = self._tokenvalue(token)
260 if ';' == expected and u';' == val:
261 return 'EOF'
262 else:
263 new['valid'] = False
264 self._log.error(
265 u'CSSNamespaceRule: Unexpected char.', token)
266 return expected
267
268
269 newseq = []
270 valid, expected = self._parse(expected='prefix or uri',
271 seq=newseq, tokenizer=tokenizer,
272 productions={'IDENT': _ident,
273 'STRING': _string,
274 'URI': _uri,
275 'CHAR': _char})
276
277
278 valid = valid and new['valid']
279
280
281 if not new['uri']:
282 valid = False
283 self._log.error(u'CSSNamespaceRule: No namespace URI found: %s' %
284 self._valuestr(cssText))
285
286 if expected != 'EOF':
287 valid = False
288 self._log.error(u'CSSNamespaceRule: No ";" found: %s' %
289 self._valuestr(cssText))
290
291
292 self.valid = valid
293 if valid:
294 self.atkeyword = new['keyword']
295 self._prefix = new['prefix']
296 self.namespaceURI = new['uri']
297 self.seq = newseq
298
299 cssText = property(fget=_getCssText, fset=_setCssText,
300 doc="(DOM attribute) The parsable textual representation.")
301
303 return "cssutils.css.%s(namespaceURI=%r, prefix=%r)" % (
304 self.__class__.__name__, self.namespaceURI, self.prefix)
305
307 return "<cssutils.css.%s object namespaceURI=%r prefix=%r at 0x%x>" % (
308 self.__class__.__name__, self.namespaceURI, self.prefix, id(self))
309