1
0
mirror of https://gitlab.gnome.org/GNOME/libxslt synced 2025-11-08 11:02:18 +03:00

Work done on namespace support:

- 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.
Daniel
This commit is contained in:
Daniel Veillard
2001-01-28 16:27:44 +00:00
parent 31de2205b1
commit fe557f63a6
10 changed files with 284 additions and 65 deletions

View File

@@ -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

View File

@@ -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

8
TODO
View File

@@ -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

View File

@@ -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

204
libxslt/namespaces.c Normal file
View File

@@ -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);
}

32
libxslt/namespaces.h Normal file
View File

@@ -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__ */

View File

@@ -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);

View File

@@ -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);
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;

View File

@@ -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",

View File

@@ -101,6 +101,11 @@ struct _xsltStylesheet {
void *piMatch; /* template based on processing-instruction() */
void *commentMatch; /* template based on comment() */
/*
* Namespace aliases
*/
xmlHashTablePtr nsAliases; /* the namespace alias hash tables */
/*
* Output related stuff.
*/