[Lxml-checkins] r52025 - in lxml/trunk: . src/lxml src/lxml/tests

scoder at codespeak.net scoder at codespeak.net
Sun Mar 2 09:31:22 CET 2008


Author: scoder
Date: Sun Mar  2 09:31:20 2008
New Revision: 52025

Modified:
   lxml/trunk/   (props changed)
   lxml/trunk/TODO.txt
   lxml/trunk/src/lxml/readonlytree.pxi
   lxml/trunk/src/lxml/tests/test_xslt.py
   lxml/trunk/src/lxml/xslt.pxd
Log:
 r3664 at delle:  sbehnel | 2008-03-02 08:56:19 +0100
  r3650 at delle:  sbehnel | 2008-02-29 21:39:21 +0100
  initial import: will use read-only elements to access the XSLT tree, the input tree and the output tree
 


Modified: lxml/trunk/TODO.txt
==============================================================================
--- lxml/trunk/TODO.txt	(original)
+++ lxml/trunk/TODO.txt	Sun Mar  2 09:31:20 2008
@@ -45,6 +45,22 @@
   by libxml2 (patch exists)
 
 
+XSLT extension elements
+-----------------------
+
+* implementation: one base class that represents the result parent
+
+  - .append(), .extend() and .text will add to the result tree (no .tail)
+
+  - difference: Elements should be copied, not moved?  (will break
+    later changes, but this just means that Elements in the result
+    tree are immutable, including those that were added)
+
+  - how to make input tree read-only? maybe just document?
+
+  - docs: "once in the result tree, Elements must no longer be changed"?
+
+
 lxml 2.0
 ========
 

Modified: lxml/trunk/src/lxml/readonlytree.pxi
==============================================================================
--- lxml/trunk/src/lxml/readonlytree.pxi	(original)
+++ lxml/trunk/src/lxml/readonlytree.pxi	Sun Mar  2 09:31:20 2008
@@ -207,17 +207,21 @@
     cdef _ReadOnlyElementProxy NEW_RO_PROXY "PY_NEW" (object t)
 
 cdef _ReadOnlyElementProxy _newReadOnlyProxy(
-    _ReadOnlyElementProxy sourceProxy, xmlNode* c_node):
+    _ReadOnlyElementProxy source_proxy, xmlNode* c_node):
     cdef _ReadOnlyElementProxy el
     el = NEW_RO_PROXY(_ReadOnlyElementProxy)
     el._c_node = c_node
-    if sourceProxy is None:
+    _initReadOnlyProxy(el, source_proxy)
+    return el
+
+cdef inline _initReadOnlyProxy(_ReadOnlyElementProxy el,
+                               _ReadOnlyElementProxy source_proxy):
+    if source_proxy is None:
         el._source_proxy = el
         el._dependent_proxies = [el]
     else:
-        el._source_proxy = sourceProxy
-        python.PyList_Append(sourceProxy._dependent_proxies, el)
-    return el
+        el._source_proxy = source_proxy
+        python.PyList_Append(source_proxy._dependent_proxies, el)
 
 cdef _freeReadOnlyProxies(_ReadOnlyElementProxy sourceProxy):
     cdef _ReadOnlyElementProxy el
@@ -228,3 +232,71 @@
     for el in sourceProxy._dependent_proxies:
         el._c_node = NULL
     del sourceProxy._dependent_proxies[:]
+
+
+cdef class _ReadOnlyRootElementProxy(_ReadOnlyElementProxy):
+    """A read-only element that frees the subtree on deallocation.
+    """
+    def __dealloc__(self):
+        if self._c_node is not NULL:
+            tree.xmlFreeNode(self._c_node)
+
+cdef class _AppendOnlyElementProxy(_ReadOnlyElementProxy):
+    """A read-only element that allows adding children and changing the
+    text content (i.e. everything that adds to the subtree).
+    """
+    cpdef append(self, other_element):
+        """Append a copy of an Element to the list of children.
+        """
+        cdef xmlNode* c_next
+        cdef xmlNode* c_node
+        self._assertNode()
+        c_node = _roNodeOf(other_element)
+        c_node = _copyNodeToDoc(c_node, self._c_node.doc)
+        c_next = c_node.next
+        tree.xmlAddChild(self._c_node, c_node)
+        _moveTail(c_next, c_node)
+            
+    def extend(self, elements):
+        """Append a copy of all Elements from a sequence to the list of
+        children.
+        """
+        self._assertNode()
+        for element in elements:
+            self.append(element)
+
+    property text:
+        """Text before the first subelement. This is either a string or the
+        value None, if there was no text.
+        """
+        def __get__(self):
+            self._assertNode()
+            return _collectText(self._c_node.children)
+
+        def __set__(self, value):
+            self._assertNode()
+            if isinstance(value, QName):
+                value = python.PyUnicode_FromEncodedObject(
+                    _resolveQNameText(self, value), 'UTF-8', 'strict')
+            _setNodeText(self._c_node, value)
+
+cdef _AppendOnlyElementProxy _newAppendOnlyProxy(
+    _ReadOnlyElementProxy source_proxy, xmlNode* c_node):
+    cdef _AppendOnlyElementProxy el
+    el = <_AppendOnlyElementProxy>NEW_RO_PROXY(_AppendOnlyElementProxy)
+    el._c_node = c_node
+    _initReadOnlyProxy(el, source_proxy)
+    return el
+
+cdef xmlNode* _roNodeOf(element) except NULL:
+    cdef xmlNode* c_node
+    if isinstance(element, _Element):
+        c_node = (<_Element>element)._c_node
+    elif isinstance(element, _ReadOnlyElementProxy):
+        c_node = (<_ReadOnlyElementProxy>element)._c_node
+    else:
+        raise TypeError("invalid value to append()")
+
+    if c_node is NULL:
+        raise TypeError("invalid element")
+    return c_node

Modified: lxml/trunk/src/lxml/tests/test_xslt.py
==============================================================================
--- lxml/trunk/src/lxml/tests/test_xslt.py	(original)
+++ lxml/trunk/src/lxml/tests/test_xslt.py	Sun Mar  2 09:31:20 2008
@@ -604,6 +604,26 @@
         self.assertEquals(self._rootstring(result),
                           '<A>X</A>')
 
+    def test_extension_element(self):
+        tree = self.parse('<a><b>B</b></a>')
+        style = self.parse('''\
+<xsl:stylesheet version="1.0"
+    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+    xmlns:myns="testns"
+    extension-element-prefixes="myns"
+    exclude-result-prefixes="myns">
+  <xsl:template match="a">
+    <A><myns:mytext>b</myns:mytext></A>
+  </xsl:template>
+</xsl:stylesheet>''')
+
+        class mytext(etree.XSLTExtension):
+            pass
+
+        result = tree.xslt(style, extensions={})
+        self.assertEquals(self._rootstring(result),
+                          '<A><b>X</b></A>')
+
     def test_xslt_document_XML(self):
         # make sure document('') works from parsed strings
         xslt = etree.XSLT(etree.XML("""\

Modified: lxml/trunk/src/lxml/xslt.pxd
==============================================================================
--- lxml/trunk/src/lxml/xslt.pxd	(original)
+++ lxml/trunk/src/lxml/xslt.pxd	Sun Mar  2 09:31:20 2008
@@ -1,4 +1,4 @@
-from tree cimport xmlDoc, xmlDict
+from tree cimport xmlDoc, xmlNode, xmlDict
 from xpath cimport xmlXPathContext, xmlXPathFunction
 
 cdef extern from "libxslt/xslt.h":
@@ -22,6 +22,11 @@
         void* _private
         xmlDict* dict
         int profile
+        xmlNode* node
+        xmlDoc* output
+        xmlNode* insert
+
+    ctypedef struct xsltStackElem
 
     cdef xsltStylesheet* xsltParseStylesheetDoc(xmlDoc* doc) nogil
     cdef void xsltFreeStylesheet(xsltStylesheet* sheet) nogil
@@ -59,6 +64,9 @@
                                          char** params, char* output,
                                          void* profile,
                                          xsltTransformContext* context) nogil
+    cdef void xsltProcessOneNode(xsltTransformContext* ctxt,
+                                 xmlNode* contextNode,
+                                 xsltStackElem* params)
     cdef xsltTransformContext* xsltNewTransformContext(xsltStylesheet* style,
                                                        xmlDoc* doc) nogil
     cdef void xsltFreeTransformContext(xsltTransformContext* context) nogil


More information about the lxml-checkins mailing list