And most of this is simply untested, yet...:
authorDaniel Veillard <veillard@src.gnome.org>
Fri, 2 Feb 2001 10:20:16 +0000 (10:20 +0000)
committerDaniel Veillard <veillard@src.gnome.org>
Fri, 2 Feb 2001 10:20:16 +0000 (10:20 +0000)
- FEATURES: updated
- transform.c: added xsl:element support
- namespaces.[ch]: added xsltGetSpecialNamespace()
- attributes.c: added xsl:attribute namespace support.
Daniel

ChangeLog
FEATURES
TODO
libxslt/attributes.c
libxslt/namespaces.c
libxslt/namespaces.h
libxslt/transform.c

index 1ffa204..57a0175 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Fri Feb  2 11:15:24 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
+
+       * FEATURES: updated
+       * transform.c: added xsl:element support
+       * namespaces.[ch]: added xsltGetSpecialNamespace()
+       * attributes.c: added xsl:attribute namespace support.
+
 Thu Feb  1 20:58:54 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
 
        * libxslt/Makefile.am libxslt/imports.[ch]: new module to
index 22959b0..eeeda7c 100644 (file)
--- a/FEATURES
+++ b/FEATURES
@@ -27,11 +27,11 @@ NO              Embedding Stylesheets
 Top Level Elements:
 ===================
 
-NO                 xsl:include
-NO                     href = uri-reference
+YES                xsl:include
+YES                    href = uri-reference
 
-NO                 xsl:import
-NO                     href = uri-reference
+YES                xsl:import
+YES                    href = uri-reference
 
 YES                xsl:strip-space
 YES                    elements = tokens
@@ -49,8 +49,8 @@ YES               xsl:namespace-alias
 YES                    stylesheet-prefix = prefix | "#default"
 YES                    result-prefix = prefix | "#default"
 
-NO                 xsl:attribute-set
-NO                     name = qname 
+YES                xsl:attribute-set
+YES                    name = qname 
 NO                     use-attribute-sets = qnames
 
 YES                xsl:variable
@@ -92,14 +92,14 @@ NO              xsl:apply-imports
 YES                xsl:call-template
 YES                    name = qname
 
-NO                 xsl:element
-NO                     name = { qname }
-NO                     namespace = { uri-reference }
-NO                     use-attribute-sets = qnames
+YES                xsl:element
+YES                    name = { qname }
+YES                    namespace = { uri-reference }
+YES                    use-attribute-sets = qnames
 
 YES                xsl:attribute
 YES                    name = { qname }
-NO                     namespace = { uri-reference }
+YES                    namespace = { uri-reference }
 
 YES                xsl:text
 YES                    disable-output-escaping = "yes" | "no"
@@ -110,7 +110,7 @@ YES                 name = { ncname }
 YES                xsl:comment
 
 YES                xsl:copy
-NO                     use-attribute-sets = qnames
+YES                    use-attribute-sets = qnames
 
 YES                xsl:value-of
 YES                    select = string-expression 
diff --git a/TODO b/TODO
index 2caefd1..acc15a6 100644 (file)
--- a/TODO
+++ b/TODO
@@ -15,8 +15,7 @@ Design:
     be a bit ugly ...
     
 Import:
-  -> parse them
-  -> provide functions to circulate in the import tree of stylesheets
+  -> make sure we use the cascade wherever it's needed
 
 Extra functions:
   -> document() should not be a problem since Result Tree Fragments are
@@ -64,6 +63,10 @@ Contextual error reporting:
                  *        *
                   ********
 
+Import:
+  -> parse them
+  -> provide functions to circulate in the import tree of stylesheets
+
 Extra functions:
   -> make a separate module.
   => done functions.[ch]
index f119f42..6863992 100644 (file)
@@ -325,16 +325,17 @@ xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr node,
        prop = NULL;
        prefix = NULL;
     }
+
     if ((prefix != NULL) && (xmlStrEqual(prefix, (const xmlChar *)"xmlns"))) {
 #ifdef DEBUG_PARSING
-           xsltGenericDebug(xsltGenericDebugContext,
-                "xslt:attribute : xmlns prefix forbidden\n");
+       xsltGenericDebug(xsltGenericDebugContext,
+            "xslt:attribute : xmlns prefix forbidden\n");
 #endif
        goto error;
     }
     prop = xsltEvalAttrValueTemplate(ctxt, inst, (const xmlChar *)"namespace");
     if (prop != NULL) {
-       TODO /* xsl:attribute namespace */
+       ns = xsltGetSpecialNamespace(ctxt, inst, prop, prefix, ctxt->insert);
     } else {
        if (prefix != NULL) {
            ns = xmlSearchNs(inst->doc, inst, prefix);
index 1e69978..b70670d 100644 (file)
@@ -120,6 +120,51 @@ error:
 }
 
 /**
+ * xsltGetSpecificNamespace:
+ * @ctxt:  a transformation context
+ * @cur:  the input node
+ * @URI:  the namespace URI
+ * @prefix:  the suggested prefix
+ * @out:  the output node (or its parent)
+ *
+ * Find the right namespace value for this URI, if needed create
+ * and add a new namespace decalaration on the node
+ *
+ * Returns the namespace node to use or NULL
+ */
+xmlNsPtr
+xsltGetSpecialNamespace(xsltTransformContextPtr ctxt, xmlNodePtr cur,
+               const xmlChar *URI, const xmlChar *prefix, xmlNodePtr out) {
+    xmlNsPtr ret;
+    static int prefixno = 1;
+    char nprefix[10];
+
+    if ((ctxt == NULL) || (cur == NULL) || (out == NULL) || (URI == NULL))
+       return(NULL);
+
+    if ((out->parent != NULL) &&
+       (out->parent->type == XML_ELEMENT_NODE) &&
+       (out->parent->ns != NULL) &&
+       (xmlStrEqual(out->parent->ns->href, URI)))
+       ret = out->parent->ns;
+    else
+       ret = xmlSearchNsByHref(out->doc, out, URI);
+
+    if (ret == NULL) {
+       if (prefix == NULL) {
+           do {
+               sprintf(nprefix, "ns%d", prefixno++);
+               ret = xmlSearchNs(out->doc, out, (xmlChar *)nprefix);
+           } while (ret != NULL);
+           prefix = (const xmlChar *) &nprefix[0];
+       }
+       if (out->type == XML_ELEMENT_NODE)
+           ret = xmlNewNs(out, URI, prefix);
+    }
+    return(ret);
+}
+
+/**
  * xsltGetNamespace:
  * @ctxt:  a transformation context
  * @cur:  the input node
index a4158a8..b972856 100644 (file)
@@ -21,6 +21,11 @@ xmlNsPtr     xsltGetNamespace        (xsltTransformContextPtr ctxt,
                                         xmlNodePtr cur,
                                         xmlNsPtr ns,
                                         xmlNodePtr out);
+xmlNsPtr       xsltGetSpecialNamespace (xsltTransformContextPtr ctxt,
+                                        xmlNodePtr cur,
+                                        const xmlChar *URI,
+                                        const xmlChar *prefix,
+                                        xmlNodePtr out);
 xmlNsPtr       xsltCopyNamespaceList   (xsltTransformContextPtr ctxt,
                                         xmlNodePtr node,
                                         xmlNsPtr cur);
index 5695ea2..9383bf3 100644 (file)
@@ -442,6 +442,94 @@ xsltCopy(xsltTransformContextPtr ctxt, xmlNodePtr node,
 }
 
 /**
+ * xsltElement:
+ * @ctxt:  a XSLT process context
+ * @node:  the node in the source tree.
+ * @inst:  the xslt element node
+ *
+ * Process the xslt element node on the source node
+ */
+void
+xsltElement(xsltTransformContextPtr ctxt, xmlNodePtr node,
+           xmlNodePtr inst) {
+    xmlChar *prop = NULL, *attributes = NULL;
+    xmlChar *ncname = NULL;
+    xmlChar *prefix = NULL;
+    xmlChar *value = NULL;
+    xmlNsPtr ns = NULL;
+    xmlNodePtr copy;
+
+
+    if (ctxt->insert == NULL)
+       return;
+    if (ctxt->insert->children != NULL) {
+       xsltGenericError(xsltGenericErrorContext,
+            "xslt:element : node has already children\n");
+       return;
+    }
+    prop = xsltEvalAttrValueTemplate(ctxt, inst, (const xmlChar *)"name");
+    if (prop == NULL) {
+       xsltGenericError(xsltGenericErrorContext,
+            "xslt:element : name is missing\n");
+       goto error;
+    }
+
+    ncname = xmlSplitQName2(prop, &prefix);
+    if (ncname == NULL) {
+       ncname = prop;
+       prop = NULL;
+       prefix = NULL;
+    }
+    prop = xsltEvalAttrValueTemplate(ctxt, inst, (const xmlChar *)"namespace");
+    if (prop != NULL) {
+       ns = xsltGetSpecialNamespace(ctxt, inst, prop, prefix, ctxt->insert);
+    } else {
+       if (prefix != NULL) {
+           if (!xmlStrncasecmp(prefix, (xmlChar *)"xml", 3)) {
+#ifdef DEBUG_PARSING
+               xsltGenericDebug(xsltGenericDebugContext,
+                    "xslt:element : xml prefix forbidden\n");
+#endif
+               goto error;
+           }
+           ns = xmlSearchNs(inst->doc, inst, prefix);
+           if (ns == NULL) {
+               xsltGenericError(xsltGenericErrorContext,
+                   "no namespace bound to prefix %s\n", prefix);
+           } else {
+               ns = xsltGetNamespace(ctxt, inst, ns, ctxt->insert);
+           }
+       }
+    }
+
+    copy = xmlNewDocNode(ctxt->output, ns, ncname, NULL);
+    if (copy == NULL) {
+       xsltGenericError(xsltGenericErrorContext,
+           "xsl:element : creation of %s failed\n", ncname);
+       goto error;
+    }
+    xmlAddChild(ctxt->insert, copy);
+    attributes = xsltEvalAttrValueTemplate(ctxt, inst,
+                                      (const xmlChar *)"use-attribute-sets");
+    if (attributes != NULL) {
+       xsltApplyAttributeSet(ctxt, node, inst, attributes);
+        xmlFree(attributes);
+    }
+    
+    xsltApplyOneTemplate(ctxt, ctxt->node, inst->children);
+
+error:
+    if (prop != NULL)
+        xmlFree(prop);
+    if (ncname != NULL)
+        xmlFree(ncname);
+    if (prefix != NULL)
+        xmlFree(prefix);
+    if (value != NULL)
+        xmlFree(value);
+}
+
+/**
  * xsltComment:
  * @ctxt:  a XSLT process context
  * @node:  the node in the source tree.
@@ -1174,12 +1262,10 @@ xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
                ctxt->insert = insert;
                xsltAttribute(ctxt, node, cur);
                ctxt->insert = oldInsert;
-               /*******
            } else if (IS_XSLT_NAME(cur, "element")) {
                ctxt->insert = insert;
                xsltElement(ctxt, node, cur);
                ctxt->insert = oldInsert;
-               *******/
            } else if (IS_XSLT_NAME(cur, "comment")) {
                ctxt->insert = insert;
                xsltComment(ctxt, node, cur);