summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--FEATURES10
-rw-r--r--TODO8
-rw-r--r--libxslt/Makefile.am2
-rw-r--r--libxslt/namespaces.c204
-rw-r--r--libxslt/namespaces.h32
-rw-r--r--libxslt/templates.c19
-rw-r--r--libxslt/transform.c58
-rw-r--r--libxslt/xslt.c3
-rw-r--r--libxslt/xsltInternals.h5
10 files changed, 284 insertions, 65 deletions
diff --git a/ChangeLog b/ChangeLog
index cd2eefdd..ea0627e0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Sun Jan 28 17:25:35 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
+
+ * FEATURES TODO: updates
+ * libxslt/namespaces.[ch] libxslt/templates.c libxslt/transform.c
+ libxslt/xslt.c libxslt/xsltInternals.h: added support for
+ namespace aliases and cleaned up the overall namespace related
+ code. This materialize as a new module.
+
Sun Jan 28 08:41:10 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
* configure.in libxslt.spec.in: changes needed for libxml2-devel
diff --git a/FEATURES b/FEATURES
index 16e2efa4..08e00c81 100644
--- a/FEATURES
+++ b/FEATURES
@@ -45,9 +45,9 @@ YES name = qname
YES priority = number
NO mode = qname
-NO xsl:namespace-alias
-NO stylesheet-prefix = prefix | "#default"
-NO result-prefix = prefix | "#default"
+YES xsl:namespace-alias
+YES stylesheet-prefix = prefix | "#default"
+YES result-prefix = prefix | "#default"
NO xsl:attribute-set
NO name = qname
@@ -99,7 +99,7 @@ NO use-attribute-sets = qnames
YES xsl:attribute
YES name = { qname }
-YES namespace = { uri-reference }
+NO namespace = { uri-reference }
YES xsl:text
YES disable-output-escaping = "yes" | "no"
@@ -193,7 +193,7 @@ YES Built-in Template Rules
YES match="*|/"
YES match="text()|@*"
YES match="processing-instruction()|comment()"
-NO Namespace
+YES Namespace
NO Mode
NO Extension Elements
diff --git a/TODO b/TODO
index 47d246bb..22536374 100644
--- a/TODO
+++ b/TODO
@@ -5,9 +5,6 @@
********
Doc:
- - put a page at http://xmlsoft.org/XSLT/
- - generate/transform the DocBook to HTML
- - add HTML to package
- manpage and doc for xsltproc
Design:
@@ -92,3 +89,8 @@ Pattern tester:
-> also put fast lookup for "text()", "comment()", "node()"
based patterns lists.
=> done
+
+Doc:
+ - put a page at http://xmlsoft.org/XSLT/
+ - generate/transform the DocBook to HTML
+ - add HTML to package
diff --git a/libxslt/Makefile.am b/libxslt/Makefile.am
index 6036591e..f582bf1c 100644
--- a/libxslt/Makefile.am
+++ b/libxslt/Makefile.am
@@ -12,6 +12,7 @@ xsltinc_HEADERS = \
templates.h \
variables.h \
functions.h \
+ namespaces.h \
transform.h \
xsltInternals.h
@@ -22,6 +23,7 @@ libxslt_la_SOURCES = \
templates.c \
variables.c \
functions.c \
+ namespaces.c \
transform.c
diff --git a/libxslt/namespaces.c b/libxslt/namespaces.c
new file mode 100644
index 00000000..98424535
--- /dev/null
+++ b/libxslt/namespaces.c
@@ -0,0 +1,204 @@
+/*
+ * namespaces.c: Implementation of the XSLT namespaces handling
+ *
+ * Reference:
+ * http://www.w3.org/TR/1999/REC-xslt-19991116
+ *
+ * See Copyright for the status of this software.
+ *
+ * Daniel.Veillard@imag.fr
+ */
+
+#include "xsltconfig.h"
+
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_MATH_H
+#include <math.h>
+#endif
+#ifdef HAVE_FLOAT_H
+#include <float.h>
+#endif
+#ifdef HAVE_IEEEFP_H
+#include <ieeefp.h>
+#endif
+#ifdef HAVE_NAN_H
+#include <nan.h>
+#endif
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
+#include <libxml/hash.h>
+#include <libxml/xmlerror.h>
+#include <libxml/uri.h>
+#include "xslt.h"
+#include "xsltInternals.h"
+#include "xsltutils.h"
+#include "namespaces.h"
+
+
+
+/************************************************************************
+ * *
+ * Module interfaces *
+ * *
+ ************************************************************************/
+
+/**
+ * xsltNamespaceAlias:
+ * @style: the XSLT stylesheet
+ * @node: the xsl:namespace-alias node
+ *
+ * Read the stylesheet-prefix and result-prefix attributes, register
+ * them as well as the corresponding namespace.
+ */
+void
+xsltNamespaceAlias(xsltStylesheetPtr style, xmlNodePtr node) {
+ xmlChar *sprefix;
+ xmlNsPtr sNs;
+ xmlChar *rprefix;
+ xmlNsPtr rNs;
+
+ sprefix = xmlGetNsProp(node, (const xmlChar *)"stylesheet-prefix",
+ XSLT_NAMESPACE);
+ if (sprefix == NULL) {
+ xsltGenericError(xsltGenericErrorContext,
+ "namespace-alias: stylesheet-prefix attribute missing\n");
+ return;
+ }
+ rprefix = xmlGetNsProp(node, (const xmlChar *)"result-prefix",
+ XSLT_NAMESPACE);
+ if (rprefix == NULL) {
+ xsltGenericError(xsltGenericErrorContext,
+ "namespace-alias: result-prefix attribute missing\n");
+ goto error;
+ }
+ if (xmlStrEqual(sprefix, (const xmlChar *)"#default")) {
+ sNs = xmlSearchNs(node->doc, node, NULL);
+ } else {
+ sNs = xmlSearchNs(node->doc, node, sprefix);
+ }
+ if ((sNs == NULL) || (sNs->href == NULL)) {
+ xsltGenericError(xsltGenericErrorContext,
+ "namespace-alias: prefix %s not bound to any namespace\n",
+ sprefix);
+ goto error;
+ }
+ if (xmlStrEqual(rprefix, (const xmlChar *)"#default")) {
+ rNs = xmlSearchNs(node->doc, node, NULL);
+ } else {
+ rNs = xmlSearchNs(node->doc, node, rprefix);
+ }
+ if ((rNs == NULL) || (rNs->href == NULL)) {
+ xsltGenericError(xsltGenericErrorContext,
+ "namespace-alias: prefix %s not bound to any namespace\n",
+ rprefix);
+ goto error;
+ }
+ if (style->nsAliases == NULL)
+ style->nsAliases = xmlHashCreate(10);
+ if (style->nsAliases == NULL) {
+ xsltGenericError(xsltGenericErrorContext,
+ "namespace-alias: cannot create hash table\n");
+ goto error;
+ }
+ xmlHashAddEntry((xmlHashTablePtr) style->nsAliases,
+ sNs->href, (void *) rNs->href);
+
+error:
+ if (sprefix != NULL)
+ xmlFree(sprefix);
+ if (rprefix != NULL)
+ xmlFree(rprefix);
+}
+
+/**
+ * xsltGetNamespace:
+ * @ctxt: a transformation context
+ * @cur: the input node
+ * @ns: the namespace
+ * @out: the output node (or its parent)
+ *
+ * Find the right namespace value for this prefix, if needed create
+ * and add a new namespace decalaration on the node
+ * Handle namespace aliases
+ *
+ * Returns the namespace node to use or NULL
+ */
+xmlNsPtr
+xsltGetNamespace(xsltTransformContextPtr ctxt, xmlNodePtr cur, xmlNsPtr ns,
+ xmlNodePtr out) {
+ xmlNsPtr ret;
+ const xmlChar *URI;
+
+ if ((ctxt == NULL) || (cur == NULL) || (out == NULL) || (ns == NULL))
+ return(NULL);
+ if ((out->type == XML_ELEMENT_NODE) && (out->ns != NULL) &&
+ ((out->ns->href != NULL) && (ns->href != NULL) &&
+ (xmlStrEqual(out->ns->href, ns->href)))) {
+ return(out->ns);
+ }
+
+ /* TODO apply cascading */
+ if (ctxt->style->nsAliases != NULL) {
+ URI = (const xmlChar *) xmlHashLookup(ctxt->style->nsAliases, ns->href);
+ if (URI == NULL)
+ URI = ns->href;
+ } else
+ URI = ns->href;
+
+ ret = xmlSearchNsByHref(out->doc, out, URI);
+ if (ret == NULL) {
+ if (out->type == XML_ELEMENT_NODE)
+ ret = xmlNewNs(out, ns->href, ns->prefix);
+ }
+ return(ret);
+}
+
+/**
+ * xsltCopyNamespaceList:
+ * @ctxt: a transformation context
+ * @node: the target node
+ * @cur: the first namespace
+ *
+ * Do a copy of an namespace list. If @node is non-NULL the
+ * new namespaces are added automatically. This handles namespaces
+ * aliases
+ *
+ * Returns: a new xmlNsPtr, or NULL in case of error.
+ */
+xmlNsPtr
+xsltCopyNamespaceList(xsltTransformContextPtr ctxt, xmlNodePtr node,
+ xmlNsPtr cur) {
+ xmlNsPtr ret = NULL;
+ xmlNsPtr p = NULL,q;
+ const xmlChar *URI;
+
+ while (cur != NULL) {
+ if (!xmlStrEqual(cur->href, XSLT_NAMESPACE)) {
+ /* TODO apply cascading */
+ URI = (const xmlChar *) xmlHashLookup(ctxt->style->nsAliases,
+ cur->href);
+ if (URI != NULL) {
+ q = xmlNewNs(node, URI, cur->prefix);
+ } else {
+ q = xmlNewNs(node, cur->href, cur->prefix);
+ }
+ if (p == NULL) {
+ ret = p = q;
+ } else {
+ p->next = q;
+ p = q;
+ }
+ }
+ cur = cur->next;
+ }
+ return(ret);
+}
+
diff --git a/libxslt/namespaces.h b/libxslt/namespaces.h
new file mode 100644
index 00000000..14c2f4df
--- /dev/null
+++ b/libxslt/namespaces.h
@@ -0,0 +1,32 @@
+/*
+ * namespaces.h: interface for the XSLT namespace handling
+ *
+ * See Copyright for the status of this software.
+ *
+ * Daniel.Veillard@imag.fr
+ */
+
+#ifndef __XML_XSLT_NAMESPACES_H__
+#define __XML_XSLT_NAMESPACES_H__
+
+#include <libxml/tree.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void xsltNamespaceAlias (xsltStylesheetPtr style,
+ xmlNodePtr node);
+xmlNsPtr xsltGetNamespace (xsltTransformContextPtr ctxt,
+ xmlNodePtr cur,
+ xmlNsPtr ns,
+ xmlNodePtr out);
+xmlNsPtr xsltCopyNamespaceList (xsltTransformContextPtr ctxt,
+ xmlNodePtr node,
+ xmlNsPtr cur);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __XML_XSLT_NAMESPACES_H__ */
+
diff --git a/libxslt/templates.c b/libxslt/templates.c
index ebc0b4d3..66d6e407 100644
--- a/libxslt/templates.c
+++ b/libxslt/templates.c
@@ -25,6 +25,7 @@
#include "functions.h"
#include "templates.h"
#include "transform.h"
+#include "namespaces.h"
#define DEBUG_TEMPLATES
@@ -264,23 +265,7 @@ xsltAttrTemplateProcess(xsltTransformContextPtr ctxt, xmlNodePtr target,
if (ret == NULL) return(NULL);
ret->parent = target;
- if ((cur->ns != NULL) && (target != NULL)) {
- if ((target != NULL) && (target->ns != NULL) &&
- (xmlStrEqual(target->ns->href, cur->ns->href))) {
- ret->ns = target->ns;
- } else {
- xmlNsPtr ns;
-
- ns = xmlSearchNsByHref(ctxt->output, target, cur->ns->href);
- if (ns != NULL) {
- ret->ns = ns;
- } else {
- ns = xmlNewNs(target, cur->ns->href, cur->ns->prefix);
- ret->ns = ns;
- }
- }
- } else
- ret->ns = NULL;
+ ret->ns = xsltGetNamespace(ctxt, cur->parent, cur->ns, target);
if (cur->children != NULL) {
xmlChar *in = xmlNodeListGetString(ctxt->doc, cur->children, 1);
diff --git a/libxslt/transform.c b/libxslt/transform.c
index 81eb3c96..171e45b2 100644
--- a/libxslt/transform.c
+++ b/libxslt/transform.c
@@ -30,6 +30,7 @@
#include "pattern.h"
#include "transform.h"
#include "variables.h"
+#include "namespaces.h"
#include "templates.h"
#define DEBUG_PROCESS
@@ -349,12 +350,6 @@ xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr node,
"xslt:attribute : node has already children\n");
return;
}
- prop = xsltEvalAttrValueTemplate(ctxt, inst, (const xmlChar *)"namespace");
- if (prop != NULL) {
- TODO /* xsl:attribute namespace */
- xmlFree(prop);
- return;
- }
prop = xsltEvalAttrValueTemplate(ctxt, inst, (const xmlChar *)"name");
if (prop == NULL) {
xsltGenericError(xsltGenericErrorContext,
@@ -373,13 +368,23 @@ xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr node,
"xslt:attribute : xmlns forbidden\n");
goto error;
}
- if ((prefix != NULL) && (ns == NULL)) {
- ns = xmlSearchNs(ctxt->insert->doc, ctxt->insert, prefix);
- if (ns == NULL) {
- xsltGenericError(xsltGenericErrorContext,
- "no namespace bound to prefix %s\n", prefix);
+ prop = xsltEvalAttrValueTemplate(ctxt, inst, (const xmlChar *)"namespace");
+ if (prop != NULL) {
+ TODO /* xsl:attribute namespace */
+ xmlFree(prop);
+ return;
+ } else {
+ if (prefix != NULL) {
+ 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);
+ }
}
}
+
value = xsltEvalTemplateString(ctxt, node, inst);
if (value == NULL) {
@@ -528,34 +533,9 @@ xsltCopyNode(xsltTransformContextPtr ctxt, xmlNodePtr node,
* Add namespaces as they are needed
*/
if (node->nsDef != NULL)
- copy->nsDef = xmlCopyNamespaceList(node->nsDef);
+ xsltCopyNamespaceList(ctxt, copy, node->nsDef);
if (node->ns != NULL) {
- /*
- * optimization, if the namespace is already the
- * on on the parent node, reuse it directly
- *
- * TODO: check possible mess with xmlCopyNamespaceList
- */
- if ((insert->type == XML_ELEMENT_NODE) &&
- (insert->ns != NULL) &&
- (xmlStrEqual(insert->ns->href, node->ns->href))) {
- copy->ns = insert->ns;
- } else {
- xmlNsPtr ns;
-
- /*
- * Look in the output tree if the namespace is
- * already in scope.
- */
- ns = xmlSearchNsByHref(ctxt->output, copy,
- node->ns->href);
- if (ns != NULL)
- copy->ns = ns;
- else {
- ns = xmlNewNs(copy, node->ns->href,
- node->ns->prefix);
- }
- }
+ copy->ns = xsltGetNamespace(ctxt, node, node->ns, insert);
}
} else {
xsltGenericError(xsltGenericErrorContext,
@@ -697,7 +677,7 @@ xsltCallTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
xmlChar *prefix = NULL;
xmlNsPtr ns = NULL;
xsltTemplatePtr template;
- xmlNodePtr cur;
+ xmlNodePtr cur = NULL;
int has_param = 0;
diff --git a/libxslt/xslt.c b/libxslt/xslt.c
index 4d4898c9..66a838b8 100644
--- a/libxslt/xslt.c
+++ b/libxslt/xslt.c
@@ -24,6 +24,7 @@
#include "xsltInternals.h"
#include "pattern.h"
#include "variables.h"
+#include "namespaces.h"
#include "xsltutils.h"
#define DEBUG_PARSING
@@ -784,7 +785,7 @@ xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) {
#endif
xsltParseStylesheetTemplate(style, cur);
} else if (IS_XSLT_NAME(cur, "namespace-alias")) {
- TODO /* Handle namespace-alias */
+ xsltNamespaceAlias(style, cur);
} else {
xsltGenericError(xsltGenericErrorContext,
"xsltParseStylesheetTop: ignoring unknown %s element\n",
diff --git a/libxslt/xsltInternals.h b/libxslt/xsltInternals.h
index 7250e7c3..9056dc52 100644
--- a/libxslt/xsltInternals.h
+++ b/libxslt/xsltInternals.h
@@ -102,6 +102,11 @@ struct _xsltStylesheet {
void *commentMatch; /* template based on comment() */
/*
+ * Namespace aliases
+ */
+ xmlHashTablePtr nsAliases; /* the namespace alias hash tables */
+
+ /*
* Output related stuff.
*/
xmlChar *method; /* the output method */