ReactOS  0.4.13-dev-982-g9853eab
attributes.c
Go to the documentation of this file.
1 /*
2  * attributes.c: Implementation of the XSLT attributes handling
3  *
4  * Reference:
5  * http://www.w3.org/TR/1999/REC-xslt-19991116
6  *
7  * See Copyright for the status of this software.
8  *
9  * daniel@veillard.com
10  */
11 
12 #include "precomp.h"
13 
14 #define WITH_XSLT_DEBUG_ATTRIBUTES
15 #ifdef WITH_XSLT_DEBUG
16 #define WITH_XSLT_DEBUG_ATTRIBUTES
17 #endif
18 
19 /*
20  * Useful macros
21  */
22 #ifdef IS_BLANK
23 #undef IS_BLANK
24 #endif
25 
26 #define IS_BLANK(c) (((c) == 0x20) || ((c) == 0x09) || ((c) == 0xA) || \
27  ((c) == 0x0D))
28 
29 #define IS_BLANK_NODE(n) \
30  (((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content)))
31 
32 #define ATTRSET_UNRESOLVED 0
33 #define ATTRSET_RESOLVING 1
34 #define ATTRSET_RESOLVED 2
35 
36 
37 /*
38  * The in-memory structure corresponding to an XSLT Attribute in
39  * an attribute set
40  */
41 
42 
43 typedef struct _xsltAttrElem xsltAttrElem;
45 struct _xsltAttrElem {
46  struct _xsltAttrElem *next;/* chained list */
47  xmlNodePtr attr; /* the xsl:attribute definition */
48 };
49 
53  struct _xsltUseAttrSet *next; /* chained list */
54  const xmlChar *ncname;
55  const xmlChar *ns;
56 };
57 
58 typedef struct _xsltAttrSet xsltAttrSet;
60 struct _xsltAttrSet {
61  int state;
62  xsltAttrElemPtr attrs; /* list head */
63  xsltUseAttrSetPtr useAttrSets; /* list head */
64 };
65 
71 };
72 
73 static void
76  const xmlChar *ns, int depth);
77 
78 /************************************************************************
79  * *
80  * XSLT Attribute handling *
81  * *
82  ************************************************************************/
83 
92 static xsltAttrElemPtr
94  xsltAttrElemPtr cur;
95 
96  cur = (xsltAttrElemPtr) xmlMalloc(sizeof(xsltAttrElem));
97  if (cur == NULL) {
99  "xsltNewAttrElem : malloc failed\n");
100  return(NULL);
101  }
102  memset(cur, 0, sizeof(xsltAttrElem));
103  cur->attr = attr;
104  return(cur);
105 }
106 
113 static void
115  xmlFree(attr);
116 }
117 
124 static void
127 
128  while (list != NULL) {
129  next = list->next;
131  list = next;
132  }
133 }
134 
144 static xsltAttrElemPtr
146  xsltAttrElemPtr next, cur;
147 
148  if (attr == NULL)
149  return(list);
150  if (list == NULL)
151  return(xsltNewAttrElem(attr));
152  cur = list;
153  while (cur != NULL) {
154  next = cur->next;
155  if (next == NULL) {
156  cur->next = xsltNewAttrElem(attr);
157  return(list);
158  }
159  cur = next;
160  }
161  return(list);
162 }
163 
173 static xsltUseAttrSetPtr
174 xsltNewUseAttrSet(const xmlChar *ncname, const xmlChar *ns) {
175  xsltUseAttrSetPtr cur;
176 
177  cur = (xsltUseAttrSetPtr) xmlMalloc(sizeof(xsltUseAttrSet));
178  if (cur == NULL) {
180  "xsltNewUseAttrSet : malloc failed\n");
181  return(NULL);
182  }
183  memset(cur, 0, sizeof(xsltUseAttrSet));
184  cur->ncname = ncname;
185  cur->ns = ns;
186  return(cur);
187 }
188 
195 static void
197  xmlFree(use);
198 }
199 
206 static void
209 
210  while (list != NULL) {
211  next = list->next;
213  list = next;
214  }
215 }
216 
227 static xsltUseAttrSetPtr
229  const xmlChar *ns) {
230  xsltUseAttrSetPtr next, cur;
231 
232  if (ncname == NULL)
233  return(list);
234  if (list == NULL)
235  return(xsltNewUseAttrSet(ncname, ns));
236  cur = list;
237  while (cur != NULL) {
238  if ((cur->ncname == ncname) && (cur->ns == ns))
239  return(list);
240  next = cur->next;
241  if (next == NULL) {
242  cur->next = xsltNewUseAttrSet(ncname, ns);
243  return(list);
244  }
245  cur = next;
246  }
247  return(list);
248 }
249 
257 static xsltAttrSetPtr
259  xsltAttrSetPtr cur;
260 
261  cur = (xsltAttrSetPtr) xmlMalloc(sizeof(xsltAttrSet));
262  if (cur == NULL) {
264  "xsltNewAttrSet : malloc failed\n");
265  return(NULL);
266  }
267  memset(cur, 0, sizeof(xsltAttrSet));
268  return(cur);
269 }
270 
277 static void
279  if (set == NULL)
280  return;
281 
282  xsltFreeAttrElemList(set->attrs);
283  xsltFreeUseAttrSetList(set->useAttrSets);
284  xmlFree(set);
285 }
286 
295 static void
297  xsltAttrElemPtr cur;
298  xsltAttrElemPtr old = other->attrs;
299  int add;
300 
301  while (old != NULL) {
302  /*
303  * Check that the attribute is not yet in the list
304  */
305  cur = set->attrs;
306  add = 1;
307  while (cur != NULL) {
308  xsltStylePreCompPtr curComp = cur->attr->psvi;
309  xsltStylePreCompPtr oldComp = old->attr->psvi;
310 
311  if ((curComp->name == oldComp->name) &&
312  (curComp->ns == oldComp->ns)) {
313  add = 0;
314  break;
315  }
316  if (cur->next == NULL)
317  break;
318  cur = cur->next;
319  }
320 
321  if (add == 1) {
322  if (cur == NULL) {
323  set->attrs = xsltNewAttrElem(old->attr);
324  } else if (add) {
325  cur->next = xsltNewAttrElem(old->attr);
326  }
327  }
328 
329  old = old->next;
330  }
331 }
332 
333 /************************************************************************
334  * *
335  * Module interfaces *
336  * *
337  ************************************************************************/
338 
347 void
349  const xmlChar *ncname;
350  const xmlChar *prefix;
351  const xmlChar *nsUri = NULL;
352  xmlChar *value;
355 
356  if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
357  return;
358 
359  value = xmlGetNsProp(cur, (const xmlChar *)"name", NULL);
360  if ((value == NULL) || (*value == 0)) {
362  "xsl:attribute-set : name is missing\n");
363  if (value)
364  xmlFree(value);
365  return;
366  }
367 
368  if (xmlValidateQName(value, 0)) {
370  "xsl:attribute-set : The name '%s' is not a valid QName.\n",
371  value);
372  style->errors++;
373  xmlFree(value);
374  return;
375  }
376 
377  ncname = xsltSplitQName(style->dict, value, &prefix);
378  xmlFree(value);
379  value = NULL;
380  if (prefix != NULL) {
381  xmlNsPtr ns = xmlSearchNs(style->doc, cur, prefix);
382  if (ns == NULL) {
384  "xsl:attribute-set : No namespace found for QName '%s:%s'\n",
385  prefix, ncname);
386  style->errors++;
387  return;
388  }
389  nsUri = ns->href;
390  }
391 
392  if (style->attributeSets == NULL) {
393 #ifdef WITH_XSLT_DEBUG_ATTRIBUTES
395  "creating attribute set table\n");
396 #endif
397  style->attributeSets = xmlHashCreate(10);
398  }
399  if (style->attributeSets == NULL)
400  return;
401 
402  set = xmlHashLookup2(style->attributeSets, ncname, nsUri);
403  if (set == NULL) {
404  set = xsltNewAttrSet();
405  if (set == NULL)
406  return;
407  xmlHashAddEntry2(style->attributeSets, ncname, nsUri, set);
408  }
409 
410  /*
411  * Parse the content. Only xsl:attribute elements are allowed.
412  */
413  child = cur->children;
414  while (child != NULL) {
415  /*
416  * Report invalid nodes.
417  */
418  if ((child->type != XML_ELEMENT_NODE) ||
419  (child->ns == NULL) ||
420  (! IS_XSLT_ELEM(child)))
421  {
422  if (child->type == XML_ELEMENT_NODE)
424  "xsl:attribute-set : unexpected child %s\n",
425  child->name);
426  else
428  "xsl:attribute-set : child of unexpected type\n");
429  } else if (!IS_XSLT_NAME(child, "attribute")) {
431  "xsl:attribute-set : unexpected child xsl:%s\n",
432  child->name);
433  } else {
434 #ifdef WITH_XSLT_DEBUG_ATTRIBUTES
436  "add attribute to list %s\n", ncname);
437 #endif
439  if (child->children != NULL) {
440 #ifdef XSLT_REFACTORED
441  xsltParseSequenceConstructor(XSLT_CCTXT(style),
442  child->children);
443 #else
445 #endif
446  }
447  if (child->psvi == NULL) {
449  "xsl:attribute-set : internal error, attribute %s not "
450  "compiled\n", child->name);
451  }
452  else {
453  set->attrs = xsltAddAttrElemList(set->attrs, child);
454  }
455  }
456 
457  child = child->next;
458  }
459 
460  /*
461  * Process attribute "use-attribute-sets".
462  */
463  value = xmlGetNsProp(cur, BAD_CAST "use-attribute-sets", NULL);
464  if (value != NULL) {
465  const xmlChar *curval, *endval;
466  curval = value;
467  while (*curval != 0) {
468  while (IS_BLANK(*curval)) curval++;
469  if (*curval == 0)
470  break;
471  endval = curval;
472  while ((*endval != 0) && (!IS_BLANK(*endval))) endval++;
473  curval = xmlDictLookup(style->dict, curval, endval - curval);
474  if (curval) {
475  const xmlChar *ncname2 = NULL;
476  const xmlChar *prefix2 = NULL;
477  const xmlChar *nsUri2 = NULL;
478 
479 #ifdef WITH_XSLT_DEBUG_ATTRIBUTES
481  "xsl:attribute-set : %s adds use %s\n", ncname, curval);
482 #endif
483 
484  if (xmlValidateQName(curval, 0)) {
486  "xsl:attribute-set : The name '%s' in "
487  "use-attribute-sets is not a valid QName.\n", curval);
488  style->errors++;
489  xmlFree(value);
490  return;
491  }
492 
493  ncname2 = xsltSplitQName(style->dict, curval, &prefix2);
494  if (prefix2 != NULL) {
495  xmlNsPtr ns2 = xmlSearchNs(style->doc, cur, prefix2);
496  if (ns2 == NULL) {
498  "xsl:attribute-set : No namespace found for QName "
499  "'%s:%s' in use-attribute-sets\n",
500  prefix2, ncname2);
501  style->errors++;
502  xmlFree(value);
503  return;
504  }
505  nsUri2 = ns2->href;
506  }
507  set->useAttrSets = xsltAddUseAttrSetList(set->useAttrSets,
508  ncname2, nsUri2);
509  }
510  curval = endval;
511  }
512  xmlFree(value);
513  value = NULL;
514  }
515 
516 #ifdef WITH_XSLT_DEBUG_ATTRIBUTES
518  "updated attribute list %s\n", ncname);
519 #endif
520 }
521 
530 static void
532  int depth) {
533  xsltStylesheetPtr cur;
535  xsltUseAttrSetPtr use = set->useAttrSets;
537 
538  while (use != NULL) {
539  /*
540  * Iterate top stylesheet and all imports.
541  */
542  cur = topStyle;
543  while (cur != NULL) {
544  if (cur->attributeSets) {
546  use->ns);
547  if (other != NULL) {
548  xsltResolveAttrSet(other, topStyle, cur, use->ncname,
549  use->ns, depth + 1);
551  break;
552  }
553  }
554  cur = xsltNextImport(cur);
555  }
556 
557  next = use->next;
558  /* Free useAttrSets early. */
559  xsltFreeUseAttrSet(use);
560  use = next;
561  }
562 
563  set->useAttrSets = NULL;
564 }
565 
576 static void
579  const xmlChar *ns, int depth) {
580  xsltStylesheetPtr cur;
582 
583  if (set->state == ATTRSET_RESOLVED)
584  return;
585  if (set->state == ATTRSET_RESOLVING) {
586  xsltTransformError(NULL, topStyle, NULL,
587  "xsl:attribute-set : use-attribute-sets recursion detected"
588  " on %s\n", name);
589  topStyle->errors++;
590  set->state = ATTRSET_RESOLVED;
591  return;
592  }
593  if (depth > 100) {
594  xsltTransformError(NULL, topStyle, NULL,
595  "xsl:attribute-set : use-attribute-sets maximum recursion "
596  "depth exceeded on %s\n", name);
597  topStyle->errors++;
598  return;
599  }
600 
601  set->state = ATTRSET_RESOLVING;
602 
603  xsltResolveUseAttrSets(set, topStyle, depth);
604 
605  /* Merge imported sets. */
606  cur = xsltNextImport(style);
607  while (cur != NULL) {
608  if (cur->attributeSets != NULL) {
610 
611  if (other != NULL) {
612 #ifdef WITH_XSLT_DEBUG_ATTRIBUTES
614  "xsl:attribute-set : merging import for %s\n", name);
615 #endif
616  xsltResolveUseAttrSets(other, topStyle, depth);
620  }
621  }
622 
623  cur = xsltNextImport(cur);
624  }
625 
626  set->state = ATTRSET_RESOLVED;
627 }
628 
638 static void
639 xsltResolveSASCallback(void *payload, void *data,
640  const xmlChar *name, const xmlChar *ns,
642  xsltAttrSetPtr set = (xsltAttrSetPtr) payload;
644  xsltStylesheetPtr topStyle = asctx->topStyle;
645  xsltStylesheetPtr style = asctx->style;
646 
647  xsltResolveAttrSet(set, topStyle, style, name, ns, 1);
648 
649  /* Move attribute sets to top stylesheet. */
650  if (style != topStyle) {
651  /*
652  * This imported stylesheet won't be visited anymore. Don't bother
653  * removing the hash entry.
654  */
655  if (xmlHashAddEntry2(topStyle->attributeSets, name, ns, set) < 0) {
657  "xsl:attribute-set : internal error, can't move imported "
658  " attribute set %s\n", name);
659  }
660  }
661 }
662 
669 void
671  xsltStylesheetPtr cur;
672  xsltAttrSetContext asctx;
673 
674 #ifdef WITH_XSLT_DEBUG_ATTRIBUTES
676  "Resolving attribute sets references\n");
677 #endif
678  asctx.topStyle = style;
679  cur = style;
680  while (cur != NULL) {
681  if (cur->attributeSets != NULL) {
682  if (style->attributeSets == NULL) {
683 #ifdef WITH_XSLT_DEBUG_ATTRIBUTES
685  "creating attribute set table\n");
686 #endif
687  style->attributeSets = xmlHashCreate(10);
688  }
689  asctx.style = cur;
691  &asctx);
692 
693  if (cur != style) {
694  /*
695  * the attribute lists have either been migrated to style
696  * or freed directly in xsltResolveSASCallback()
697  */
699  cur->attributeSets = NULL;
700  }
701  }
702  cur = xsltNextImport(cur);
703  }
704 }
705 
715 void
717  xmlNodePtr contextNode,
718  xmlNodePtr inst,
719  xsltElemPreCompPtr castedComp)
720 {
721 #ifdef XSLT_REFACTORED
722  xsltStyleItemAttributePtr comp =
723  (xsltStyleItemAttributePtr) castedComp;
724 #else
725  xsltStylePreCompPtr comp = (xsltStylePreCompPtr) castedComp;
726 #endif
727  xmlNodePtr targetElem;
728  xmlChar *prop = NULL;
729  const xmlChar *name = NULL, *prefix = NULL, *nsName = NULL;
730  xmlChar *value = NULL;
731  xmlNsPtr ns = NULL;
733 
734  if ((ctxt == NULL) || (contextNode == NULL) || (inst == NULL) ||
735  (inst->type != XML_ELEMENT_NODE) )
736  return;
737 
738  /*
739  * A comp->has_name == 0 indicates that we need to skip this instruction,
740  * since it was evaluated to be invalid already during compilation.
741  */
742  if (!comp->has_name)
743  return;
744  /*
745  * BIG NOTE: This previously used xsltGetSpecialNamespace() and
746  * xsltGetNamespace(), but since both are not appropriate, we
747  * will process namespace lookup here to avoid adding yet another
748  * ns-lookup function to namespaces.c.
749  */
750  /*
751  * SPEC XSLT 1.0: Error cases:
752  * - Creating nodes other than text nodes during the instantiation of
753  * the content of the xsl:attribute element; implementations may
754  * either signal the error or ignore the offending nodes."
755  */
756 
757  if (comp == NULL) {
758  xsltTransformError(ctxt, NULL, inst,
759  "Internal error in xsltAttribute(): "
760  "The XSLT 'attribute' instruction was not compiled.\n");
761  return;
762  }
763  /*
764  * TODO: Shouldn't ctxt->insert == NULL be treated as an internal error?
765  * So report an internal error?
766  */
767  if (ctxt->insert == NULL)
768  return;
769  /*
770  * SPEC XSLT 1.0:
771  * "Adding an attribute to a node that is not an element;
772  * implementations may either signal the error or ignore the attribute."
773  *
774  * TODO: I think we should signal such errors in the future, and maybe
775  * provide an option to ignore such errors.
776  */
777  targetElem = ctxt->insert;
778  if (targetElem->type != XML_ELEMENT_NODE)
779  return;
780 
781  /*
782  * SPEC XSLT 1.0:
783  * "Adding an attribute to an element after children have been added
784  * to it; implementations may either signal the error or ignore the
785  * attribute."
786  *
787  * TODO: We should decide whether not to report such errors or
788  * to ignore them; note that we *ignore* if the parent is not an
789  * element, but here we report an error.
790  */
791  if (targetElem->children != NULL) {
792  /*
793  * NOTE: Ah! This seems to be intended to support streamed
794  * result generation!.
795  */
796  xsltTransformError(ctxt, NULL, inst,
797  "xsl:attribute: Cannot add attributes to an "
798  "element if children have been already added "
799  "to the element.\n");
800  return;
801  }
802 
803  /*
804  * Process the name
805  * ----------------
806  */
807 
808 #ifdef WITH_DEBUGGER
809  if (ctxt->debugStatus != XSLT_DEBUG_NONE)
810  xslHandleDebugger(inst, contextNode, NULL, ctxt);
811 #endif
812 
813  if (comp->name == NULL) {
814  /* TODO: fix attr acquisition wrt to the XSLT namespace */
815  prop = xsltEvalAttrValueTemplate(ctxt, inst,
816  (const xmlChar *) "name", XSLT_NAMESPACE);
817  if (prop == NULL) {
818  xsltTransformError(ctxt, NULL, inst,
819  "xsl:attribute: The attribute 'name' is missing.\n");
820  goto error;
821  }
822  if (xmlValidateQName(prop, 0)) {
823  xsltTransformError(ctxt, NULL, inst,
824  "xsl:attribute: The effective name '%s' is not a "
825  "valid QName.\n", prop);
826  /* we fall through to catch any further errors, if possible */
827  }
828 
829  /*
830  * Reject a name of "xmlns".
831  */
832  if (xmlStrEqual(prop, BAD_CAST "xmlns")) {
833  xsltTransformError(ctxt, NULL, inst,
834  "xsl:attribute: The effective name 'xmlns' is not allowed.\n");
835  xmlFree(prop);
836  goto error;
837  }
838 
839  name = xsltSplitQName(ctxt->dict, prop, &prefix);
840  xmlFree(prop);
841  } else {
842  /*
843  * The "name" value was static.
844  */
845 #ifdef XSLT_REFACTORED
846  prefix = comp->nsPrefix;
847  name = comp->name;
848 #else
849  name = xsltSplitQName(ctxt->dict, comp->name, &prefix);
850 #endif
851  }
852 
853  /*
854  * Process namespace semantics
855  * ---------------------------
856  *
857  * Evaluate the namespace name.
858  */
859  if (comp->has_ns) {
860  /*
861  * The "namespace" attribute was existent.
862  */
863  if (comp->ns != NULL) {
864  /*
865  * No AVT; just plain text for the namespace name.
866  */
867  if (comp->ns[0] != 0)
868  nsName = comp->ns;
869  } else {
870  xmlChar *tmpNsName;
871  /*
872  * Eval the AVT.
873  */
874  /* TODO: check attr acquisition wrt to the XSLT namespace */
875  tmpNsName = xsltEvalAttrValueTemplate(ctxt, inst,
876  (const xmlChar *) "namespace", XSLT_NAMESPACE);
877  /*
878  * This fixes bug #302020: The AVT might also evaluate to the
879  * empty string; this means that the empty string also indicates
880  * "no namespace".
881  * SPEC XSLT 1.0:
882  * "If the string is empty, then the expanded-name of the
883  * attribute has a null namespace URI."
884  */
885  if ((tmpNsName != NULL) && (tmpNsName[0] != 0))
886  nsName = xmlDictLookup(ctxt->dict, BAD_CAST tmpNsName, -1);
887  xmlFree(tmpNsName);
888  }
889 
890  if (xmlStrEqual(nsName, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
891  xsltTransformError(ctxt, NULL, inst,
892  "xsl:attribute: Namespace http://www.w3.org/2000/xmlns/ "
893  "forbidden.\n");
894  goto error;
895  }
896  if (xmlStrEqual(nsName, XML_XML_NAMESPACE)) {
897  prefix = BAD_CAST "xml";
898  } else if (xmlStrEqual(prefix, BAD_CAST "xml")) {
899  prefix = NULL;
900  }
901  } else if (prefix != NULL) {
902  /*
903  * SPEC XSLT 1.0:
904  * "If the namespace attribute is not present, then the QName is
905  * expanded into an expanded-name using the namespace declarations
906  * in effect for the xsl:attribute element, *not* including any
907  * default namespace declaration."
908  */
909  ns = xmlSearchNs(inst->doc, inst, prefix);
910  if (ns == NULL) {
911  /*
912  * Note that this is treated as an error now (checked with
913  * Saxon, Xalan-J and MSXML).
914  */
915  xsltTransformError(ctxt, NULL, inst,
916  "xsl:attribute: The QName '%s:%s' has no "
917  "namespace binding in scope in the stylesheet; "
918  "this is an error, since the namespace was not "
919  "specified by the instruction itself.\n", prefix, name);
920  } else
921  nsName = ns->href;
922  }
923 
924  /*
925  * Find/create a matching ns-decl in the result tree.
926  */
927  ns = NULL;
928 
929 #if 0
930  if (0) {
931  /*
932  * OPTIMIZE TODO: How do we know if we are adding to a
933  * fragment or to the result tree?
934  *
935  * If we are adding to a result tree fragment (i.e., not to the
936  * actual result tree), we'll don't bother searching for the
937  * ns-decl, but just store it in the dummy-doc of the result
938  * tree fragment.
939  */
940  if (nsName != NULL) {
941  /*
942  * TODO: Get the doc of @targetElem.
943  */
944  ns = xsltTreeAcquireStoredNs(some doc, nsName, prefix);
945  }
946  }
947 #endif
948 
949  if (nsName != NULL) {
950  /*
951  * Something about ns-prefixes:
952  * SPEC XSLT 1.0:
953  * "XSLT processors may make use of the prefix of the QName specified
954  * in the name attribute when selecting the prefix used for outputting
955  * the created attribute as XML; however, they are not required to do
956  * so and, if the prefix is xmlns, they must not do so"
957  */
958  /*
959  * xsl:attribute can produce a scenario where the prefix is NULL,
960  * so generate a prefix.
961  */
962  if ((prefix == NULL) || xmlStrEqual(prefix, BAD_CAST "xmlns")) {
963  xmlChar *pref = xmlStrdup(BAD_CAST "ns_1");
964 
965  ns = xsltGetSpecialNamespace(ctxt, inst, nsName, pref, targetElem);
966 
967  xmlFree(pref);
968  } else {
969  ns = xsltGetSpecialNamespace(ctxt, inst, nsName, prefix,
970  targetElem);
971  }
972  if (ns == NULL) {
973  xsltTransformError(ctxt, NULL, inst,
974  "Namespace fixup error: Failed to acquire an in-scope "
975  "namespace binding for the generated attribute '{%s}%s'.\n",
976  nsName, name);
977  goto error;
978  }
979  }
980  /*
981  * Construction of the value
982  * -------------------------
983  */
984  if (inst->children == NULL) {
985  /*
986  * No content.
987  * TODO: Do we need to put the empty string in ?
988  */
989  attr = xmlSetNsProp(ctxt->insert, ns, name, (const xmlChar *) "");
990  } else if ((inst->children->next == NULL) &&
991  ((inst->children->type == XML_TEXT_NODE) ||
992  (inst->children->type == XML_CDATA_SECTION_NODE)))
993  {
994  xmlNodePtr copyTxt;
995 
996  /*
997  * xmlSetNsProp() will take care of duplicates.
998  */
999  attr = xmlSetNsProp(ctxt->insert, ns, name, NULL);
1000  if (attr == NULL) /* TODO: report error ? */
1001  goto error;
1002  /*
1003  * This was taken over from xsltCopyText() (transform.c).
1004  */
1005  if (ctxt->internalized &&
1006  (ctxt->insert->doc != NULL) &&
1007  (ctxt->insert->doc->dict == ctxt->dict))
1008  {
1009  copyTxt = xmlNewText(NULL);
1010  if (copyTxt == NULL) /* TODO: report error */
1011  goto error;
1012  /*
1013  * This is a safe scenario where we don't need to lookup
1014  * the dict.
1015  */
1016  copyTxt->content = inst->children->content;
1017  /*
1018  * Copy "disable-output-escaping" information.
1019  * TODO: Does this have any effect for attribute values
1020  * anyway?
1021  */
1022  if (inst->children->name == xmlStringTextNoenc)
1023  copyTxt->name = xmlStringTextNoenc;
1024  } else {
1025  /*
1026  * Copy the value.
1027  */
1028  copyTxt = xmlNewText(inst->children->content);
1029  if (copyTxt == NULL) /* TODO: report error */
1030  goto error;
1031  }
1032  attr->children = attr->last = copyTxt;
1033  copyTxt->parent = (xmlNodePtr) attr;
1034  copyTxt->doc = attr->doc;
1035  /*
1036  * Copy "disable-output-escaping" information.
1037  * TODO: Does this have any effect for attribute values
1038  * anyway?
1039  */
1040  if (inst->children->name == xmlStringTextNoenc)
1041  copyTxt->name = xmlStringTextNoenc;
1042 
1043  /*
1044  * since we create the attribute without content IDness must be
1045  * asserted as a second step
1046  */
1047  if ((copyTxt->content != NULL) &&
1048  (xmlIsID(attr->doc, attr->parent, attr)))
1049  xmlAddID(NULL, attr->doc, copyTxt->content, attr);
1050  } else {
1051  /*
1052  * The sequence constructor might be complex, so instantiate it.
1053  */
1054  value = xsltEvalTemplateString(ctxt, contextNode, inst);
1055  if (value != NULL) {
1056  attr = xmlSetNsProp(ctxt->insert, ns, name, value);
1057  xmlFree(value);
1058  } else {
1059  /*
1060  * TODO: Do we have to add the empty string to the attr?
1061  * TODO: Does a value of NULL indicate an
1062  * error in xsltEvalTemplateString() ?
1063  */
1064  attr = xmlSetNsProp(ctxt->insert, ns, name,
1065  (const xmlChar *) "");
1066  }
1067  }
1068 
1069 error:
1070  return;
1071 }
1072 
1085 void
1087  xmlNodePtr inst,
1088  const xmlChar *attrSets)
1089 {
1090  const xmlChar *ncname = NULL;
1091  const xmlChar *prefix = NULL;
1092  const xmlChar *curstr, *endstr;
1095 
1096  if (attrSets == NULL) {
1097  if (inst == NULL)
1098  return;
1099  else {
1100  /*
1101  * Extract the value from @inst.
1102  */
1103  if (inst->type == XML_ATTRIBUTE_NODE) {
1104  if ( ((xmlAttrPtr) inst)->children != NULL)
1105  attrSets = ((xmlAttrPtr) inst)->children->content;
1106 
1107  }
1108  if (attrSets == NULL) {
1109  /*
1110  * TODO: Return an error?
1111  */
1112  return;
1113  }
1114  }
1115  }
1116  /*
1117  * Parse/apply the list of QNames.
1118  */
1119  curstr = attrSets;
1120  while (*curstr != 0) {
1121  while (IS_BLANK(*curstr))
1122  curstr++;
1123  if (*curstr == 0)
1124  break;
1125  endstr = curstr;
1126  while ((*endstr != 0) && (!IS_BLANK(*endstr)))
1127  endstr++;
1128  curstr = xmlDictLookup(ctxt->dict, curstr, endstr - curstr);
1129  if (curstr) {
1130  xmlNsPtr ns;
1131  const xmlChar *nsUri = NULL;
1132 
1133 #ifdef WITH_XSLT_DEBUG_ATTRIBUTES
1135  "apply attribute set %s\n", curstr);
1136 #endif
1137 
1138  if (xmlValidateQName(curstr, 0)) {
1139  xsltTransformError(ctxt, NULL, inst,
1140  "The name '%s' in use-attribute-sets is not a valid "
1141  "QName.\n", curstr);
1142  return;
1143  }
1144 
1145  ncname = xsltSplitQName(ctxt->dict, curstr, &prefix);
1146  if (prefix != NULL) {
1147  ns = xmlSearchNs(inst->doc, inst, prefix);
1148  if (ns == NULL) {
1149  xsltTransformError(ctxt, NULL, inst,
1150  "use-attribute-set : No namespace found for QName "
1151  "'%s:%s'\n", prefix, ncname);
1152  return;
1153  }
1154  nsUri = ns->href;
1155  }
1156 
1157  style = ctxt->style;
1158 
1159 #ifdef WITH_DEBUGGER
1160  if ((style != NULL) &&
1161  (style->attributeSets != NULL) &&
1162  (ctxt->debugStatus != XSLT_DEBUG_NONE))
1163  {
1164  set = xmlHashLookup2(style->attributeSets, ncname, nsUri);
1165  if ((set != NULL) && (set->attrs != NULL) &&
1166  (set->attrs->attr != NULL))
1167  xslHandleDebugger(set->attrs->attr->parent, node, NULL,
1168  ctxt);
1169  }
1170 #endif
1171  /*
1172  * Lookup the referenced attribute-set. All attribute sets were
1173  * moved to the top stylesheet so there's no need to iterate
1174  * imported stylesheets
1175  */
1176  set = xmlHashLookup2(style->attributeSets, ncname, nsUri);
1177  if (set != NULL) {
1178  xsltAttrElemPtr cur = set->attrs;
1179  while (cur != NULL) {
1180  if (cur->attr != NULL) {
1181  xsltAttribute(ctxt, node, cur->attr,
1182  cur->attr->psvi);
1183  }
1184  cur = cur->next;
1185  }
1186  }
1187  }
1188  curstr = endstr;
1189  }
1190 }
1191 
1192 static void
1194  const xmlChar *name ATTRIBUTE_UNUSED) {
1195  xsltFreeAttrSet((xsltAttrSetPtr) payload);
1196 }
1197 
1204 void
1206  if (style->attributeSets != NULL)
1207  xmlHashFree((xmlHashTablePtr) style->attributeSets,
1209  style->attributeSets = NULL;
1210 }
int add
Definition: i386-dis.c:3122
void * psvi
Definition: tree.h:505
struct _xsltAttrElem * next
Definition: attributes.c:46
static void xsltFreeAttrSet(xsltAttrSetPtr set)
Definition: attributes.c:278
void xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr contextNode, xmlNodePtr inst, xsltElemPreCompPtr castedComp)
Definition: attributes.c:716
xsltAttrElem * xsltAttrElemPtr
Definition: attributes.c:44
static void xsltResolveUseAttrSets(xsltAttrSetPtr set, xsltStylesheetPtr topStyle, int depth)
Definition: attributes.c:531
#define error(str)
Definition: mkdosfs.c:1605
static xsltAttrSetPtr xsltNewAttrSet()
Definition: attributes.c:258
const xmlChar * name
Definition: tree.h:492
Definition: tree.h:389
xsltStylesheetPtr xsltNextImport(xsltStylesheetPtr cur)
Definition: imports.c:250
XMLPUBFUN int XMLCALL xmlHashAddEntry2(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, void *userdata)
Definition: hash.c:404
int other
Definition: msacm.c:1364
const xmlChar * ns
static void xsltFreeUseAttrSetList(xsltUseAttrSetPtr list)
Definition: attributes.c:207
static xsltUseAttrSetPtr xsltNewUseAttrSet(const xmlChar *ncname, const xmlChar *ns)
Definition: attributes.c:174
static xsltAttrElemPtr xsltNewAttrElem(xmlNodePtr attr)
Definition: attributes.c:93
static xsltUseAttrSetPtr xsltAddUseAttrSetList(xsltUseAttrSetPtr list, const xmlChar *ncname, const xmlChar *ns)
Definition: attributes.c:228
static void xsltResolveSASCallback(void *payload, void *data, const xmlChar *name, const xmlChar *ns, ATTRIBUTE_UNUSED const xmlChar *ignored)
Definition: attributes.c:639
xmlNsPtr xsltGetSpecialNamespace(xsltTransformContextPtr ctxt, xmlNodePtr invocNode, const xmlChar *nsName, const xmlChar *nsPrefix, xmlNodePtr target)
Definition: namespaces.c:299
#define XSLT_NAMESPACE
Definition: xslt.h:46
XMLPUBFUN void *XMLCALL xmlHashLookup2(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2)
Definition: hash.c:474
#define IS_XSLT_ELEM(n)
Definition: xsltutils.h:54
static HWND child
Definition: cursoricon.c:298
xsltAttrSetContext * xsltAttrSetContextPtr
Definition: attributes.c:67
const xmlChar * ncname
Definition: attributes.c:54
xmlChar * xsltEvalAttrValueTemplate(xsltTransformContextPtr ctxt, xmlNodePtr inst, const xmlChar *name, const xmlChar *ns)
Definition: templates.c:384
struct _xmlDoc * doc
Definition: tree.h:498
xsltStylesheetPtr topStyle
Definition: attributes.c:69
XMLPUBFUN void XMLCALL xmlHashFree(xmlHashTablePtr table, xmlHashDeallocator f)
Definition: hash.c:320
xmlGenericErrorFunc xsltGenericError
Definition: xsltutils.c:502
XMLPUBFUN xmlNsPtr XMLCALL xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace)
static void xsltResolveAttrSet(xsltAttrSetPtr set, xsltStylesheetPtr topStyle, xsltStylesheetPtr style, const xmlChar *name, const xmlChar *ns, int depth)
Definition: attributes.c:577
smooth NULL
Definition: ftsmooth.c:416
xsltUseAttrSetPtr useAttrSets
Definition: attributes.c:63
#define XML_XML_NAMESPACE
Definition: tree.h:140
xsltUseAttrSet * xsltUseAttrSetPtr
Definition: attributes.c:51
xmlNode * xmlNodePtr
Definition: tree.h:488
#define BAD_CAST
Definition: xmlstring.h:35
void xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst)
Definition: preproc.c:2175
struct _xmlNode * parent
Definition: tree.h:495
const xmlChar * ns
Definition: attributes.c:55
void * xsltGenericDebugContext
Definition: xsltutils.c:549
static xsltAttrElemPtr xsltAddAttrElemList(xsltAttrElemPtr list, xmlNodePtr attr)
Definition: attributes.c:145
const xmlChar * xsltSplitQName(xmlDictPtr dict, const xmlChar *name, const xmlChar **prefix)
Definition: xsltutils.c:720
XMLPUBFUN int XMLCALL xmlHashRemoveEntry2(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, xmlHashDeallocator f)
Definition: hash.c:1069
static UINT set(struct ID3DXConstantTableImpl *table, IDirect3DDevice9 *device, struct ctab_constant *constant, const void **indata, D3DXPARAMETER_TYPE intype, UINT *size, UINT incol, D3DXPARAMETER_CLASS inclass, UINT index, BOOL is_pointer)
Definition: shader.c:1095
struct list * next
Definition: list.h:38
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:250
XMLPUBFUN xmlChar *XMLCALL xmlGetNsProp(const xmlNode *node, const xmlChar *name, const xmlChar *nameSpace)
XMLPUBFUN const xmlChar *XMLCALL xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len)
Definition: dict.c:858
Definition: cookie.c:170
xmlGenericErrorFunc xsltGenericDebug
Definition: xsltutils.c:548
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
xmlChar * content
Definition: tree.h:502
XMLPUBFUN xmlHashTablePtr XMLCALL xmlHashCreate(int size)
Definition: hash.c:174
void * xsltGenericErrorContext
Definition: xsltutils.c:503
Definition: tree.h:489
void xsltApplyAttributeSet(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, const xmlChar *attrSets)
Definition: attributes.c:1086
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
xmlAttr * xmlAttrPtr
Definition: tree.h:433
void xsltFreeAttributeSetsHashes(xsltStylesheetPtr style)
Definition: attributes.c:1205
XMLPUBFUN void XMLCALL xmlHashScanFull(xmlHashTablePtr table, xmlHashScannerFull f, void *data)
Definition: hash.c:873
#define ATTRIBUTE_UNUSED
Definition: win32config.h:132
XMLPUBFUN int XMLCALL xmlIsID(xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr)
Definition: valid.c:2704
__u8 attr
Definition: mkdosfs.c:359
xsltAttrElemPtr attrs
Definition: attributes.c:62
Definition: mxnamespace.c:44
unsigned char xmlChar
Definition: xmlstring.h:28
Definition: _list.h:228
XMLPUBFUN xmlIDPtr XMLCALL xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, xmlAttrPtr attr)
Definition: valid.c:2602
#define IS_BLANK(c)
Definition: attributes.c:26
static void xsltFreeAttrElem(xsltAttrElemPtr attr)
Definition: attributes.c:114
GLsizei const GLfloat * value
Definition: glext.h:6069
xmlElementType type
Definition: tree.h:491
xsltAttrSet * xsltAttrSetPtr
Definition: attributes.c:59
void xslHandleDebugger(xmlNodePtr cur, xmlNodePtr node, xsltTemplatePtr templ, xsltTransformContextPtr ctxt)
Definition: xsltutils.c:2422
xsltStylePreComp * xsltStylePreCompPtr
static void xsltFreeUseAttrSet(xsltUseAttrSetPtr use)
Definition: attributes.c:196
XMLPUBFUN xmlNodePtr XMLCALL xmlNewText(const xmlChar *content)
xsltStylesheetPtr style
static unsigned __int64 next
Definition: rand_nt.c:6
#define ATTRSET_RESOLVING
Definition: attributes.c:33
struct _xsltUseAttrSet * next
Definition: attributes.c:53
static void xsltFreeAttributeSetsEntry(void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
Definition: attributes.c:1193
#define list
Definition: rosglue.h:35
XMLPUBVAR const xmlChar xmlStringTextNoenc[]
XMLPUBVAR xmlMallocFunc xmlMalloc
Definition: globals.h:247
uint8_t ignored[3]
Definition: fsck.fat.h:35
const xmlChar * name
void xsltResolveStylesheetAttributeSet(xsltStylesheetPtr style)
Definition: attributes.c:670
xmlHashTablePtr attributeSets
struct _xmlNode * children
Definition: tree.h:493
Definition: tree.h:434
xmlChar * xsltEvalTemplateString(xsltTransformContextPtr ctxt, xmlNodePtr contextNode, xmlNodePtr inst)
Definition: templates.c:189
Definition: name.c:36
#define ATTRSET_RESOLVED
Definition: attributes.c:34
xmlNodePtr attr
Definition: attributes.c:47
static void xsltFreeAttrElemList(xsltAttrElemPtr list)
Definition: attributes.c:125
XMLPUBFUN int XMLCALL xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:157
static void xsltMergeAttrSets(xsltAttrSetPtr set, xsltAttrSetPtr other)
Definition: attributes.c:296
void xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *msg,...)
Definition: xsltutils.c:678
void xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ)
Definition: xslt.c:4863
Arabic default style
Definition: afstyles.h:93
Definition: _set.h:46
const xmlChar * href
Definition: tree.h:392
#define memset(x, y, z)
Definition: compat.h:39
#define IS_XSLT_NAME(n, val)
Definition: xsltutils.h:63
xsltStylesheetPtr style
Definition: attributes.c:70
XMLPUBFUN xmlChar *XMLCALL xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:66
void xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur)
Definition: attributes.c:348
Definition: dlist.c:348