def _xu_element(self, context, element, preserveSpace): name = element.getAttributeNS(EMPTY_NAMESPACE, 'name') if not name: raise XUpdateException(XUpdateException.NO_NAME) _name = self.parseAVT(name) namespace = element.getAttributeNS(EMPTY_NAMESPACE, 'namespace') _namespace = self.parseAVT(namespace) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(element) 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 element.childNodes: self.visit(context, child, preserveSpace) self.writers[-1].endElement(name, namespace) context.processorNss = oldNss return
def _xu_attribute(self, context, node, preserveSpace): 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: self.visit(context, child, preserveSpace) finally: result = self.popResult() self.writers[-1].attribute(name, result, namespace) context.processorNss = oldNss return
def _xu_insert(self, context, element, preserveSpace): select = element.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(element) nodeset = self.evaluateExpression(context, select) if not nodeset: raise XUpdateException(XUpdateException.INVALID_SELECT, expr=select) for refnode in nodeset: self.pushDomResult(refnode.ownerDocument) try: for child in element.childNodes: self.visit(context, child, preserveSpace) finally: result = self.popResult() if element.localName == 'insert-before': refnode.parentNode.insertBefore(result, refnode) elif element.localName == 'insert-after': # if arg 2 is None, insertBefore behaves like appendChild refnode.parentNode.insertBefore(result, refnode.nextSibling) context.processorNss = oldNss return
def _xu_append(self, context, element, preserveSpace): select = element.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) child = element.getAttributeNS(EMPTY_NAMESPACE, u'child') or u'last()' oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(element) nodeset = self.evaluateExpression(context, select) if not isinstance(nodeset, Types.NodesetType) or not nodeset: # Error if not a node-set or empty node-set raise XUpdateException(XUpdateException.INVALID_SELECT, expr=select) for refnode in nodeset: self.pushDomResult(refnode.ownerDocument) # A wrapper element is used in case attributes are being added wrapper_localName = 'wrapper' wrapper_namespace = EMPTY_NAMESPACE try: self.writers[-1].startElement(wrapper_localName, wrapper_namespace) for node in element.childNodes: self.visit(context, node, preserveSpace) finally: self.writers[-1].endElement(wrapper_localName, wrapper_namespace) 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 = self.evaluateExpression(con, child) position = int(Conversions.NumberValue(position)) wrapper = result.childNodes[0] if wrapper.attributes and hasattr(refnode, 'setAttributeNodeNS'): for attr in wrapper.attributes.values(): refnode.setAttributeNodeNS(attr) # we operate on a shallow copy of the child nodes here to avoid # modifying the membership of the sequence we're interating over. for node in tuple(wrapper.childNodes): if position >= size: refnode.appendChild(node) else: refnode.insertBefore(node, refnode.childNodes[position]) context.processorNss = oldNss return
def _xu_if(self, context, element, preserveSpace): test = element.getAttributeNS(EMPTY_NAMESPACE, u'test') if not test: raise XUpdateException(XUpdateException.NO_TEST) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(element) result = self.evaluateExpression(context, test) if Conversions.BooleanValue(result): for node in element.childNodes: self.visit(context, node, preserveSpace) context.processorNss = oldNss return
def _xu_processing_instruction(self, context, element, preserveSpace): name = element.getAttributeNS(EMPTY_NAMESPACE, 'name') if not name: raise XUpdateException(XUpdateException.NO_NAME) _name = self.parseAVT(name) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) name = _name.evaluate(context) self.pushStringResult() try: for node in element.childNodes: self.visit(context, node, preserveSpace) finally: result = self.popResult() self.writers[-1].processingInstruction(name, result) context.processorNss = oldNss return
def _xu_remove(self, context, element, preserveSpace): select = element.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(element) nodeset = self.evaluateExpression(context, select) if nodeset: refnode = nodeset[0] 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(nodeset[0]) context.processorNss = oldNss return
def _xu_rename(self, context, element, preserveSpace): select = element.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(element) nodeset = self.evaluateExpression(context, select) if not nodeset: raise XUpdateException(XUpdateException.INVALID_SELECT, expr=select) new_name = XmlStrStrip(element.firstChild.data) (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: parent = refnode.parentNode if parent is None: parent = refnode.ownerDocument new_elem = refnode.ownerDocument.createElementNS(namespace, new_name) parent.replaceChild(new_elem, refnode) # Copy any existing attributes to the newly created element if refnode.attributes: for attr in refnode.attributes.values(): new_elem.setAttributeNodeNS(attr) # Now copy any children as well while refnode.firstChild: new_elem.appendChild(refnode.firstChild) context.processorNss = oldNss return
def _xu_value_of(self, context, element, preserveSpace): select = element.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(element) result = self.evaluateExpression(context, select) if isinstance(result, Types.NodesetType): for node in result: # should be OK to pass self as processor; # CopyNode only needs to access its .writers[-1] CopyNode(self, node) else: # a string, number or boolean if not isinstance(result, Types.StringType): result = Conversions.StringValue(result) self.writers[-1].text(result) context.processorNss = oldNss return
def _xu_variable(self, context, element, preserveSpace): name = element.getAttributeNS(EMPTY_NAMESPACE, 'name') if not name: raise XUpdateException(XUpdateException.NO_NAME) select = element.getAttributeNS(EMPTY_NAMESPACE, u'select') if select: oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(element) result = self.evaluateExpression(context, select) context.processorNss = oldNss else: result = Conversions.StringValue(element) (prefix, local) = SplitQName(name) if prefix: namespace = context.processorNss[prefix] else: namespace = EMPTY_NAMESPACE context.varBindings[(namespace, local)] = result return
def _xu_update(self, context, element, preserveSpace): select = element.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(element) nodeset = self.evaluateExpression(context, select) if not nodeset: raise XUpdateException(XUpdateException.INVALID_SELECT, expr=select) refnode = nodeset[0] if refnode.nodeType == Node.ATTRIBUTE_NODE: self.pushStringResult() try: for child in element.childNodes: self.visit(context, child, preserveSpace) finally: result = self.popResult() refnode.value = result else: self.pushDomResult(refnode.ownerDocument) try: for child in element.childNodes: self.visit(context, child, preserveSpace) finally: result = self.popResult() while refnode.firstChild: refnode.removeChild(refnode.firstChild) refnode.appendChild(result) context.processorNss = oldNss return
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
refnode.appendChild(result) context.processorNss = oldNss elif node.localName == 'rename': 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')) 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