| OLD | NEW |
| 1 /* | 1 /* |
| 2 * namespaces.c: Implementation of the XSLT namespaces handling | 2 * namespaces.c: Implementation of the XSLT namespaces handling |
| 3 * | 3 * |
| 4 * Reference: | 4 * Reference: |
| 5 * http://www.w3.org/TR/1999/REC-xslt-19991116 | 5 * http://www.w3.org/TR/1999/REC-xslt-19991116 |
| 6 * | 6 * |
| 7 * See Copyright for the status of this software. | 7 * See Copyright for the status of this software. |
| 8 * | 8 * |
| 9 * daniel@veillard.com | 9 * daniel@veillard.com |
| 10 */ | 10 */ |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 #include "xsltutils.h" | 48 #include "xsltutils.h" |
| 49 #include "namespaces.h" | 49 #include "namespaces.h" |
| 50 #include "imports.h" | 50 #include "imports.h" |
| 51 | 51 |
| 52 /************************************************************************ | 52 /************************************************************************ |
| 53 * * | 53 * * |
| 54 * Module interfaces * | 54 * Module interfaces * |
| 55 * * | 55 * * |
| 56 ************************************************************************/ | 56 ************************************************************************/ |
| 57 | 57 |
| 58 #ifdef XSLT_REFACTORED | 58 #ifdef XSLT_REFACTORED |
| 59 static xsltNsAliasPtr | 59 static xsltNsAliasPtr |
| 60 xsltNewNsAlias(xsltCompilerCtxtPtr cctxt) | 60 xsltNewNsAlias(xsltCompilerCtxtPtr cctxt) |
| 61 { | 61 { |
| 62 xsltNsAliasPtr ret; | 62 xsltNsAliasPtr ret; |
| 63 | 63 |
| 64 if (cctxt == NULL) | 64 if (cctxt == NULL) |
| 65 return(NULL); | 65 return(NULL); |
| 66 | 66 |
| 67 ret = (xsltNsAliasPtr) xmlMalloc(sizeof(xsltNsAlias)); | 67 ret = (xsltNsAliasPtr) xmlMalloc(sizeof(xsltNsAlias)); |
| 68 if (ret == NULL) { | 68 if (ret == NULL) { |
| 69 xsltTransformError(NULL, cctxt->style, NULL, | 69 xsltTransformError(NULL, cctxt->style, NULL, |
| 70 "Internal error in xsltNewNsAlias(): Memory allocation failed.\n"); | 70 "Internal error in xsltNewNsAlias(): Memory allocation failed.\n"); |
| 71 cctxt->style->errors++; | 71 cctxt->style->errors++; |
| 72 return(NULL); | 72 return(NULL); |
| 73 } | 73 } |
| 74 memset(ret, 0, sizeof(xsltNsAlias)); | 74 memset(ret, 0, sizeof(xsltNsAlias)); |
| 75 /* | 75 /* |
| 76 * TODO: Store the item at current stylesheet-level. | 76 * TODO: Store the item at current stylesheet-level. |
| 77 */ | 77 */ |
| 78 ret->next = cctxt->nsAliases; | 78 ret->next = cctxt->nsAliases; |
| 79 cctxt->nsAliases = ret; | 79 cctxt->nsAliases = ret; |
| 80 | 80 |
| 81 return(ret); | 81 return(ret); |
| 82 } | 82 } |
| 83 #endif /* XSLT_REFACTORED */ | 83 #endif /* XSLT_REFACTORED */ |
| 84 /** | 84 /** |
| 85 * xsltNamespaceAlias: | 85 * xsltNamespaceAlias: |
| 86 * @style: the XSLT stylesheet | 86 * @style: the XSLT stylesheet |
| 87 * @node: the xsl:namespace-alias node | 87 * @node: the xsl:namespace-alias node |
| 88 * | 88 * |
| 89 * Read the stylesheet-prefix and result-prefix attributes, register | 89 * Read the stylesheet-prefix and result-prefix attributes, register |
| 90 * them as well as the corresponding namespace. | 90 * them as well as the corresponding namespace. |
| 91 */ | 91 */ |
| 92 void | 92 void |
| 93 xsltNamespaceAlias(xsltStylesheetPtr style, xmlNodePtr node) | 93 xsltNamespaceAlias(xsltStylesheetPtr style, xmlNodePtr node) |
| 94 { | 94 { |
| 95 xmlChar *resultPrefix = NULL; | 95 xmlChar *resultPrefix = NULL; |
| 96 xmlChar *stylePrefix = NULL; | 96 xmlChar *stylePrefix = NULL; |
| 97 xmlNsPtr literalNs = NULL; | 97 xmlNsPtr literalNs = NULL; |
| 98 xmlNsPtr targetNs = NULL; | 98 xmlNsPtr targetNs = NULL; |
| 99 | 99 |
| 100 #ifdef XSLT_REFACTORED | 100 #ifdef XSLT_REFACTORED |
| 101 xsltNsAliasPtr alias; | 101 xsltNsAliasPtr alias; |
| 102 | 102 |
| 103 if ((style == NULL) || (node == NULL)) | 103 if ((style == NULL) || (node == NULL)) |
| 104 return; | 104 return; |
| 105 | 105 |
| 106 /* | 106 /* |
| 107 * SPEC XSLT 1.0: | 107 * SPEC XSLT 1.0: |
| 108 * "If a namespace URI is declared to be an alias for multiple | 108 * "If a namespace URI is declared to be an alias for multiple |
| 109 * different namespace URIs, then the declaration with the highest | 109 * different namespace URIs, then the declaration with the highest |
| 110 * import precedence is used. It is an error if there is more than | 110 * import precedence is used. It is an error if there is more than |
| 111 * one such declaration. An XSLT processor may signal the error; | 111 * one such declaration. An XSLT processor may signal the error; |
| 112 * if it does not signal the error, it must recover by choosing, | 112 * if it does not signal the error, it must recover by choosing, |
| 113 * from amongst the declarations with the highest import precedence, | 113 * from amongst the declarations with the highest import precedence, |
| 114 * the one that occurs last in the stylesheet." | 114 * the one that occurs last in the stylesheet." |
| 115 * | 115 * |
| 116 * SPEC TODO: Check for the errors mentioned above. | 116 * SPEC TODO: Check for the errors mentioned above. |
| 117 */ | 117 */ |
| 118 /* | 118 /* |
| 119 * NOTE that the XSLT 2.0 also *does* use the NULL namespace if | 119 * NOTE that the XSLT 2.0 also *does* use the NULL namespace if |
| 120 * "#default" is used and there's no default namespace is scope. | 120 * "#default" is used and there's no default namespace is scope. |
| 121 * I.e., this is *not* an error. | 121 * I.e., this is *not* an error. |
| 122 * Most XSLT 1.0 implementations work this way. | 122 * Most XSLT 1.0 implementations work this way. |
| 123 * The XSLT 1.0 spec has nothing to say on the subject. | 123 * The XSLT 1.0 spec has nothing to say on the subject. |
| 124 */ | 124 */ |
| 125 /* | 125 /* |
| 126 * Attribute "stylesheet-prefix". | 126 * Attribute "stylesheet-prefix". |
| 127 */ | 127 */ |
| 128 stylePrefix = xmlGetNsProp(node, (const xmlChar *)"stylesheet-prefix", NULL)
; | 128 stylePrefix = xmlGetNsProp(node, (const xmlChar *)"stylesheet-prefix", NULL)
; |
| 129 if (stylePrefix == NULL) { | 129 if (stylePrefix == NULL) { |
| 130 xsltTransformError(NULL, style, node, | 130 xsltTransformError(NULL, style, node, |
| 131 "The attribute 'stylesheet-prefix' is missing.\n"); | 131 "The attribute 'stylesheet-prefix' is missing.\n"); |
| 132 return; | 132 return; |
| 133 } | 133 } |
| 134 if (xmlStrEqual(stylePrefix, (const xmlChar *)"#default")) | 134 if (xmlStrEqual(stylePrefix, (const xmlChar *)"#default")) |
| 135 » literalNs = xmlSearchNs(node->doc, node, NULL);» | 135 » literalNs = xmlSearchNs(node->doc, node, NULL); |
| 136 else { | 136 else { |
| 137 literalNs = xmlSearchNs(node->doc, node, stylePrefix); | 137 literalNs = xmlSearchNs(node->doc, node, stylePrefix); |
| 138 if (literalNs == NULL) { | 138 if (literalNs == NULL) { |
| 139 xsltTransformError(NULL, style, node, | 139 xsltTransformError(NULL, style, node, |
| 140 "Attribute 'stylesheet-prefix': There's no namespace " | 140 "Attribute 'stylesheet-prefix': There's no namespace " |
| 141 "declaration in scope for the prefix '%s'.\n", | 141 "declaration in scope for the prefix '%s'.\n", |
| 142 stylePrefix); | 142 stylePrefix); |
| 143 goto error; | 143 goto error; |
| 144 } | 144 } |
| 145 } | 145 } |
| 146 /* | 146 /* |
| 147 * Attribute "result-prefix". | 147 * Attribute "result-prefix". |
| 148 */ | 148 */ |
| 149 resultPrefix = xmlGetNsProp(node, (const xmlChar *)"result-prefix", NULL); | 149 resultPrefix = xmlGetNsProp(node, (const xmlChar *)"result-prefix", NULL); |
| 150 if (resultPrefix == NULL) { | 150 if (resultPrefix == NULL) { |
| 151 xsltTransformError(NULL, style, node, | 151 xsltTransformError(NULL, style, node, |
| 152 "The attribute 'result-prefix' is missing.\n"); | 152 "The attribute 'result-prefix' is missing.\n"); |
| 153 goto error; | 153 goto error; |
| 154 } | 154 } |
| 155 if (xmlStrEqual(resultPrefix, (const xmlChar *)"#default")) | 155 if (xmlStrEqual(resultPrefix, (const xmlChar *)"#default")) |
| 156 targetNs = xmlSearchNs(node->doc, node, NULL); | 156 targetNs = xmlSearchNs(node->doc, node, NULL); |
| 157 else { | 157 else { |
| 158 targetNs = xmlSearchNs(node->doc, node, resultPrefix); | 158 targetNs = xmlSearchNs(node->doc, node, resultPrefix); |
| 159 | 159 |
| 160 if (targetNs == NULL) { | 160 if (targetNs == NULL) { |
| 161 xsltTransformError(NULL, style, node, | 161 xsltTransformError(NULL, style, node, |
| 162 "Attribute 'result-prefix': There's no namespace " | 162 "Attribute 'result-prefix': There's no namespace " |
| 163 "declaration in scope for the prefix '%s'.\n", | 163 "declaration in scope for the prefix '%s'.\n", |
| 164 stylePrefix); | 164 stylePrefix); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 190 * TODO: Has this an effect at all? | 190 * TODO: Has this an effect at all? |
| 191 * | 191 * |
| 192 * <xsl:namespace-alias stylesheet-prefix="foo" | 192 * <xsl:namespace-alias stylesheet-prefix="foo" |
| 193 * result-prefix="#default"/> | 193 * result-prefix="#default"/> |
| 194 * From namespace to no namespace. | 194 * From namespace to no namespace. |
| 195 * | 195 * |
| 196 * <xsl:namespace-alias stylesheet-prefix="#default" | 196 * <xsl:namespace-alias stylesheet-prefix="#default" |
| 197 * result-prefix="foo"/> | 197 * result-prefix="foo"/> |
| 198 * From no namespace to namespace. | 198 * From no namespace to namespace. |
| 199 */ | 199 */ |
| 200 | 200 |
| 201 » | 201 |
| 202 /* | 202 /* |
| 203 * Store the ns-node in the alias-object. | 203 * Store the ns-node in the alias-object. |
| 204 */ | 204 */ |
| 205 alias = xsltNewNsAlias(XSLT_CCTXT(style)); | 205 alias = xsltNewNsAlias(XSLT_CCTXT(style)); |
| 206 if (alias == NULL) | 206 if (alias == NULL) |
| 207 return; | 207 return; |
| 208 alias->literalNs = literalNs; | 208 alias->literalNs = literalNs; |
| 209 alias->targetNs = targetNs; | 209 alias->targetNs = targetNs; |
| 210 XSLT_CCTXT(style)->hasNsAliases = 1; | 210 XSLT_CCTXT(style)->hasNsAliases = 1; |
| 211 | 211 |
| 212 | 212 |
| 213 #else /* XSLT_REFACTORED */ | 213 #else /* XSLT_REFACTORED */ |
| 214 const xmlChar *literalNsName; | 214 const xmlChar *literalNsName; |
| 215 const xmlChar *targetNsName; | 215 const xmlChar *targetNsName; |
| 216 | 216 |
| 217 | 217 |
| 218 if ((style == NULL) || (node == NULL)) | 218 if ((style == NULL) || (node == NULL)) |
| 219 return; | 219 return; |
| 220 | 220 |
| 221 stylePrefix = xmlGetNsProp(node, (const xmlChar *)"stylesheet-prefix", NULL)
; | 221 stylePrefix = xmlGetNsProp(node, (const xmlChar *)"stylesheet-prefix", NULL)
; |
| 222 if (stylePrefix == NULL) { | 222 if (stylePrefix == NULL) { |
| 223 xsltTransformError(NULL, style, node, | 223 xsltTransformError(NULL, style, node, |
| 224 "namespace-alias: stylesheet-prefix attribute missing\n"); | 224 "namespace-alias: stylesheet-prefix attribute missing\n"); |
| 225 return; | 225 return; |
| 226 } | 226 } |
| 227 resultPrefix = xmlGetNsProp(node, (const xmlChar *)"result-prefix", NULL); | 227 resultPrefix = xmlGetNsProp(node, (const xmlChar *)"result-prefix", NULL); |
| 228 if (resultPrefix == NULL) { | 228 if (resultPrefix == NULL) { |
| 229 xsltTransformError(NULL, style, node, | 229 xsltTransformError(NULL, style, node, |
| 230 "namespace-alias: result-prefix attribute missing\n"); | 230 "namespace-alias: result-prefix attribute missing\n"); |
| 231 goto error; | 231 goto error; |
| 232 } | 232 } |
| 233 | 233 |
| 234 if (xmlStrEqual(stylePrefix, (const xmlChar *)"#default")) { | 234 if (xmlStrEqual(stylePrefix, (const xmlChar *)"#default")) { |
| 235 literalNs = xmlSearchNs(node->doc, node, NULL); | 235 literalNs = xmlSearchNs(node->doc, node, NULL); |
| 236 if (literalNs == NULL) { | 236 if (literalNs == NULL) { |
| 237 literalNsName = NULL; | 237 literalNsName = NULL; |
| 238 } else | 238 } else |
| 239 literalNsName = literalNs->href; /* Yes - set for nsAlias table */ | 239 literalNsName = literalNs->href; /* Yes - set for nsAlias table */ |
| 240 } else { | 240 } else { |
| 241 literalNs = xmlSearchNs(node->doc, node, stylePrefix); | 241 literalNs = xmlSearchNs(node->doc, node, stylePrefix); |
| 242 | 242 |
| 243 if ((literalNs == NULL) || (literalNs->href == NULL)) { | 243 if ((literalNs == NULL) || (literalNs->href == NULL)) { |
| 244 xsltTransformError(NULL, style, node, | 244 xsltTransformError(NULL, style, node, |
| 245 "namespace-alias: prefix %s not bound to any namespace\n", | 245 "namespace-alias: prefix %s not bound to any namespace\n", |
| 246 stylePrefix); | 246 stylePrefix); |
| 247 goto error; | 247 goto error; |
| 248 } else | 248 } else |
| 249 literalNsName = literalNs->href; | 249 literalNsName = literalNs->href; |
| 250 } | 250 } |
| 251 | 251 |
| 252 /* | 252 /* |
| (...skipping 15 matching lines...) Expand all Loading... |
| 268 "namespace-alias: prefix %s not bound to any namespace\n", | 268 "namespace-alias: prefix %s not bound to any namespace\n", |
| 269 resultPrefix); | 269 resultPrefix); |
| 270 goto error; | 270 goto error; |
| 271 } else | 271 } else |
| 272 targetNsName = targetNs->href; | 272 targetNsName = targetNs->href; |
| 273 } | 273 } |
| 274 /* | 274 /* |
| 275 * Special case: if #default is used for | 275 * Special case: if #default is used for |
| 276 * the stylesheet-prefix (literal namespace) and there's no default | 276 * the stylesheet-prefix (literal namespace) and there's no default |
| 277 * namespace in scope, we'll use style->defaultAlias for this. | 277 * namespace in scope, we'll use style->defaultAlias for this. |
| 278 */ | 278 */ |
| 279 if (literalNsName == NULL) { | 279 if (literalNsName == NULL) { |
| 280 if (targetNs != NULL) { | 280 if (targetNs != NULL) { |
| 281 /* | 281 /* |
| 282 * BUG TODO: Is it not sufficient to have only 1 field for | 282 * BUG TODO: Is it not sufficient to have only 1 field for |
| 283 * this, since subsequently alias declarations will | 283 * this, since subsequently alias declarations will |
| 284 » * overwrite this.» | 284 » * overwrite this. |
| 285 * Example: | 285 * Example: |
| 286 * <xsl:namespace-alias result-prefix="foo" | 286 * <xsl:namespace-alias result-prefix="foo" |
| 287 * stylesheet-prefix="#default"/> | 287 * stylesheet-prefix="#default"/> |
| 288 * <xsl:namespace-alias result-prefix="bar" | 288 * <xsl:namespace-alias result-prefix="bar" |
| 289 * stylesheet-prefix="#default"/> | 289 * stylesheet-prefix="#default"/> |
| 290 * The mapping for "foo" won't be visible anymore. | 290 * The mapping for "foo" won't be visible anymore. |
| 291 */ | 291 */ |
| 292 style->defaultAlias = targetNs->href; | 292 style->defaultAlias = targetNs->href; |
| 293 } | 293 } |
| 294 } else { | 294 } else { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 * here (it was in the old code). | 351 * here (it was in the old code). |
| 352 * NOTE: @invocNode was named @cur in the old code and was documented to | 352 * NOTE: @invocNode was named @cur in the old code and was documented to |
| 353 * be an input node; since it was only used to anchor an error report | 353 * be an input node; since it was only used to anchor an error report |
| 354 * somewhere, we can safely change this to @invocNode, which now | 354 * somewhere, we can safely change this to @invocNode, which now |
| 355 * will be the XSLT instruction (also a literal result element/attribute), | 355 * will be the XSLT instruction (also a literal result element/attribute), |
| 356 * which was responsible for this call. | 356 * which was responsible for this call. |
| 357 */ | 357 */ |
| 358 /* | 358 /* |
| 359 * OPTIMIZE TODO: This all could be optimized by keeping track of | 359 * OPTIMIZE TODO: This all could be optimized by keeping track of |
| 360 * the ns-decls currently in-scope via a specialized context. | 360 * the ns-decls currently in-scope via a specialized context. |
| 361 */ | 361 */ |
| 362 if ((nsPrefix == NULL) && ((nsName == NULL) || (nsName[0] == 0))) { | 362 if ((nsPrefix == NULL) && ((nsName == NULL) || (nsName[0] == 0))) { |
| 363 /* | 363 /* |
| 364 * NOTE: the "undeclaration" of the default namespace was | 364 * NOTE: the "undeclaration" of the default namespace was |
| 365 * part of the logic of the old xsltGetSpecialNamespace() code, | 365 * part of the logic of the old xsltGetSpecialNamespace() code, |
| 366 * so we'll keep that mechanism. | 366 * so we'll keep that mechanism. |
| 367 * Related to the old code: bug #302020: | 367 * Related to the old code: bug #302020: |
| 368 */ | 368 */ |
| 369 /* | 369 /* |
| 370 * OPTIMIZE TODO: This all could be optimized by keeping track of | 370 * OPTIMIZE TODO: This all could be optimized by keeping track of |
| 371 * the ns-decls currently in-scope via a specialized context. | 371 * the ns-decls currently in-scope via a specialized context. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 391 /* | 391 /* |
| 392 * The default namespace was undeclared on the | 392 * The default namespace was undeclared on the |
| 393 * result element. | 393 * result element. |
| 394 */ | 394 */ |
| 395 return(NULL); | 395 return(NULL); |
| 396 } | 396 } |
| 397 break; | 397 break; |
| 398 } | 398 } |
| 399 ns = ns->next; | 399 ns = ns->next; |
| 400 } while (ns != NULL); | 400 } while (ns != NULL); |
| 401 » }» | 401 » } |
| 402 if ((target->parent != NULL) && | 402 if ((target->parent != NULL) && |
| 403 (target->parent->type == XML_ELEMENT_NODE)) | 403 (target->parent->type == XML_ELEMENT_NODE)) |
| 404 { | 404 { |
| 405 /* | 405 /* |
| 406 * The parent element is in no namespace, so assume | 406 * The parent element is in no namespace, so assume |
| 407 * that there is no default namespace in scope. | 407 * that there is no default namespace in scope. |
| 408 */ | 408 */ |
| 409 if (target->parent->ns == NULL) | 409 if (target->parent->ns == NULL) |
| 410 return(NULL); | 410 return(NULL); |
| 411 » | 411 |
| 412 ns = xmlSearchNs(target->doc, target->parent, | 412 ns = xmlSearchNs(target->doc, target->parent, |
| 413 NULL); | 413 NULL); |
| 414 /* | 414 /* |
| 415 * Fine if there's no default ns is scope, or if the | 415 * Fine if there's no default ns is scope, or if the |
| 416 * default ns was undeclared. | 416 * default ns was undeclared. |
| 417 */ | 417 */ |
| 418 if ((ns == NULL) || (ns->href == NULL) || (ns->href[0] == 0)) | 418 if ((ns == NULL) || (ns->href == NULL) || (ns->href[0] == 0)) |
| 419 return(NULL); | 419 return(NULL); |
| 420 » | 420 |
| 421 /* | 421 /* |
| 422 * Undeclare the default namespace. | 422 * Undeclare the default namespace. |
| 423 */ | 423 */ |
| 424 xmlNewNs(target, BAD_CAST "", NULL); | 424 xmlNewNs(target, BAD_CAST "", NULL); |
| 425 » /* TODO: Check result */» | 425 » /* TODO: Check result */ |
| 426 return(NULL); | 426 return(NULL); |
| 427 } | 427 } |
| 428 return(NULL); | 428 return(NULL); |
| 429 } | 429 } |
| 430 /* | 430 /* |
| 431 * Handle the XML namespace. | 431 * Handle the XML namespace. |
| 432 * QUESTION: Is this faster than using xmlStrEqual() anyway? | 432 * QUESTION: Is this faster than using xmlStrEqual() anyway? |
| 433 */ | 433 */ |
| 434 if ((nsPrefix != NULL) && | 434 if ((nsPrefix != NULL) && |
| 435 (nsPrefix[0] == 'x') && (nsPrefix[1] == 'm') && | 435 (nsPrefix[0] == 'x') && (nsPrefix[1] == 'm') && |
| (...skipping 21 matching lines...) Expand all Loading... |
| 457 } | 457 } |
| 458 } | 458 } |
| 459 ns = ns->next; | 459 ns = ns->next; |
| 460 } while (ns != NULL); | 460 } while (ns != NULL); |
| 461 } | 461 } |
| 462 if (prefixOccupied) { | 462 if (prefixOccupied) { |
| 463 /* | 463 /* |
| 464 * If the ns-prefix is occupied by an other ns-decl on the | 464 * If the ns-prefix is occupied by an other ns-decl on the |
| 465 * result element, then this means: | 465 * result element, then this means: |
| 466 * 1) The desired prefix is shadowed | 466 * 1) The desired prefix is shadowed |
| 467 » * 2) There's no way around changing the prefix» | 467 » * 2) There's no way around changing the prefix |
| 468 * | 468 * |
| 469 * Try a desperate search for an in-scope ns-decl | 469 * Try a desperate search for an in-scope ns-decl |
| 470 * with a matching ns-name before we use the last option, | 470 * with a matching ns-name before we use the last option, |
| 471 * which is to recreate the ns-decl with a modified prefix. | 471 * which is to recreate the ns-decl with a modified prefix. |
| 472 */ | 472 */ |
| 473 ns = xmlSearchNsByHref(target->doc, target, nsName); | 473 ns = xmlSearchNsByHref(target->doc, target, nsName); |
| 474 if (ns != NULL) | 474 if (ns != NULL) |
| 475 return(ns); | 475 return(ns); |
| 476 | 476 |
| 477 /* | 477 /* |
| 478 * Fallback to changing the prefix. | 478 * Fallback to changing the prefix. |
| 479 » */ | 479 » */ |
| 480 } else if ((target->parent != NULL) && | 480 } else if ((target->parent != NULL) && |
| 481 (target->parent->type == XML_ELEMENT_NODE)) | 481 (target->parent->type == XML_ELEMENT_NODE)) |
| 482 { | 482 { |
| 483 /* | 483 /* |
| 484 * Try to find a matching ns-decl in the ancestor-axis. | 484 * Try to find a matching ns-decl in the ancestor-axis. |
| 485 * | 485 * |
| 486 * Check the common case: The parent element of the current | 486 * Check the common case: The parent element of the current |
| 487 * result element is in the same namespace (with an equal ns-prefix). | 487 * result element is in the same namespace (with an equal ns-prefix). |
| 488 » */ | 488 » */ |
| 489 if ((target->parent->ns != NULL) && | 489 if ((target->parent->ns != NULL) && |
| 490 ((target->parent->ns->prefix != NULL) == (nsPrefix != NULL))) | 490 ((target->parent->ns->prefix != NULL) == (nsPrefix != NULL))) |
| 491 { | 491 { |
| 492 ns = target->parent->ns; | 492 ns = target->parent->ns; |
| 493 » | 493 |
| 494 if (nsPrefix == NULL) { | 494 if (nsPrefix == NULL) { |
| 495 if (xmlStrEqual(ns->href, nsName)) | 495 if (xmlStrEqual(ns->href, nsName)) |
| 496 return(ns); | 496 return(ns); |
| 497 } else if (xmlStrEqual(ns->prefix, nsPrefix) && | 497 } else if (xmlStrEqual(ns->prefix, nsPrefix) && |
| 498 xmlStrEqual(ns->href, nsName)) | 498 xmlStrEqual(ns->href, nsName)) |
| 499 { | 499 { |
| 500 return(ns); | 500 return(ns); |
| 501 } | 501 } |
| 502 } | 502 } |
| 503 /* | 503 /* |
| 504 * Lookup the remaining in-scope namespaces. | 504 * Lookup the remaining in-scope namespaces. |
| 505 » */ | 505 » */ |
| 506 ns = xmlSearchNs(target->doc, target->parent, nsPrefix); | 506 ns = xmlSearchNs(target->doc, target->parent, nsPrefix); |
| 507 if (ns != NULL) { | 507 if (ns != NULL) { |
| 508 if (xmlStrEqual(ns->href, nsName)) | 508 if (xmlStrEqual(ns->href, nsName)) |
| 509 » » return(ns);» | 509 » » return(ns); |
| 510 /* | 510 /* |
| 511 * Now check for a nasty case: We need to ensure that the new | 511 * Now check for a nasty case: We need to ensure that the new |
| 512 * ns-decl won't shadow a prefix in-use by an existing attribute. | 512 * ns-decl won't shadow a prefix in-use by an existing attribute. |
| 513 * <foo xmlns:a="urn:test:a"> | 513 * <foo xmlns:a="urn:test:a"> |
| 514 * <bar a:a="val-a"> | 514 * <bar a:a="val-a"> |
| 515 * <xsl:attribute xmlns:a="urn:test:b" name="a:b"> | 515 * <xsl:attribute xmlns:a="urn:test:b" name="a:b"> |
| 516 * val-b</xsl:attribute> | 516 * val-b</xsl:attribute> |
| 517 * </bar> | 517 * </bar> |
| 518 * </foo> | 518 * </foo> |
| 519 */ | 519 */ |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 578 declare_new_prefix: | 578 declare_new_prefix: |
| 579 /* | 579 /* |
| 580 * Fallback: we need to generate a new prefix and declare the namespace | 580 * Fallback: we need to generate a new prefix and declare the namespace |
| 581 * on the result element. | 581 * on the result element. |
| 582 */ | 582 */ |
| 583 { | 583 { |
| 584 xmlChar pref[30]; | 584 xmlChar pref[30]; |
| 585 int counter = 1; | 585 int counter = 1; |
| 586 | 586 |
| 587 if (nsPrefix == NULL) { | 587 if (nsPrefix == NULL) { |
| 588 » nsPrefix = "ns"; | 588 » nsPrefix = BAD_CAST "ns"; |
| 589 } | 589 } |
| 590 | 590 |
| 591 do { | 591 do { |
| 592 snprintf((char *) pref, 30, "%s_%d", nsPrefix, counter++); | 592 snprintf((char *) pref, 30, "%s_%d", nsPrefix, counter++); |
| 593 ns = xmlSearchNs(target->doc, target, BAD_CAST pref); | 593 ns = xmlSearchNs(target->doc, target, BAD_CAST pref); |
| 594 if (counter > 1000) { | 594 if (counter > 1000) { |
| 595 xsltTransformError(ctxt, NULL, invocNode, | 595 xsltTransformError(ctxt, NULL, invocNode, |
| 596 "Internal error in xsltAcquireResultInScopeNs(): " | 596 "Internal error in xsltAcquireResultInScopeNs(): " |
| 597 "Failed to compute a unique ns-prefix for the " | 597 "Failed to compute a unique ns-prefix for the " |
| 598 "generated element"); | 598 "generated element"); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 626 * - xsltCopyTreeInternal() (*not* anymore) | 626 * - xsltCopyTreeInternal() (*not* anymore) |
| 627 * - xsltApplySequenceConstructor() (*not* in the refactored code), | 627 * - xsltApplySequenceConstructor() (*not* in the refactored code), |
| 628 * - xsltElement() (*not* anymore) | 628 * - xsltElement() (*not* anymore) |
| 629 * | 629 * |
| 630 * Returns a namespace declaration or NULL in case of | 630 * Returns a namespace declaration or NULL in case of |
| 631 * namespace fixup failures or API or internal errors. | 631 * namespace fixup failures or API or internal errors. |
| 632 */ | 632 */ |
| 633 xmlNsPtr | 633 xmlNsPtr |
| 634 xsltGetNamespace(xsltTransformContextPtr ctxt, xmlNodePtr cur, xmlNsPtr ns, | 634 xsltGetNamespace(xsltTransformContextPtr ctxt, xmlNodePtr cur, xmlNsPtr ns, |
| 635 xmlNodePtr out) | 635 xmlNodePtr out) |
| 636 { | 636 { |
| 637 | 637 |
| 638 if (ns == NULL) | 638 if (ns == NULL) |
| 639 return(NULL); | 639 return(NULL); |
| 640 | 640 |
| 641 #ifdef XSLT_REFACTORED | 641 #ifdef XSLT_REFACTORED |
| 642 /* | 642 /* |
| 643 * Namespace exclusion and ns-aliasing is performed at | 643 * Namespace exclusion and ns-aliasing is performed at |
| 644 * compilation-time in the refactored code. | 644 * compilation-time in the refactored code. |
| 645 * Additionally, aliasing is not intended for non Literal | 645 * Additionally, aliasing is not intended for non Literal |
| 646 * Result Elements. | 646 * Result Elements. |
| 647 */ | 647 */ |
| 648 return(xsltGetSpecialNamespace(ctxt, cur, ns->href, ns->prefix, out)); | 648 return(xsltGetSpecialNamespace(ctxt, cur, ns->href, ns->prefix, out)); |
| 649 #else | 649 #else |
| 650 { | 650 { |
| 651 xsltStylesheetPtr style; | 651 xsltStylesheetPtr style; |
| 652 const xmlChar *URI = NULL; /* the replacement URI */ | 652 const xmlChar *URI = NULL; /* the replacement URI */ |
| 653 | 653 |
| 654 if ((ctxt == NULL) || (cur == NULL) || (out == NULL)) | 654 if ((ctxt == NULL) || (cur == NULL) || (out == NULL)) |
| 655 return(NULL); | 655 return(NULL); |
| 656 | 656 |
| 657 style = ctxt->style; | 657 style = ctxt->style; |
| 658 while (style != NULL) { | 658 while (style != NULL) { |
| 659 if (style->nsAliases != NULL) | 659 if (style->nsAliases != NULL) |
| 660 » » URI = (const xmlChar *) | 660 » » URI = (const xmlChar *) |
| 661 xmlHashLookup(style->nsAliases, ns->href); | 661 xmlHashLookup(style->nsAliases, ns->href); |
| 662 if (URI != NULL) | 662 if (URI != NULL) |
| 663 break; | 663 break; |
| 664 » | 664 |
| 665 style = xsltNextImport(style); | 665 style = xsltNextImport(style); |
| 666 } | 666 } |
| 667 » | 667 |
| 668 » | 668 |
| 669 if (URI == UNDEFINED_DEFAULT_NS) { | 669 if (URI == UNDEFINED_DEFAULT_NS) { |
| 670 return(xsltGetSpecialNamespace(ctxt, cur, NULL, NULL, out)); | 670 return(xsltGetSpecialNamespace(ctxt, cur, NULL, NULL, out)); |
| 671 #if 0 | 671 #if 0 |
| 672 /* | 672 /* |
| 673 * TODO: Removed, since wrong. If there was no default | 673 * TODO: Removed, since wrong. If there was no default |
| 674 * namespace in the stylesheet then this must resolve to | 674 * namespace in the stylesheet then this must resolve to |
| 675 * the NULL namespace. | 675 * the NULL namespace. |
| 676 */ | 676 */ |
| 677 » xmlNsPtr dflt;» | 677 » xmlNsPtr dflt; |
| 678 dflt = xmlSearchNs(cur->doc, cur, NULL); | 678 dflt = xmlSearchNs(cur->doc, cur, NULL); |
| 679 if (dflt != NULL) | 679 if (dflt != NULL) |
| 680 URI = dflt->href; | 680 URI = dflt->href; |
| 681 else | 681 else |
| 682 return NULL; | 682 return NULL; |
| 683 #endif | 683 #endif |
| 684 } else if (URI == NULL) | 684 } else if (URI == NULL) |
| 685 URI = ns->href; | 685 URI = ns->href; |
| 686 | 686 |
| 687 return(xsltGetSpecialNamespace(ctxt, cur, URI, ns->prefix, out)); | 687 return(xsltGetSpecialNamespace(ctxt, cur, URI, ns->prefix, out)); |
| 688 } | 688 } |
| 689 #endif | 689 #endif |
| 690 } | 690 } |
| 691 | 691 |
| 692 /** | 692 /** |
| 693 * xsltGetPlainNamespace: | 693 * xsltGetPlainNamespace: |
| 694 * @ctxt: a transformation context | 694 * @ctxt: a transformation context |
| 695 * @cur: the input node | 695 * @cur: the input node |
| 696 * @ns: the namespace | 696 * @ns: the namespace |
| 697 * @out: the result element | 697 * @out: the result element |
| 698 * | 698 * |
| 699 * Obsolete. | 699 * Obsolete. |
| 700 * *Not* called by any Libxslt/Libexslt function. | 700 * *Not* called by any Libxslt/Libexslt function. |
| 701 * Exaclty the same as xsltGetNamespace(). | 701 * Exaclty the same as xsltGetNamespace(). |
| 702 * | 702 * |
| 703 * Returns a namespace declaration or NULL in case of | 703 * Returns a namespace declaration or NULL in case of |
| 704 * namespace fixup failures or API or internal errors. | 704 * namespace fixup failures or API or internal errors. |
| 705 */ | 705 */ |
| 706 xmlNsPtr | 706 xmlNsPtr |
| 707 xsltGetPlainNamespace(xsltTransformContextPtr ctxt, xmlNodePtr cur, | 707 xsltGetPlainNamespace(xsltTransformContextPtr ctxt, xmlNodePtr cur, |
| 708 xmlNsPtr ns, xmlNodePtr out) | 708 xmlNsPtr ns, xmlNodePtr out) |
| 709 { | 709 { |
| 710 return(xsltGetNamespace(ctxt, cur, ns, out)); | 710 return(xsltGetNamespace(ctxt, cur, ns, out)); |
| 711 } | 711 } |
| 712 | 712 |
| 713 /** | 713 /** |
| 714 * xsltCopyNamespaceList: | 714 * xsltCopyNamespaceList: |
| 715 * @ctxt: a transformation context | 715 * @ctxt: a transformation context |
| 716 * @node: the target node | 716 * @node: the target node |
| 717 * @cur: the first namespace | 717 * @cur: the first namespace |
| 718 * | 718 * |
| 719 * Do a copy of an namespace list. If @node is non-NULL the | 719 * Do a copy of an namespace list. If @node is non-NULL the |
| 720 * new namespaces are added automatically. This handles namespaces | 720 * new namespaces are added automatically. This handles namespaces |
| 721 * aliases. | 721 * aliases. |
| 722 * This function is intended only for *internal* use at | 722 * This function is intended only for *internal* use at |
| 723 * transformation-time for copying ns-declarations of Literal | 723 * transformation-time for copying ns-declarations of Literal |
| 724 * Result Elements. | 724 * Result Elements. |
| 725 * | 725 * |
| 726 * Called by: | 726 * Called by: |
| 727 * xsltCopyTreeInternal() (transform.c) | 727 * xsltCopyTreeInternal() (transform.c) |
| 728 * xsltShallowCopyElem() (transform.c) | 728 * xsltShallowCopyElem() (transform.c) |
| 729 * | 729 * |
| 730 * REVISIT: This function won't be used in the refactored code. | 730 * REVISIT: This function won't be used in the refactored code. |
| 731 * | 731 * |
| 732 * Returns: a new xmlNsPtr, or NULL in case of error. | 732 * Returns: a new xmlNsPtr, or NULL in case of error. |
| 733 */ | 733 */ |
| 734 xmlNsPtr | 734 xmlNsPtr |
| 735 xsltCopyNamespaceList(xsltTransformContextPtr ctxt, xmlNodePtr node, | 735 xsltCopyNamespaceList(xsltTransformContextPtr ctxt, xmlNodePtr node, |
| 736 xmlNsPtr cur) { | 736 xmlNsPtr cur) { |
| 737 xmlNsPtr ret = NULL, tmp; | 737 xmlNsPtr ret = NULL, tmp; |
| 738 xmlNsPtr p = NULL,q; | 738 xmlNsPtr p = NULL,q; |
| 739 | 739 |
| 740 if (cur == NULL) | 740 if (cur == NULL) |
| 741 return(NULL); | 741 return(NULL); |
| 742 if (cur->type != XML_NAMESPACE_DECL) | 742 if (cur->type != XML_NAMESPACE_DECL) |
| 743 return(NULL); | 743 return(NULL); |
| 744 | 744 |
| 745 /* | 745 /* |
| 746 * One can add namespaces only on element nodes | 746 * One can add namespaces only on element nodes |
| 747 */ | 747 */ |
| 748 if ((node != NULL) && (node->type != XML_ELEMENT_NODE)) | 748 if ((node != NULL) && (node->type != XML_ELEMENT_NODE)) |
| 749 node = NULL; | 749 node = NULL; |
| 750 | 750 |
| 751 while (cur != NULL) { | 751 while (cur != NULL) { |
| 752 if (cur->type != XML_NAMESPACE_DECL) | 752 if (cur->type != XML_NAMESPACE_DECL) |
| 753 break; | 753 break; |
| 754 | 754 |
| 755 /* | 755 /* |
| 756 * Avoid duplicating namespace declarations in the tree if | 756 * Avoid duplicating namespace declarations in the tree if |
| 757 * a matching declaration is in scope. | 757 * a matching declaration is in scope. |
| 758 */ | 758 */ |
| 759 if (node != NULL) { | 759 if (node != NULL) { |
| 760 if ((node->ns != NULL) && | 760 if ((node->ns != NULL) && |
| 761 (xmlStrEqual(node->ns->prefix, cur->prefix)) && | 761 (xmlStrEqual(node->ns->prefix, cur->prefix)) && |
| 762 » (xmlStrEqual(node->ns->href, cur->href))) { | 762 » (xmlStrEqual(node->ns->href, cur->href))) { |
| 763 cur = cur->next; | 763 cur = cur->next; |
| 764 continue; | 764 continue; |
| 765 } | 765 } |
| 766 tmp = xmlSearchNs(node->doc, node, cur->prefix); | 766 tmp = xmlSearchNs(node->doc, node, cur->prefix); |
| 767 if ((tmp != NULL) && (xmlStrEqual(tmp->href, cur->href))) { | 767 if ((tmp != NULL) && (xmlStrEqual(tmp->href, cur->href))) { |
| 768 cur = cur->next; | 768 cur = cur->next; |
| 769 continue; | 769 continue; |
| 770 } | 770 } |
| 771 } | 771 } |
| 772 #ifdef XSLT_REFACTORED | 772 #ifdef XSLT_REFACTORED |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 817 * @ns: the namespace node | 817 * @ns: the namespace node |
| 818 * | 818 * |
| 819 * Copies a namespace node (declaration). If @elem is not NULL, | 819 * Copies a namespace node (declaration). If @elem is not NULL, |
| 820 * then the new namespace will be declared on @elem. | 820 * then the new namespace will be declared on @elem. |
| 821 * | 821 * |
| 822 * Returns: a new xmlNsPtr, or NULL in case of an error. | 822 * Returns: a new xmlNsPtr, or NULL in case of an error. |
| 823 */ | 823 */ |
| 824 xmlNsPtr | 824 xmlNsPtr |
| 825 xsltCopyNamespace(xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED, | 825 xsltCopyNamespace(xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED, |
| 826 xmlNodePtr elem, xmlNsPtr ns) | 826 xmlNodePtr elem, xmlNsPtr ns) |
| 827 { | 827 { |
| 828 if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL)) | 828 if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL)) |
| 829 return(NULL); | 829 return(NULL); |
| 830 /* | 830 /* |
| 831 * One can add namespaces only on element nodes | 831 * One can add namespaces only on element nodes |
| 832 */ | 832 */ |
| 833 if ((elem != NULL) && (elem->type != XML_ELEMENT_NODE)) | 833 if ((elem != NULL) && (elem->type != XML_ELEMENT_NODE)) |
| 834 return(xmlNewNs(NULL, ns->href, ns->prefix)); | 834 return(xmlNewNs(NULL, ns->href, ns->prefix)); |
| 835 else | 835 else |
| 836 return(xmlNewNs(elem, ns->href, ns->prefix)); | 836 return(xmlNewNs(elem, ns->href, ns->prefix)); |
| 837 } | 837 } |
| 838 | 838 |
| 839 | 839 |
| 840 /** | 840 /** |
| 841 * xsltFreeNamespaceAliasHashes: | 841 * xsltFreeNamespaceAliasHashes: |
| 842 * @style: an XSLT stylesheet | 842 * @style: an XSLT stylesheet |
| 843 * | 843 * |
| 844 * Free up the memory used by namespaces aliases | 844 * Free up the memory used by namespaces aliases |
| 845 */ | 845 */ |
| 846 void | 846 void |
| 847 xsltFreeNamespaceAliasHashes(xsltStylesheetPtr style) { | 847 xsltFreeNamespaceAliasHashes(xsltStylesheetPtr style) { |
| 848 if (style->nsAliases != NULL) | 848 if (style->nsAliases != NULL) |
| 849 xmlHashFree((xmlHashTablePtr) style->nsAliases, NULL); | 849 xmlHashFree((xmlHashTablePtr) style->nsAliases, NULL); |
| 850 style->nsAliases = NULL; | 850 style->nsAliases = NULL; |
| 851 } | 851 } |
| OLD | NEW |