about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/lxml/xsltext.pxi
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/lxml/xsltext.pxi
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are here HEAD master
Diffstat (limited to '.venv/lib/python3.12/site-packages/lxml/xsltext.pxi')
-rw-r--r--.venv/lib/python3.12/site-packages/lxml/xsltext.pxi242
1 files changed, 242 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/lxml/xsltext.pxi b/.venv/lib/python3.12/site-packages/lxml/xsltext.pxi
new file mode 100644
index 00000000..21894b9e
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/lxml/xsltext.pxi
@@ -0,0 +1,242 @@
+# XSLT extension elements
+
+cdef class XSLTExtension:
+    """Base class of an XSLT extension element.
+    """
+    def execute(self, context, self_node, input_node, output_parent):
+        """execute(self, context, self_node, input_node, output_parent)
+        Execute this extension element.
+
+        Subclasses must override this method.  They may append
+        elements to the `output_parent` element here, or set its text
+        content.  To this end, the `input_node` provides read-only
+        access to the current node in the input document, and the
+        `self_node` points to the extension element in the stylesheet.
+
+        Note that the `output_parent` parameter may be `None` if there
+        is no parent element in the current context (e.g. no content
+        was added to the output tree yet).
+        """
+        pass
+
+    def apply_templates(self, _XSLTContext context not None, node, output_parent=None,
+                        *, elements_only=False, remove_blank_text=False):
+        """apply_templates(self, context, node, output_parent=None, elements_only=False, remove_blank_text=False)
+
+        Call this method to retrieve the result of applying templates
+        to an element.
+
+        The return value is a list of elements or text strings that
+        were generated by the XSLT processor.  If you pass
+        ``elements_only=True``, strings will be discarded from the result
+        list.  The option ``remove_blank_text=True`` will only discard
+        strings that consist entirely of whitespace (e.g. formatting).
+        These options do not apply to Elements, only to bare string results.
+
+        If you pass an Element as `output_parent` parameter, the result
+        will instead be appended to the element (including attributes
+        etc.) and the return value will be `None`.  This is a safe way
+        to generate content into the output document directly, without
+        having to take care of special values like text or attributes.
+        Note that the string discarding options will be ignored in this
+        case.
+        """
+        cdef xmlNode* c_parent
+        cdef xmlNode* c_node
+        cdef xmlNode* c_context_node
+        assert context._xsltCtxt is not NULL, "XSLT context not initialised"
+        c_context_node = _roNodeOf(node)
+        #assert c_context_node.doc is context._xsltContext.node.doc, \
+        #    "switching input documents during transformation is not currently supported"
+
+        if output_parent is not None:
+            c_parent = _nonRoNodeOf(output_parent)
+        else:
+            c_parent = tree.xmlNewDocNode(
+                context._xsltCtxt.output, NULL, <unsigned char*>"fake-parent", NULL)
+
+        c_node = context._xsltCtxt.insert
+        context._xsltCtxt.insert = c_parent
+        xslt.xsltProcessOneNode(
+            context._xsltCtxt, c_context_node, NULL)
+        context._xsltCtxt.insert = c_node
+
+        if output_parent is not None:
+            return None
+
+        try:
+            return self._collectXSLTResultContent(
+                context, c_parent, elements_only, remove_blank_text)
+        finally:
+            # free all intermediate nodes that will not be freed by proxies
+            tree.xmlFreeNode(c_parent)
+
+    def process_children(self, _XSLTContext context not None, output_parent=None,
+                         *, elements_only=False, remove_blank_text=False):
+        """process_children(self, context, output_parent=None, elements_only=False, remove_blank_text=False)
+
+        Call this method to process the XSLT content of the extension
+        element itself.
+
+        The return value is a list of elements or text strings that
+        were generated by the XSLT processor.  If you pass
+        ``elements_only=True``, strings will be discarded from the result
+        list.  The option ``remove_blank_text=True`` will only discard
+        strings that consist entirely of whitespace (e.g. formatting).
+        These options do not apply to Elements, only to bare string results.
+
+        If you pass an Element as `output_parent` parameter, the result
+        will instead be appended to the element (including attributes
+        etc.) and the return value will be `None`.  This is a safe way
+        to generate content into the output document directly, without
+        having to take care of special values like text or attributes.
+        Note that the string discarding options will be ignored in this
+        case.
+        """
+        cdef xmlNode* c_parent
+        cdef xslt.xsltTransformContext* c_ctxt = context._xsltCtxt
+        cdef xmlNode* c_old_output_parent = c_ctxt.insert
+        assert context._xsltCtxt is not NULL, "XSLT context not initialised"
+
+        # output_parent node is used for adding results instead of
+        # elements list used in apply_templates, that's easier and allows to
+        # use attributes added to extension element with <xsl:attribute>.
+
+        if output_parent is not None:
+            c_parent = _nonRoNodeOf(output_parent)
+        else:
+            c_parent = tree.xmlNewDocNode(
+                context._xsltCtxt.output, NULL, <unsigned char*>"fake-parent", NULL)
+
+        c_ctxt.insert = c_parent
+        xslt.xsltApplyOneTemplate(c_ctxt,
+            c_ctxt.node, c_ctxt.inst.children, NULL, NULL)
+        c_ctxt.insert = c_old_output_parent
+
+        if output_parent is not None:
+            return None
+
+        try:
+            return self._collectXSLTResultContent(
+                context, c_parent, elements_only, remove_blank_text)
+        finally:
+            # free all intermediate nodes that will not be freed by proxies
+            tree.xmlFreeNode(c_parent)
+
+    cdef _collectXSLTResultContent(self, _XSLTContext context, xmlNode* c_parent,
+                                   bint elements_only, bint remove_blank_text):
+        cdef xmlNode* c_node
+        cdef xmlNode* c_next
+        cdef _ReadOnlyProxy proxy
+        cdef list results = [] # or maybe _collectAttributes(c_parent, 2) ?
+        c_node = c_parent.children
+        while c_node is not NULL:
+            c_next = c_node.next
+            if c_node.type == tree.XML_TEXT_NODE:
+                if not elements_only:
+                    s = funicode(c_node.content)
+                    if not remove_blank_text or s.strip():
+                        results.append(s)
+                    s = None
+            elif c_node.type == tree.XML_ELEMENT_NODE:
+                proxy = _newReadOnlyProxy(
+                    context._extension_element_proxy, c_node)
+                results.append(proxy)
+                # unlink node and make sure it will be freed later on
+                tree.xmlUnlinkNode(c_node)
+                proxy.free_after_use()
+            else:
+                raise TypeError, \
+                    f"unsupported XSLT result type: {c_node.type}"
+            c_node = c_next
+        return results
+
+
+cdef _registerXSLTExtensions(xslt.xsltTransformContext* c_ctxt,
+                             extension_dict):
+    for ns_utf, name_utf in extension_dict:
+        xslt.xsltRegisterExtElement(
+            c_ctxt, _xcstr(name_utf), _xcstr(ns_utf),
+            <xslt.xsltTransformFunction>_callExtensionElement)
+
+cdef void _callExtensionElement(xslt.xsltTransformContext* c_ctxt,
+                                xmlNode* c_context_node,
+                                xmlNode* c_inst_node,
+                                void* dummy) noexcept with gil:
+    cdef _XSLTContext context
+    cdef XSLTExtension extension
+    cdef python.PyObject* dict_result
+    cdef xmlNode* c_node
+    cdef _ReadOnlyProxy context_node = None, self_node = None
+    cdef object output_parent # not restricted to ro-nodes
+    c_uri = _getNs(c_inst_node)
+    if c_uri is NULL:
+        # not allowed, and should never happen
+        return
+    if c_ctxt.xpathCtxt.userData is NULL:
+        # just for safety, should never happen
+        return
+    context = <_XSLTContext>c_ctxt.xpathCtxt.userData
+    try:
+        try:
+            dict_result = python.PyDict_GetItem(
+                context._extension_elements, (c_uri, c_inst_node.name))
+            if dict_result is NULL:
+                raise KeyError, f"extension element {funicode(c_inst_node.name)} not found"
+            extension = <object>dict_result
+
+            try:
+                # build the context proxy nodes
+                self_node = _newReadOnlyProxy(None, c_inst_node)
+                if _isElement(c_ctxt.insert):
+                    output_parent = _newAppendOnlyProxy(self_node, c_ctxt.insert)
+                else:
+                    # may be the document node or other stuff
+                    output_parent = _newOpaqueAppendOnlyNodeWrapper(c_ctxt.insert)
+                if c_context_node.type in (tree.XML_DOCUMENT_NODE,
+                                           tree.XML_HTML_DOCUMENT_NODE):
+                    c_node = tree.xmlDocGetRootElement(<xmlDoc*>c_context_node)
+                    if c_node is not NULL:
+                        context_node = _newReadOnlyProxy(self_node, c_node)
+                    else:
+                        context_node = None
+                elif c_context_node.type in (tree.XML_ATTRIBUTE_NODE,
+                                             tree.XML_TEXT_NODE,
+                                             tree.XML_CDATA_SECTION_NODE):
+                    # this isn't easy to support using read-only
+                    # nodes, as the smart-string factory must
+                    # instantiate the parent proxy somehow...
+                    raise TypeError(f"Unsupported element type: {c_context_node.type}")
+                else:
+                    context_node  = _newReadOnlyProxy(self_node, c_context_node)
+
+                # run the XSLT extension
+                context._extension_element_proxy = self_node
+                extension.execute(context, self_node, context_node, output_parent)
+            finally:
+                context._extension_element_proxy = None
+                if self_node is not None:
+                    _freeReadOnlyProxies(self_node)
+        except Exception as e:
+            try:
+                e = unicode(e).encode("UTF-8")
+            except:
+                e = repr(e).encode("UTF-8")
+            message = python.PyBytes_FromFormat(
+                "Error executing extension element '%s': %s",
+                c_inst_node.name, _cstr(e))
+            xslt.xsltTransformError(c_ctxt, NULL, c_inst_node, "%s", message)
+            context._exc._store_raised()
+        except:
+            # just in case
+            message = python.PyBytes_FromFormat(
+                "Error executing extension element '%s'", c_inst_node.name)
+            xslt.xsltTransformError(c_ctxt, NULL, c_inst_node, "%s", message)
+            context._exc._store_raised()
+    except:
+        # no Python functions here - everything can fail...
+        xslt.xsltTransformError(c_ctxt, NULL, c_inst_node,
+                                "Error during XSLT extension element evaluation")
+        context._exc._store_raised()
+    finally:
+        return  # swallow any further exceptions