예제 #1
0
    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
예제 #2
0
    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
예제 #3
0
    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
예제 #4
0
    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
예제 #5
0
    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
예제 #6
0
    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
예제 #7
0
    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
예제 #8
0
    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
예제 #9
0
    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
예제 #10
0
    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
예제 #11
0
    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
예제 #12
0
    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
예제 #13
0
                        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