15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * attrvt.c: Implementation of the XSL Transformation 1.0 engine 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * attribute value template handling part. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * References: 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * http://www.w3.org/TR/1999/REC-xslt-19991116 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Michael Kay "XSLT Programmer's Reference" pp 637-643 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Writing Multiple Output Files 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * See Copyright for the status of this software. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * daniel@veillard.com 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IN_LIBXSLT 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "libxslt.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/xmlmemory.h> 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/tree.h> 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/xpath.h> 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <libxml/xpathInternals.h> 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xslt.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xsltutils.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "xsltInternals.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "templates.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_XSLT_DEBUG 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define WITH_XSLT_DEBUG_AVT 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MAX_AVT_SEG 10 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct _xsltAttrVT xsltAttrVT; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef xsltAttrVT *xsltAttrVTPtr; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct _xsltAttrVT { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct _xsltAttrVT *next; /* next xsltAttrVT */ 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nb_seg; /* Number of segments */ 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_seg; /* max capacity before re-alloc needed */ 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int strstart; /* is the start a string */ 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the namespaces in scope 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xmlNsPtr *nsList; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nsNr; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the content is an alternate of string and xmlXPathCompExprPtr 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *segments[MAX_AVT_SEG]; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltNewAttrVT: 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @style: a XSLT process context 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Build a new xsltAttrVT structure 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the structure or NULL in case of error 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xsltAttrVTPtr 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltNewAttrVT(xsltStylesheetPtr style) { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xsltAttrVTPtr cur; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = (xsltAttrVTPtr) xmlMalloc(sizeof(xsltAttrVT)); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cur == NULL) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xsltTransformError(NULL, style, NULL, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "xsltNewAttrVTPtr : malloc failed\n"); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (style != NULL) style->errors++; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return(NULL); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(cur, 0, sizeof(xsltAttrVT)); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur->nb_seg = 0; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur->max_seg = MAX_AVT_SEG; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur->strstart = 0; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur->next = style->attVTs; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Note: this pointer may be changed by a re-alloc within xsltCompileAttr, 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * so that code may change the stylesheet pointer also! 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) style->attVTs = (xsltAttrVTPtr) cur; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return(cur); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltFreeAttrVT: 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @avt: pointer to an xsltAttrVT structure 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Free up the memory associated to the attribute value template 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltFreeAttrVT(xsltAttrVTPtr avt) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (avt == NULL) return; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (avt->strstart == 1) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0;i < avt->nb_seg; i += 2) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (avt->segments[i] != NULL) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xmlFree((xmlChar *) avt->segments[i]); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 1;i < avt->nb_seg; i += 2) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xmlXPathFreeCompExpr((xmlXPathCompExprPtr) avt->segments[i]); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0;i < avt->nb_seg; i += 2) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xmlXPathFreeCompExpr((xmlXPathCompExprPtr) avt->segments[i]); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 1;i < avt->nb_seg; i += 2) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (avt->segments[i] != NULL) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xmlFree((xmlChar *) avt->segments[i]); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (avt->nsList != NULL) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xmlFree(avt->nsList); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xmlFree(avt); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltFreeAVTList: 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @avt: pointer to an list of AVT structures 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Free up the memory associated to the attribute value templates 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltFreeAVTList(void *avt) { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xsltAttrVTPtr cur = (xsltAttrVTPtr) avt, next; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (cur != NULL) { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next = cur->next; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xsltFreeAttrVT(cur); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = next; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltSetAttrVTsegment: 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ avt: pointer to an xsltAttrVT structure 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ val: the value to be set to the next available segment 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Within xsltCompileAttr there are several places where a value 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * needs to be added to the 'segments' array within the xsltAttrVT 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * structure, and at each place the allocated size may have to be 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * re-allocated. This routine takes care of that situation. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the avt pointer, which may have been changed by a re-alloc 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static xsltAttrVTPtr 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltSetAttrVTsegment(xsltAttrVTPtr avt, void *val) { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (avt->nb_seg >= avt->max_seg) { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) avt = (xsltAttrVTPtr) xmlRealloc(avt, sizeof(xsltAttrVT) + 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) avt->max_seg * sizeof(void *)); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (avt == NULL) { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&avt->segments[avt->nb_seg], 0, MAX_AVT_SEG*sizeof(void *)); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) avt->max_seg += MAX_AVT_SEG; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) avt->segments[avt->nb_seg++] = val; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return avt; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltCompileAttr: 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @style: a XSLT process context 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @attr: the attribute coming from the stylesheet. 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Precompile an attribute in a stylesheet, basically it checks if it is 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * an attrubute value template, and if yes establish some structures needed 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to process it at transformation time. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltCompileAttr(xsltStylesheetPtr style, xmlAttrPtr attr) { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const xmlChar *str; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const xmlChar *cur; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xmlChar *ret = NULL; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xmlChar *expr = NULL; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xsltAttrVTPtr avt; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i = 0, lastavt = 0; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((style == NULL) || (attr == NULL) || (attr->children == NULL)) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((attr->children->type != XML_TEXT_NODE) || 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (attr->children->next != NULL)) { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xsltTransformError(NULL, style, attr->parent, 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Attribute '%s': The content is expected to be a single text " 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "node when compiling an AVT.\n", attr->name); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) style->errors++; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) str = attr->children->content; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((xmlStrchr(str, '{') == NULL) && 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (xmlStrchr(str, '}') == NULL)) return; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_XSLT_DEBUG_AVT 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xsltGenericDebug(xsltGenericDebugContext, 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Found AVT %s: %s\n", attr->name, str); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (attr->psvi != NULL) { 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WITH_XSLT_DEBUG_AVT 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xsltGenericDebug(xsltGenericDebugContext, 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "AVT %s: already compiled\n", attr->name); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Create a new AVT object. 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) avt = xsltNewAttrVT(style); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (avt == NULL) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attr->psvi = avt; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) avt->nsList = xmlGetNsList(attr->doc, attr->parent); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (avt->nsList != NULL) { 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (avt->nsList[i] != NULL) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i++; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) avt->nsNr = i; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur = str; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (*cur != 0) { 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*cur == '{') { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*(cur+1) == '{') { /* escaped '{' */ 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur++; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = xmlStrncat(ret, str, cur - str); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur++; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) str = cur; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*(cur+1) == '}') { /* skip empty AVT */ 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = xmlStrncat(ret, str, cur - str); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur += 2; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) str = cur; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((ret != NULL) || (cur - str > 0)) { 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = xmlStrncat(ret, str, cur - str); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) str = cur; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (avt->nb_seg == 0) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) avt->strstart = 1; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((avt = xsltSetAttrVTsegment(avt, (void *) ret)) == NULL) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto error; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = NULL; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lastavt = 0; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur++; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ((*cur != 0) && (*cur != '}')) { 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Need to check for literal (bug539741) */ 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((*cur == '\'') || (*cur == '"')) { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char delim = *(cur++); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ((*cur != 0) && (*cur != delim)) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur++; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*cur != 0) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur++; /* skip the ending delimiter */ 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur++; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*cur == 0) { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xsltTransformError(NULL, style, attr->parent, 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Attribute '%s': The AVT has an unmatched '{'.\n", 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attr->name); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) style->errors++; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto error; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) str++; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expr = xmlStrndup(str, cur - str); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (expr == NULL) { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * TODO: What needs to be done here? 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XSLT_TODO 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto error; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xmlXPathCompExprPtr comp; 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp = xsltXPathCompile(style, expr); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (comp == NULL) { 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xsltTransformError(NULL, style, attr->parent, 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Attribute '%s': Failed to compile the expression " 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "'%s' in the AVT.\n", attr->name, expr); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) style->errors++; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto error; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (avt->nb_seg == 0) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) avt->strstart = 0; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lastavt == 1) { 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((avt = xsltSetAttrVTsegment(avt, NULL)) == NULL) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto error; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((avt = xsltSetAttrVTsegment(avt, (void *) comp)) == NULL) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto error; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lastavt = 1; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xmlFree(expr); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expr = NULL; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur++; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) str = cur; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (*cur == '}') { 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur++; 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*cur == '}') { /* escaped '}' */ 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = xmlStrncat(ret, str, cur - str); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur++; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) str = cur; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xsltTransformError(NULL, style, attr->parent, 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Attribute '%s': The AVT has an unmatched '}'.\n", 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attr->name); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto error; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur++; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((ret != NULL) || (cur - str > 0)) { 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = xmlStrncat(ret, str, cur - str); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) str = cur; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (avt->nb_seg == 0) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) avt->strstart = 1; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((avt = xsltSetAttrVTsegment(avt, (void *) ret)) == NULL) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto error; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = NULL; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)error: 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (avt == NULL) { 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xsltTransformError(NULL, style, attr->parent, 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "xsltCompileAttr: malloc problem\n"); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (attr->psvi != avt) { /* may have changed from realloc */ 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) attr->psvi = avt; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This is a "hack", but I can't see any clean method of 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * doing it. If a re-alloc has taken place, then the pointer 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * for this AVT may have changed. style->attVTs was set by 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltNewAttrVT, so it needs to be re-set to the new value! 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) style->attVTs = avt; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret != NULL) 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xmlFree(ret); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (expr != NULL) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xmlFree(expr); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * xsltEvalAVT: 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @ctxt: the XSLT transformation context 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @avt: the prevompiled attribute value template info 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @node: the node hosting the attribute 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Process the given AVT, and return the new string value. 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns the computed string value or NULL, must be deallocated by the 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * caller. 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xmlChar * 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)xsltEvalAVT(xsltTransformContextPtr ctxt, void *avt, xmlNodePtr node) { 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xmlChar *ret = NULL, *tmp; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xmlXPathCompExprPtr comp; 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xsltAttrVTPtr cur = (xsltAttrVTPtr) avt; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int str; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((ctxt == NULL) || (avt == NULL) || (node == NULL)) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return(NULL); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) str = cur->strstart; 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0;i < cur->nb_seg;i++) { 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (str) { 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = xmlStrcat(ret, (const xmlChar *) cur->segments[i]); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp = (xmlXPathCompExprPtr) cur->segments[i]; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tmp = xsltEvalXPathStringNs(ctxt, comp, cur->nsNr, cur->nsList); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tmp != NULL) { 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret != NULL) { 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = xmlStrcat(ret, tmp); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xmlFree(tmp); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = tmp; 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) str = !str; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return(ret); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 388