def getURIFromElementName(elem, nsMap): if elem.prefix is None: prefix, localName = SplitQName(elem.nodeName) else: prefix, localName = elem.prefix, elem.localName if elem.namespaceURI: #namespace aware node u = elem.namespaceURI #comment out this assertion because ZML will add namespaces with the {URIRef} tokens #assert u == nsMap.get(prefix, u), ('namespace URI for ' + prefix + # ' mismatch xmlns declaration ' + u + ' with rx:prefix ' + nsMap[prefix]) else: if nsMap.has_key(prefix): u = nsMap[prefix] else: u = None for name, value in elem.attributes.items(): attrPrefix, attrLocal = SplitQName(name) if attrPrefix == 'xmlns' and attrLocal == prefix: u = value #this will never go out of scope but the zml auto-generated prefixes always increment nsMap[prefix] = u break if not u: raise RxMLError('prefix ' + repr(prefix) + ' not found') if not localName.lstrip('_'): #if empty, must be all '_'s localName = localName[:-1] #strip last '_' return u + localName
def __getitem__(self, key): if isinstance(key, int): result = list(self)[key] else: force_type = None if isinstance(key, tuple): if len(key) == 3: force_type, key = key[0], key[1:] elif isinstance(key, basestring): key = (None, key) else: raise TypeError('Inappropriate key (%s)' % (key)) for attr, obj in self.xml_properties.items(): if self.is_attribute(attr): qname, ns = self.xml_attributes.get(attr) if (force_type in (None, Node.ATTRIBUTE_NODE) and key == (ns, SplitQName(qname)[1])): #The key references an XML attribute #Bypass __setattr__ result = obj break elif is_element(obj): if (force_type in (None, Node.ELEMENT_NODE) and key == (obj.namespaceURI, obj.localName)): result = obj break else: raise KeyError( 'namespace/local name combination not found (%s)' % (str(key))) return result
def xml_create_element(self, qname, ns=None, content=None, attributes=None): "Create a new, empty element (no attrs)" instance = create_element(self.xml_naming_rule, qname, ns) if content: if not isinstance(content, list): content = [content] instance.xml_children = content if attributes: instance.xml_attributes = {} for aname in attributes: if isinstance(aname, tuple): aqname, ans = aname else: aqname, ans = aname, None avalue = attributes[aname] apyname = self.xml_naming_rule.xml_to_python( SplitQName(aqname)[1], ans, check_clashes=dir(instance)) #Bypass __setattr__ instance.__dict__[apyname] = avalue instance.xml_attributes[apyname] = (aqname, ans) return instance
def xml_set_attribute(self, aname, avalue): "Set (or create) an attribute on ana element" if isinstance(aname, tuple): aqname, ans = aname else: aqname, ans = aname, None prefix, local = SplitQName(aqname) if prefix == u'xml': ans = XML_NS elif ans and not prefix and ans in self.rootNode.xmlns_prefixes.values( ): #If the user specified a namespace URI and not a prefix, they would #Usually get an ugly generated prefix. Check the document for a nicer #Alternative #Note: this could cause spurious namespace declarations if the document is not sane prefix = [ p for p, u in self.rootNode.xmlns_prefixes.items() if u == ans ][0] aqname = prefix + u':' + local apyname = self.xml_naming_rule.xml_to_python(local, ans, check_clashes=dir(self)) #Bypass __setattr__ self.__dict__[apyname] = avalue if not hasattr(self, 'xml_attributes'): self.xml_attributes = {} self.xml_attributes[apyname] = (aqname, ans) return apyname
def getURIFromElement(context, nodeset=None): string = None if nodeset is None: node = context.node elif type(nodeset) == type([]): if nodeset: node = nodeset[0] if node.nodeType != Node.ELEMENT_NODE: string = node else: return u'' else: string = nodeset if string is not None: qname = StringValue(string) (prefix, local) = SplitQName(qname) if prefix: try: namespace = context.processorNss[prefix] except KeyError: raise XPath.RuntimeException( XPath.RuntimeException.UNDEFINED_PREFIX, prefix) return namespace + getURIFragmentFromLocal(local) else: return getURIFromElementName(node)
def _onMetaData(kw, context, name, func, opname, value=None, authorize=True): from rx import raccoon (prefix, local) = SplitQName(name) if prefix: try: namespace = context.processorNss[prefix] except KeyError: raise RuntimeException(RuntimeException.UNDEFINED_PREFIX, prefix) else: namespace = None local = str(local) #function argument keyword dict can't be unicode if authorize and not kw['__server__'].authorizeMetadata( opname, namespace, local, value, kw): if value is None: value = '' raise raccoon.NotAuthorized('%s-metadata with %s:%s %s' % (opname, namespace, name, value)) dict = None kwdicts = kw['__server__'].kw2varsMap if not namespace: dict = kw elif kwdicts.get(namespace): dictname, attrib, filter = kwdicts[namespace] dict = kw.get(dictname) if dict and attrib: dict = getattr(dict, attrib, None) else: raise raccoon.UnusableNamespaceError('%s uses unusable namespace: %s' % (local, namespace)) #if dict is None: # log.debug('calling %s-metadata on an unavailable namespace %s' % (opname, namespace) ) return func(local, dict)
def create_document(qname=None, ns=None, content=None, attributes=None, pubid=None, sysid=None): """ Create a document, with optional convenience arguments to create top-level information items qname - optional QName of the document element (which will be created) if QName is not given, no other arguments may be given ns - optional namespace of the document element content - optional Unicode that makes up text content to be set as the child of the document element pubid - optional public ID of the doctype (to be set on the document) sysid - optional system ID of the doctype (to be set on the document) """ if not qname: doc = bindery.root_base() return doc doc = bindery.root_base(doctype_name=qname, pubid=pubid, sysid=sysid) prefix, local = SplitQName(qname) doc_elem = doc.xml_element(qname, ns, attributes=attributes) doc.xml_append(doc_elem) if content: doc_elem.xml_append(content) return doc
def __delitem__(self, key): if isinstance(key, int): #child = self.__getitem__(key) #index = self.xml_parent.xml_children.index(child) self.xml_parent.xml_remove_child_at(key) else: force_type = None if isinstance(key, tuple): if len(key) == 3: force_type, key = key[0], key[1:] elif isinstance(key, basestring): key = (None, key) else: raise TypeError('Inappropriate key (%s)' % (key)) for attr, obj in self.xml_properties.items(): if self.is_attribute(attr): qname, ns = self.xml_attributes.get(attr) if (force_type in (None, Node.ATTRIBUTE_NODE) and key == (ns, SplitQName(qname)[1])): #The key references an XML attribute del self.xml_attributes[attr] #Bypass __delattr__ del self.__dict__[attr] break elif is_element(obj): if (force_type in (None, Node.ELEMENT_NODE) and key == (obj.namespaceURI, obj.localName)): self.xml_remove_child(obj) break else: raise KeyError( 'namespace/local name combination not found (%s)' % (str(key))) return
def matchName(node, prefixes, local): #if node.namespaceURI: #namespace aware node # return node.namespaceURI in prefixes.values() and node.localName == local if node.prefix is None: prefix, localName = SplitQName(node.nodeName) else: prefix, localName = node.prefix, node.localName return prefix in prefixes and localName == local
def createElementNS(self, namespaceURI, qualifiedName): prefix, localName = SplitQName(qualifiedName) element = Element(qualifiedName, namespaceURI, prefix, localName) element.ownerDocument = element.rootNode = self element.baseURI = self.baseURI #element.docIndex = self.nextIndex self.nextIndex += 3 # room for namespace and attribute nodes return element
def xml_to_python(self, qname, ns=None, check_clashes=None): prefix, local = SplitQName(qname) python_id = PY_REPLACE_PAT.sub('_', local) if python_id in RESERVED_NAMES: python_id = python_id + '_' if check_clashes: while python_id in check_clashes: python_id += '_' return python_id
def __init__(self, qname, ns, value, parent): self.namespaceURI = ns self.prefix, self.localName = SplitQName(qname) self.value = value self.nodeValue = value self.name = qname self.nodeName = qname self.rootNode = parent._rootNode() docIndex = id(value) return
def _attributes(self): try: attrs = self.xml_attributes except AttributeError: return {} keys = [(ns, SplitQName(qname)) for attr, (qname, ns) in self.xml_attributes.items()] values = [ xpath_attr_wrapper(qname, ns, unicode(getattr(self, attr)), self) for attr, (qname, ns) in self.xml_attributes.items() ] return dict(zip(keys, values))
def getAttributeNS(self, ns, local): try: attrs = self.xml_attributes except AttributeError: return {} keys = [(ns, SplitQName(qname)[1]) for attr, (qname, ns) in self.xml_attributes.items()] values = [ unicode(getattr(self, attr)) for attr, (qname, ns) in self.xml_attributes.items() ] attr_dict = dict(zip(keys, values)) return attr_dict.get((ns, local), "")
def setAttributeNS(self, namespaceURI, qualifiedName, value): prefix, localName = SplitQName(qualifiedName) key = self._get_attrkey(namespaceURI, localName) attr = self.attributes.get(key) if attr: # Reuse existing attribute node attr.prefix = prefix attr.nodeValue = attr.value = value return attr = Attr(qualifiedName, namespaceURI, prefix, localName, value) self._set_attribute(key, attr) return
def startElement(self, namespaceUri, tagName, namespaces, attributes): """ Handles a startElement event. Writes part of an element's start-tag or empty-element tag to the stream, and closes the start tag of the previous element, if one remained open. Writes the xmlns attributes for the given dictionary of namespaces, and invokes attribute() as neeeded to write the given dictionary of attributes. The namespaceUri argument is ignored in this class. """ if self._inElement: # Close current start tag self.writeAscii('>') else: self._inElement = True self.writeAscii('<') self.writeEncode(tagName, 'start-tag name') # Write the namespaces, in alphabetical order of prefixes, with # the default coming first (easy since None comes before any actual # Unicode value) prefixes = namespaces.items() prefixes.sort() parent_prefixes = self._ns_stack[-1].items() for prefix, uri in prefixes: #No redundant NSDecls if (prefix, uri) not in parent_prefixes: if prefix: self.attribute(namespaceUri, tagName, u"xmlns:"+prefix, uri) else: self.attribute(namespaceUri, tagName, u"xmlns", uri) self._ns_stack.append(self._ns_stack[-1].copy()) self._ns_stack[-1].update(namespaces) # Now the attributes attrs = attributes.items() attrs = [ (self._ns_stack[-1].get(SplitQName(name)[0], None), name, value) for name, value in attributes.items() ] attrs.sort() for ns, name, value in attrs: self.attribute(namespaceUri, tagName, name, value) return
def create_element(namer, qname, ns=None, ename=None): prefix, local = SplitQName(qname) if not ename: ename = namer.xml_to_python(qname, ns) ns_class = g_namespaces.setdefault(ns, namespace(ns, prefix)) if ns_class.binding_classes.has_key(local): class_ = ns_class.binding_classes[local] else: exec "class %s(element_base): pass" % ename in globals(), locals() class_ = locals()[ename] ns_class.binding_classes[local] = class_ instance = class_() instance.nodeName = qname if ns: #intern(ns) #Can't intern Unicode instance.xmlnsUri = ns instance.xmlnsPrefix = prefix instance.xmlnsLocalName = local instance.xml_namer = namer return instance
def create_element(xmlnaming_rule, xmlqname, xmlns=None, xmlename=None): xmlprefix, xmllocal = SplitQName(xmlqname) if not xmlename: xmlename = xmlnaming_rule.xml_to_python(xmllocal, xmlns) xmlns_class = g_namespaces.setdefault(xmlns, namespace(xmlns, xmlprefix)) if xmlns_class.binding_classes.has_key(xmlename): xmlclass = xmlns_class.binding_classes[xmlename] else: exec "class %s(element_base): pass" % xmlename in globals(), locals() xmlclass = locals()[xmlename] xmlns_class.binding_classes[xmlename] = xmlclass if not hasattr(xmlclass, "xml_naming_rule"): xmlclass.xml_naming_rule = xmlnaming_rule xmlinstance = xmlclass() xmlinstance.nodeName = xmlqname if xmlns: xmlinstance.xmlnsUri = xmlns xmlinstance.xmlnsPrefix = xmlprefix xmlinstance.xmlnsLocalName = xmllocal return xmlinstance
except SyntaxError, e: raise SyntaxError("Select Expression %s: %s" % (select, str(e))) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) nodeset = _select.evaluate(context) if not nodeset: raise XUpdateException( XUpdateException.INVALID_SELECT, node.getAttributeNS(EMPTY_NAMESPACE, u'select')) Domlette.XmlStrStrip(node.firstChild.data) new_name = node.firstChild.data.strip() (prefix, local) = SplitQName(new_name) if prefix: namespace = context.processorNss[prefix] else: namespace = EMPTY_NAMESPACE for refnode in nodeset: if refnode.nodeType == Node.ATTRIBUTE_NODE: parent = refnode.ownerElement parent.removeAttributeNode(refnode) parent.setAttributeNS(namespace, new_name, refnode.value) else: assert refnode.nodeType == Node.ELEMENT_NODE refnode.nodeName = refnode.tagName = new_name refnode.namespaceURI = namespace
for p in prefixes: match = g_prefixBindingPattern.match(p) if match is None: raise TypeError('Error in -P/--prefix arguments') nsmappings[match.group(1)] = match.group(2) defs = options.get('define', []) if not isinstance(defs, list): defs = [defs] top_level_params = {} for d in defs: match = g_paramBindingPattern.match(d) if match is None: raise TypeError('Error in -D/--define arguments') name = match.group(1) prefix, local = SplitQName(name) if prefix in nsmappings: name = (nsmappings[prefix], local) top_level_params[name] = match.group(2) # misc runtime flags ignore_pis = options.has_key('ignore') checktime = options.has_key('time') # -- Do the transformation ----------------------------------------- try: if source_isrc is None: raise TypeError('No source document to transform!')
def visit(self, context, node, preserveSpace): #FIXME: We should improve this function from this ugly-ass #switch thingie to dynamic dispatch if node.nodeType == Node.ELEMENT_NODE: xml_space = node.getAttributeNS(XML_NAMESPACE, 'space') if xml_space == 'preserve': preserveSpace = 1 elif xml_space == 'default': preserveSpace = 0 # else, no change if node.namespaceURI != XUPDATE_NS: self.writers[-1].startElement(node.nodeName, node.namespaceURI) # Process the attributes oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) for attr in node.attributes.values(): value = self.parseAVT(attr.value) value = value.evaluate(context) self.writers[-1].attribute(attr.nodeName, value, attr.namespaceURI) context.processorNss = oldNss # Now the children for child in node.childNodes: context = self.visit(context, child, preserveSpace) self.writers[-1].endElement(node.nodeName) return context # XUpdate elements try: restoreGraphContext = False graphURI = node.getAttributeNS(EMPTY_NAMESPACE, u'to-graph') if graphURI: graphURI = self.parseAVT(graphURI) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) graphURI = graphURI.evaluate(context) context.processorNss = oldNss context.node.ownerDocument.pushContext(graphURI) restoreGraphContext = True if node.localName == 'modifications': for n in node.childNodes: self.visit(context, n, preserveSpace) elif node.localName == 'remove': select = node.getAttributeNS(EMPTY_NAMESPACE, u'select') #import sys #print >>sys.stderr, 'removing', select if not select: raise XUpdateException(XUpdateException.NO_SELECT) _select = self.parseExpression(select) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) nodeset = _select.evaluate(context) if nodeset: #change from 4Suite -- why did it only delete the first node in the nodeset? #that's not in the spec or very intuitive #refnode = nodeset[0] for refnode in nodeset: if refnode.nodeType == Node.ATTRIBUTE_NODE: parent = refnode.ownerElement parent.removeAttributeNode(refnode) else: parent = refnode.parentNode if parent is None: parent = refnode.ownerDocument parent.removeChild(refnode) context.processorNss = oldNss elif node.localName in ['insert-after', 'insert-before']: select = node.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) _select = self.parseExpression(select) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) nodeset = _select.evaluate(context) if not nodeset: raise XUpdateException(XUpdateException.INVALID_SELECT) refnode = nodeset[0] self.pushDomResult(refnode.ownerDocument) try: for child in node.childNodes: context = self.visit(context, child, preserveSpace) finally: result = self.popResult() if node.localName == 'insert-before': refnode.parentNode.insertBefore(result, refnode) elif node.localName == 'insert-after': # if arg 2 is None, insertBefore behaves like appendChild refnode.parentNode.insertBefore( result, refnode.nextSibling) context.processorNss = oldNss elif node.localName == 'element': name = node.getAttributeNS(EMPTY_NAMESPACE, 'name') if not name: raise XUpdateException(XUpdateException.NO_NAME) _name = self.parseAVT(name) namespace = node.getAttributeNS(EMPTY_NAMESPACE, 'namespace') _namespace = self.parseAVT(namespace) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) name = _name.evaluate(context) namespace = _namespace and _namespace.evaluate(context) (prefix, local) = SplitQName(name) if not namespace: if prefix: namespace = context.processorNss[prefix] else: namespace = EMPTY_NAMESPACE self.writers[-1].startElement(name, namespace) for child in node.childNodes: context = self.visit(context, child, preserveSpace) self.writers[-1].endElement(name) context.processorNss = oldNss elif node.localName == 'attribute': name = node.getAttributeNS(EMPTY_NAMESPACE, 'name') if not name: raise XUpdateException(XUpdateException.NO_NAME) _name = self.parseAVT(name) namespace = node.getAttributeNS(EMPTY_NAMESPACE, 'namespace') _namespace = self.parseAVT(namespace) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) name = _name.evaluate(context) namespace = _namespace and _namespace.evaluate(context) (prefix, local) = SplitQName(name) if not namespace: if prefix: namespace = context.processorNss[prefix] else: namespace = EMPTY_NAMESPACE self.pushStringResult() try: for child in node.childNodes: context = self.visit(context, child, preserveSpace) finally: result = self.popResult() self.writers[-1].attribute(name, result, namespace) context.processorNss = oldNss elif node.localName == 'append': select = node.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) _select = self.parseExpression(select) child = node.getAttributeNS(EMPTY_NAMESPACE, u'child') or u'last()' _child = self.parseExpression(child) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) nodeset = _select.evaluate(context) if not nodeset: raise XUpdateException(XUpdateException.INVALID_SELECT, select) refnode = nodeset[0] self.pushDomResult(refnode.ownerDocument) try: for child in node.childNodes: context = self.visit(context, child, preserveSpace) finally: result = self.popResult() size = len(refnode.childNodes) con = Context.Context(refnode, 1, size, processorNss={'xupdate': XUPDATE_NS}) # Python lists is 0-indexed counting, node-sets 1-indexed position = int( Conversions.NumberValue(_child.evaluate(con))) if position >= size: refnode.appendChild(result) else: refnode.insertBefore(result, refnode.childNodes[position]) context.processorNss = oldNss elif node.localName == 'replace': select = node.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) try: _select = self.parseExpression(select) except SyntaxError, e: raise SyntaxError("Select Expression %s: %s" % (select, str(e))) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) nodeset = _select.evaluate(context) if not nodeset: raise XUpdateException( XUpdateException.INVALID_SELECT, node.getAttributeNS(EMPTY_NAMESPACE, u'select')) refnode = nodeset[0] self.pushDomResult(refnode.ownerDocument) try: for child in node.childNodes: context = self.visit(context, child, preserveSpace) finally: result = self.popResult() if refnode.nodeType == Node.ATTRIBUTE_NODE: owner = refnode.parentNode owner.removeAttributeNode(refnode) owner.setAttributeNodeNS(result) else: refnode.parentNode.replaceChild(result, refnode) context.processorNss = oldNss elif node.localName == 'update': select = node.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) try: _select = self.parseExpression(select) except SyntaxError, e: raise SyntaxError("Select Expression %s: %s" % (select, str(e))) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) nodeset = _select.evaluate(context) if not nodeset: raise XUpdateException( XUpdateException.INVALID_SELECT, node.getAttributeNS(EMPTY_NAMESPACE, u'select')) refnode = nodeset[0] if refnode.nodeType == Node.ATTRIBUTE_NODE: self.pushStringResult() try: for child in node.childNodes: context = self.visit(context, child, preserveSpace) finally: result = self.popResult() refnode.nodeValue = refnode.value = result else: self.pushDomResult(refnode.ownerDocument) try: for child in node.childNodes: context = self.visit(context, child, preserveSpace) finally: result = self.popResult() while refnode.firstChild: #print 'remove', id(refnode), id(refnode.firstChild), len(refnode.childNodes) refnode.removeChild(refnode.firstChild) refnode.appendChild(result) context.processorNss = oldNss
def createAttributeNS(self, namespaceURI, qualifiedName): prefix, localName = SplitQName(qualifiedName) attr = Attr(qualifiedName, namespaceURI, prefix, localName, u'') attr.ownerDocument = attr.rootNode = self.ownerDocument return attr