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: 2007-12-02 13:57:04 +0100 (So, 02 Dez 2007) $'
12 __version__ = '$LastChangedRevision: 708 $'
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 uri sets the default
40 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=u'', readonly=False):
61 """
62 if readonly allows setting of properties in constructor only
63
64 Do not use as positional but as keyword attributes only!
65
66 namespaceURI
67 The namespace URI (a simple string!) which is bound to the
68 given prefix. If no prefix is set
69 (``CSSNamespaceRule.prefix==''``) the namespace defined by
70 namespaceURI is set as the default namespace
71 prefix
72 The prefix used in the stylesheet for the given
73 ``CSSNamespaceRule.uri``.
74
75 format namespace::
76
77 : NAMESPACE_SYM S* [namespace_prefix S*]? [STRING|URI] S* ';' S*
78 ;
79 """
80 super(CSSNamespaceRule, self).__init__()
81
82 self.atkeyword = u'@namespace'
83 self.namespaceURI = namespaceURI
84 self.prefix = prefix
85 self.seq = [self.prefix, self.namespaceURI]
86
87 self._readonly = readonly
88
90 """ returns uri as a string """
91 return self._namespaceURI
92
94 """
95 DOMException on setting
96
97 - NO_MODIFICATION_ALLOWED_ERR: (CSSRule)
98 Raised if this rule is readonly.
99 """
100 self._checkReadonly()
101
102
103 for i, x in enumerate(self.seq):
104 if x == self._namespaceURI:
105 self.seq[i] = namespaceURI
106 break
107 else:
108 self.seq = [namespaceURI]
109
110 self._namespaceURI = namespaceURI
111
112 namespaceURI = property(_getNamespaceURI, _setNamespaceURI,
113 doc="URI (string!) of the defined namespace.")
114
115 @Deprecated(u'Use property namespaceURI instead.')
118
119 @Deprecated(u'Use property namespaceURI instead.')
122
123 uri = property(_getURI, _setURI,
124 doc="DEPRECATED: Use property namespaceURI instead.")
125
126
128 """ returns prefix """
129 return self._prefix
130
132 """
133 DOMException on setting
134
135 - SYNTAX_ERR: (not checked here)
136 Raised if the specified CSS string value has a syntax error and
137 is unparsable.
138 - NO_MODIFICATION_ALLOWED_ERR: (CSSRule)
139 Raised if this rule is readonly.
140 """
141 self._checkReadonly()
142
143
144 self._prefix = prefix
145
146 for i, x in enumerate(self.seq):
147 if x == self._prefix:
148 self.seq[i] = prefix
149 break
150 else:
151 self.seq[0] = prefix
152
153 prefix = property(_getPrefix, _setPrefix,
154 doc="Prefix used for the defined namespace.")
155
156
157 - def _getCssText(self):
158 """
159 returns serialized property cssText
160 """
161 return cssutils.ser.do_CSSNamespaceRule(self)
162
163 - def _setCssText(self, cssText):
164 """
165 DOMException on setting
166
167 - HIERARCHY_REQUEST_ERR: (CSSStylesheet)
168 Raised if the rule cannot be inserted at this point in the
169 style sheet.
170 - INVALID_MODIFICATION_ERR: (self)
171 Raised if the specified CSS string value represents a different
172 type of rule than the current one.
173 - NO_MODIFICATION_ALLOWED_ERR: (CSSRule)
174 Raised if the rule is readonly.
175 - SYNTAX_ERR: (self)
176 Raised if the specified CSS string value has a syntax error and
177 is unparsable.
178 """
179 super(CSSNamespaceRule, self)._setCssText(cssText)
180 tokenizer = self._tokenize2(cssText)
181 attoken = self._nexttoken(tokenizer, None)
182 if not attoken or self._type(attoken) != self._prods.NAMESPACE_SYM:
183 self._log.error(u'CSSNamespaceRule: No CSSNamespaceRule found: %s' %
184 self._valuestr(cssText),
185 error=xml.dom.InvalidModificationErr)
186 else:
187
188 new = {
189 'keyword': self._tokenvalue(attoken),
190 'prefix': None,
191 'uri': None,
192 'valid': True
193 }
194
195 def _ident(expected, seq, token, tokenizer=None):
196
197 if 'prefix or uri' == expected:
198 new['prefix'] = self._tokenvalue(token)
199 seq.append(new['prefix'])
200 return 'uri'
201 else:
202 new['valid'] = False
203 self._log.error(
204 u'CSSNamespaceRule: Unexpected ident.', token)
205 return expected
206
207 def _string(expected, seq, token, tokenizer=None):
208
209 if expected.endswith('uri'):
210 new['uri'] = self._tokenvalue(token)[1:-1]
211 seq.append(new['uri'])
212 return ';'
213
214 else:
215 new['valid'] = False
216 self._log.error(
217 u'CSSNamespaceRule: Unexpected string.', token)
218 return expected
219
220 def _uri(expected, seq, token, tokenizer=None):
221
222 if expected.endswith('uri'):
223 uri = self._tokenvalue(token)[4:-1].strip()
224 if uri[0] == uri[-1] == '"' or\
225 uri[0] == uri[-1] == "'":
226 uri = uri[1:-1]
227 self._log.warn(
228 u'CSSNamespaceRule: Found namespace definition with url(uri), this may be deprecated in the future, use string format "uri" instead.',
229 token, error = None, neverraise=True)
230 new['uri'] = uri
231 seq.append(new['uri'])
232 return ';'
233 else:
234 new['valid'] = False
235 self._log.error(
236 u'CSSNamespaceRule: Unexpected URI.', token)
237 return expected
238
239 def _char(expected, seq, token, tokenizer=None):
240
241 val = self._tokenvalue(token)
242 if ';' == expected and u';' == val:
243 return 'EOF'
244 else:
245 new['valid'] = False
246 self._log.error(
247 u'CSSNamespaceRule: Unexpected char.', token)
248 return expected
249
250
251 newseq = []
252 valid, expected = self._parse(expected='prefix or uri',
253 seq=newseq, tokenizer=tokenizer,
254 productions={'IDENT': _ident,
255 'STRING': _string,
256 'URI': _uri,
257 'CHAR': _char})
258
259
260 valid = valid and new['valid']
261
262
263 if not new['uri']:
264 valid = False
265 self._log.error(u'CSSNamespaceRule: No namespace URI found: %s' %
266 self._valuestr(cssText))
267
268 if expected != 'EOF':
269 valid = False
270 self._log.error(u'CSSNamespaceRule: No ";" found: %s' %
271 self._valuestr(cssText))
272
273
274 self.valid = valid
275 if valid:
276 self.atkeyword = new['keyword']
277 self.prefix = new['prefix']
278 self.namespaceURI = new['uri']
279 self.seq = newseq
280
281 cssText = property(fget=_getCssText, fset=_setCssText,
282 doc="(DOM attribute) The parsable textual representation.")
283
285 return "cssutils.css.%s(namespaceURI=%r, prefix=%r)" % (
286 self.__class__.__name__, self.namespaceURI, self.prefix)
287
289 return "<cssutils.css.%s object namespaceURI=%r prefix=%r at 0x%x>" % (
290 self.__class__.__name__, self.namespaceURI, self.prefix, id(self))
291