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:
@@ -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
|
||||
|
||||
10
FEATURES
10
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
|
||||
|
||||
8
TODO
8
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
|
||||
|
||||
@@ -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
204
libxslt/namespaces.c
Normal 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
32
libxslt/namespaces.h
Normal 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__ */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user