2 * namespaces.c: Implementation of the XSLT namespaces handling
5 * http://www.w3.org/TR/1999/REC-xslt-19991116
7 * See Copyright for the status of this software.
16 #ifdef HAVE_SYS_TYPES_H
17 #include <sys/types.h>
35 #include <libxml/xmlmemory.h>
36 #include <libxml/tree.h>
37 #include <libxml/hash.h>
38 #include <libxml/xmlerror.h>
39 #include <libxml/uri.h>
41 #include "xsltInternals.h"
42 #include "xsltutils.h"
43 #include "namespaces.h"
48 /************************************************************************
52 ************************************************************************/
56 * @style: the XSLT stylesheet
57 * @node: the xsl:namespace-alias node
59 * Read the stylesheet-prefix and result-prefix attributes, register
60 * them as well as the corresponding namespace.
63 xsltNamespaceAlias(xsltStylesheetPtr style, xmlNodePtr node) {
69 sprefix = xsltGetNsProp(node, (const xmlChar *)"stylesheet-prefix",
71 if (sprefix == NULL) {
72 xsltPrintErrorContext(NULL, style, node);
73 xsltGenericError(xsltGenericErrorContext,
74 "namespace-alias: stylesheet-prefix attribute missing\n");
77 rprefix = xsltGetNsProp(node, (const xmlChar *)"result-prefix",
79 if (rprefix == NULL) {
80 xsltPrintErrorContext(NULL, style, node);
81 xsltGenericError(xsltGenericErrorContext,
82 "namespace-alias: result-prefix attribute missing\n");
85 if (xmlStrEqual(sprefix, (const xmlChar *)"#default")) {
86 sNs = xmlSearchNs(node->doc, node, NULL);
88 sNs = xmlSearchNs(node->doc, node, sprefix);
90 if ((sNs == NULL) || (sNs->href == NULL)) {
91 xsltPrintErrorContext(NULL, style, node);
92 xsltGenericError(xsltGenericErrorContext,
93 "namespace-alias: prefix %s not bound to any namespace\n",
97 if (xmlStrEqual(rprefix, (const xmlChar *)"#default")) {
98 rNs = xmlSearchNs(node->doc, node, NULL);
100 rNs = xmlSearchNs(node->doc, node, rprefix);
102 if ((rNs == NULL) || (rNs->href == NULL)) {
103 xsltPrintErrorContext(NULL, style, node);
104 xsltGenericError(xsltGenericErrorContext,
105 "namespace-alias: prefix %s not bound to any namespace\n",
109 if (style->nsAliases == NULL)
110 style->nsAliases = xmlHashCreate(10);
111 if (style->nsAliases == NULL) {
112 xsltPrintErrorContext(NULL, style, node);
113 xsltGenericError(xsltGenericErrorContext,
114 "namespace-alias: cannot create hash table\n");
117 xmlHashAddEntry((xmlHashTablePtr) style->nsAliases,
118 sNs->href, (void *) rNs->href);
128 * xsltGetSpecialNamespace:
129 * @ctxt: a transformation context
130 * @cur: the input node
131 * @URI: the namespace URI
132 * @prefix: the suggested prefix
133 * @out: the output node (or its parent)
135 * Find the right namespace value for this URI, if needed create
136 * and add a new namespace decalaration on the node
138 * Returns the namespace node to use or NULL
141 xsltGetSpecialNamespace(xsltTransformContextPtr ctxt, xmlNodePtr cur,
142 const xmlChar *URI, const xmlChar *prefix, xmlNodePtr out) {
144 static int prefixno = 1;
147 if ((ctxt == NULL) || (cur == NULL) || (out == NULL) || (URI == NULL))
150 if ((out->parent != NULL) &&
151 (out->parent->type == XML_ELEMENT_NODE) &&
152 (out->parent->ns != NULL) &&
153 (xmlStrEqual(out->parent->ns->href, URI)))
154 ret = out->parent->ns;
156 ret = xmlSearchNsByHref(out->doc, out, URI);
159 if (prefix == NULL) {
161 sprintf(nprefix, "ns%d", prefixno++);
162 ret = xmlSearchNs(out->doc, out, (xmlChar *)nprefix);
163 } while (ret != NULL);
164 prefix = (const xmlChar *) &nprefix[0];
166 if (out->type == XML_ELEMENT_NODE)
167 ret = xmlNewNs(out, URI, prefix);
174 * @ctxt: a transformation context
175 * @cur: the input node
177 * @out: the output node (or its parent)
179 * Find the right namespace value for this prefix, if needed create
180 * and add a new namespace decalaration on the node
181 * Handle namespace aliases
183 * Returns the namespace node to use or NULL
186 xsltGetNamespace(xsltTransformContextPtr ctxt, xmlNodePtr cur, xmlNsPtr ns,
188 xsltStylesheetPtr style;
190 const xmlChar *URI = NULL; /* the replacement URI */
192 if ((ctxt == NULL) || (cur == NULL) || (out == NULL) || (ns == NULL))
196 while (style != NULL) {
197 if (style->nsAliases != NULL)
198 URI = (const xmlChar *)
199 xmlHashLookup(ctxt->style->nsAliases, ns->href);
203 style = xsltNextImport(style);
209 if ((out->parent != NULL) &&
210 (out->parent->type == XML_ELEMENT_NODE) &&
211 (out->parent->ns != NULL) &&
212 (xmlStrEqual(out->parent->ns->href, URI)))
213 ret = out->parent->ns;
215 ret = xmlSearchNsByHref(out->doc, out, URI);
218 if (out->type == XML_ELEMENT_NODE)
219 ret = xmlNewNs(out, URI, ns->prefix);
225 * xsltCopyNamespaceList:
226 * @ctxt: a transformation context
227 * @node: the target node
228 * @cur: the first namespace
230 * Do a copy of an namespace list. If @node is non-NULL the
231 * new namespaces are added automatically. This handles namespaces
234 * Returns: a new xmlNsPtr, or NULL in case of error.
237 xsltCopyNamespaceList(xsltTransformContextPtr ctxt, xmlNodePtr node,
245 if (cur->type != XML_NAMESPACE_DECL)
249 * One can add namespaces only on element nodes
251 if ((node != NULL) && (node->type != XML_ELEMENT_NODE))
254 while (cur != NULL) {
255 if (cur->type != XML_NAMESPACE_DECL)
257 if (!xmlStrEqual(cur->href, XSLT_NAMESPACE)) {
258 /* TODO apply cascading */
259 URI = (const xmlChar *) xmlHashLookup(ctxt->style->nsAliases,
262 q = xmlNewNs(node, URI, cur->prefix);
264 q = xmlNewNs(node, cur->href, cur->prefix);
280 * @ctxt: a transformation context
281 * @node: the target node
282 * @cur: the namespace node
284 * Do a copy of an namespace node. If @node is non-NULL the
285 * new namespaces are added automatically. This handles namespaces
288 * Returns: a new xmlNsPtr, or NULL in case of error.
291 xsltCopyNamespace(xsltTransformContextPtr ctxt, xmlNodePtr node,
298 if (cur->type != XML_NAMESPACE_DECL)
302 * One can add namespaces only on element nodes
304 if ((node != NULL) && (node->type != XML_ELEMENT_NODE))
307 if (!xmlStrEqual(cur->href, XSLT_NAMESPACE)) {
308 URI = (const xmlChar *) xmlHashLookup(ctxt->style->nsAliases,
311 ret = xmlNewNs(node, URI, cur->prefix);
313 ret = xmlNewNs(node, cur->href, cur->prefix);
321 * xsltFreeNamespaceAliasHashes:
322 * @style: an XSLT stylesheet
324 * Free up the memory used by namespaces aliases
327 xsltFreeNamespaceAliasHashes(xsltStylesheetPtr style) {
328 if (style->nsAliases != NULL)
329 xmlHashFree((xmlHashTablePtr) style->nsAliases, NULL);
330 style->nsAliases = NULL;