*** origin/testXPath.c Fri Oct 13 11:01:52 2000 --- devel/testXPath.c Wed Oct 25 22:09:00 2000 *************** int main(int argc, char **argv) { *** 181,186 **** --- 181,189 ---- printf("\tParse the XPath strings and output the result of the parsing\n"); printf("\t--debug : dump a debug version of the result\n"); printf("\t--valid : switch on DTD support in the parser\n"); + #if defined(LIBXML_XPTR_ENABLED) + printf("\t--xptr : expressions are XPointer expressions\n"); + #endif printf("\t--expr : debug XPath expressions only\n"); printf("\t--input filename : or\n"); printf("\t-i filename : read the document from filename\n"); *** origin/xpath.c Wed Oct 25 15:11:25 2000 --- devel/xpath.c Thu Oct 26 00:20:39 2000 *************** double xmlXPathStringEvalNumber(const xm *** 71,77 **** */ double xmlXPathNAN = 0; double xmlXPathPINF = 1; ! double xmlXPathNINF = -1; #ifndef isinf #ifndef HAVE_ISINF --- 71,77 ---- */ double xmlXPathNAN = 0; double xmlXPathPINF = 1; ! double xmlXPathMINF = -1; #ifndef isinf #ifndef HAVE_ISINF *************** xmlXPathInit(void) { *** 161,168 **** xmlXPathPINF = 1; xmlXPathPINF /= 0; ! xmlXPathNINF = -1; ! xmlXPathNINF /= 0; initialized = 1; } --- 161,168 ---- xmlXPathPINF = 1; xmlXPathPINF /= 0; ! xmlXPathMINF = -1; ! xmlXPathMINF /= 0; initialized = 1; } *************** xmlXPathIdFunction(xmlXPathParserContext *** 2675,2681 **** obj = valuePop(ctxt); if (obj == NULL) XP_ERROR(XPATH_INVALID_OPERAND); if (obj->type == XPATH_NODESET) { ! TODO /* ID function in case of NodeSet */ } if (obj->type != XPATH_STRING) { valuePush(ctxt, obj); --- 2675,2699 ---- obj = valuePop(ctxt); if (obj == NULL) XP_ERROR(XPATH_INVALID_OPERAND); if (obj->type == XPATH_NODESET) { ! xmlXPathObjectPtr newobj; ! int i; ! ! ret = xmlXPathNewNodeSet(NULL); ! ! for (i = 0; i < obj->nodesetval->nodeNr; i++) { ! valuePush(ctxt, ! xmlXPathNewNodeSet(obj->nodesetval->nodeTab[i])); ! xmlXPathStringFunction(ctxt, 1); ! xmlXPathIdFunction(ctxt, 1); ! newobj = valuePop(ctxt); ! ret->nodesetval = xmlXPathNodeSetMerge(ret->nodesetval, ! newobj->nodesetval); ! xmlXPathFreeObject(newobj); ! } ! ! xmlXPathFreeObject(obj); ! valuePush(ctxt, ret); ! return; } if (obj->type != XPATH_STRING) { valuePush(ctxt, obj); *************** xmlXPathIdFunction(xmlXPathParserContext *** 2725,2744 **** } /** ! * xmlXPathLocalPartFunction: * @ctxt: the XPath Parser context * ! * Implement the local-part() XPath function ! * The local-part function returns a string containing the local part * of the name of the node in the argument node-set that is first in * document order. If the node-set is empty or the first node has no * name, an empty string is returned. If the argument is omitted it * defaults to the context node. */ void ! xmlXPathLocalPartFunction(xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathObjectPtr cur; CHECK_ARITY(1); CHECK_TYPE(XPATH_NODESET); cur = valuePop(ctxt); --- 2743,2767 ---- } /** ! * xmlXPathLocalNameFunction: * @ctxt: the XPath Parser context * ! * Implement the local-name() XPath function ! * The local-name function returns a string containing the local part * of the name of the node in the argument node-set that is first in * document order. If the node-set is empty or the first node has no * name, an empty string is returned. If the argument is omitted it * defaults to the context node. */ void ! xmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathObjectPtr cur; + if (nargs == 0) { + valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node)); + nargs = 1; + } + CHECK_ARITY(1); CHECK_TYPE(XPATH_NODESET); cur = valuePop(ctxt); *************** xmlXPathLocalPartFunction(xmlXPathParser *** 2753,2770 **** } /** ! * xmlXPathNamespaceFunction: * @ctxt: the XPath Parser context * ! * Implement the namespace() XPath function ! * The namespace function returns a string containing the namespace URI ! * of the expanded name of the node in the argument node-set that is ! * first in document order. If the node-set is empty, the first node has ! * no name, or the expanded name has no namespace URI, an empty string ! * is returned. If the argument is omitted it defaults to the context node. */ void ! xmlXPathNamespaceFunction(xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathObjectPtr cur; if (nargs == 0) { --- 2776,2794 ---- } /** ! * xmlXPathNamespaceURIFunction: * @ctxt: the XPath Parser context * ! * Implement the namespace-uri() XPath function ! * The namespace-uri function returns a string containing the ! * namespace URI of the expanded name of the node in the argument ! * node-set that is first in document order. If the node-set is empty, ! * the first node has no name, or the expanded name has no namespace ! * URI, an empty string is returned. If the argument is omitted it ! * defaults to the context node. */ void ! xmlXPathNamespaceURIFunction(xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathObjectPtr cur; if (nargs == 0) { *************** void *** 2813,2818 **** --- 2837,2847 ---- xmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathObjectPtr cur; + if (nargs == 0) { + valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node)); + nargs = 1; + } + CHECK_ARITY(1); CHECK_TYPE(XPATH_NODESET); cur = valuePop(ctxt); *************** xmlXPathNameFunction(xmlXPathParserConte *** 2874,2884 **** --- 2903,2921 ---- * number from all other IEEE 754 numeric values. * - The boolean false value is converted to the string false. * The boolean true value is converted to the string true. + * + * If the argument is omitted, it defaults to a node-set with the + * context node as its only member. */ void xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathObjectPtr cur; + if (nargs == 0) { + valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node)); + nargs = 1; + } + CHECK_ARITY(1); cur = valuePop(ctxt); if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND); *************** xmlXPathNormalizeFunction(xmlXPathParser *** 3256,3272 **** xmlBufferPtr target; xmlChar blank; ! if (nargs < 1) { /* Use current context node */ ! CHECK_ARITY(0); ! TODO /* source = xmlNodeGetContent(ctxt->context->node); */ ! } else if (nargs >= 1) { ! /* Use argument */ ! CHECK_ARITY(1); ! obj = valuePop(ctxt); ! if (obj == NULL) XP_ERROR(XPATH_INVALID_OPERAND); ! source = obj->stringval; } target = xmlBufferCreate(); if (target && source) { --- 3293,3310 ---- xmlBufferPtr target; xmlChar blank; ! if (nargs == 0) { /* Use current context node */ ! valuePush(ctxt, xmlXPathNewNodeSet(ctxt->context->node)); ! xmlXPathStringFunction(ctxt, 1); ! nargs = 1; } + + CHECK_ARITY(1); + CHECK_TYPE(XPATH_STRING); + obj = valuePop(ctxt); + source = obj->stringval; + target = xmlBufferCreate(); if (target && source) { *************** xmlXPathNormalizeFunction(xmlXPathParser *** 3292,3299 **** valuePush(ctxt, xmlXPathNewString(xmlBufferContent(target))); xmlBufferFree(target); } ! if (obj) ! xmlXPathFreeObject(obj); } /** --- 3330,3336 ---- valuePush(ctxt, xmlXPathNewString(xmlBufferContent(target))); xmlBufferFree(target); } ! xmlXPathFreeObject(obj); } /** *************** not_equal: *** 3484,3495 **** --- 3521,3548 ---- * @ctxt: the XPath Parser context * * Implement the number() XPath function + * + * BUG: since we directly call xmlXPathStringEvalNumber(), + * number("-1") isn't evaluated in -1.0 but in NaN. */ void xmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathObjectPtr cur; double res; + if (nargs == 0) { + if (ctxt->context->node == NULL) { + valuePush(ctxt, xmlXPathNewFloat(0.0)); + } else { + xmlChar* content = xmlNodeGetContent(ctxt->content->node); + + res = xmlXPathStringEvalNumber(content); + valuePush(ctxt, xmlXPathNewFloat(res)); + xmlFree(content); + } + return; + } + CHECK_ARITY(1); cur = valuePop(ctxt); switch (cur->type) { *************** xmlXPathNumberFunction(xmlXPathParserCon *** 3537,3544 **** */ void xmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs) { CHECK_ARITY(1); ! TODO /* BUG Sum : don't understand the definition */ } /** --- 3590,3614 ---- */ void xmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathObjectPtr cur; + int i; + CHECK_ARITY(1); ! CHECK_TYPE(XPATH_NODESET); ! cur = valuePop(ctxt); ! ! if (cur->nodesetval->nodeNr = 0) { ! valuePush(ctxt, xmlXPathNewFloat(0.0)); ! } else { ! valuePush(ctxt, ! xmlXPathNewNodeSet(cur->nodesetval->nodeTab[0])); ! for (i = 1; i < cur->nodesetval->nodeNr; i++) { ! valuePush(ctxt, ! xmlXPathNewNodeSet(cur->nodesetval->nodeTab[i])); ! xmlXPathAddValues(ctxt); ! } ! } ! xmlXPathFreeObject(cur); } /** *************** void *** 3553,3560 **** --- 3623,3634 ---- xmlXPathFloorFunction(xmlXPathParserContextPtr ctxt, int nargs) { CHECK_ARITY(1); CHECK_TYPE(XPATH_NUMBER); + #ifdef HAVE_MATH_H + ctxt->value->floatval = floor(ctxt->value->floatval); + #else /* floor(0.999999999999) => 1.0 !!!!!!!!!!! */ ctxt->value->floatval = (double)((int) ctxt->value->floatval); + #endif } /** *************** xmlXPathFloorFunction(xmlXPathParserCont *** 3567,3579 **** --- 3641,3660 ---- */ void xmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt, int nargs) { + #ifndef HAVE_MATH_H double f; + #endif CHECK_ARITY(1); CHECK_TYPE(XPATH_NUMBER); + + #ifdef HAVE_MATH_H + ctxt->value->floatval = ceil(ctxt->value->floatval); + #else f = (double)((int) ctxt->value->floatval); if (f != ctxt->value->floatval) ctxt->value->floatval = f + 1; + #endif } /** *************** xmlXPathRoundFunction(xmlXPathParserCont *** 3591,3602 **** CHECK_ARITY(1); CHECK_TYPE(XPATH_NUMBER); ! /* round(0.50000001) => 0 !!!!! */ f = (double)((int) ctxt->value->floatval); if (ctxt->value->floatval < f + 0.5) ctxt->value->floatval = f; - else if (ctxt->value->floatval == f + 0.5) - ctxt->value->floatval = f; /* !!!! Not following the spec here */ else ctxt->value->floatval = f + 1; } --- 3672,3691 ---- CHECK_ARITY(1); CHECK_TYPE(XPATH_NUMBER); ! ! if ((ctxt->value->floatval == xmlXPathNAN) || ! (ctxt->value->floatval == xmlXPathPINF) || ! (ctxt->value->floatval == xmlXPathNINF) || ! (ctxt->value->floatval == 0.0)) ! return; ! ! #ifdef HAVE_MATH_H ! f = floor(ctxt->value->floatval); ! #else f = (double)((int) ctxt->value->floatval); + #endif if (ctxt->value->floatval < f + 0.5) ctxt->value->floatval = f; else ctxt->value->floatval = f + 1; } *************** xmlXPathParseName(xmlXPathParserContextP *** 3720,3734 **** * xmlXPathStringEvalNumber: * @str: A string to scan * ! * [30] Number ::= Digits ('.' Digits)? * | '.' Digits * [31] Digits ::= [0-9]+ * * Parse and evaluate a Number in the string * - * BUG: "1.' is not valid ... James promised correction - * as Digits ('.' Digits?)? - * * Returns the double value. */ double --- 3809,3820 ---- * xmlXPathStringEvalNumber: * @str: A string to scan * ! * [30] Number ::= Digits ('.' Digits?)? * | '.' Digits * [31] Digits ::= [0-9]+ * * Parse and evaluate a Number in the string * * Returns the double value. */ double *************** xmlXPathStringEvalNumber(const xmlChar * *** 3767,3780 **** * xmlXPathEvalNumber: * @ctxt: the XPath Parser context * ! * [30] Number ::= Digits ('.' Digits)? * | '.' Digits * [31] Digits ::= [0-9]+ * * Parse and evaluate a Number, then push it on the stack * - * BUG: "1.' is not valid ... James promised correction - * as Digits ('.' Digits?)? */ void xmlXPathEvalNumber(xmlXPathParserContextPtr ctxt) { --- 3853,3864 ---- * xmlXPathEvalNumber: * @ctxt: the XPath Parser context * ! * [30] Number ::= Digits ('.' Digits?)? * | '.' Digits * [31] Digits ::= [0-9]+ * * Parse and evaluate a Number, then push it on the stack * */ void xmlXPathEvalNumber(xmlXPathParserContextPtr ctxt) { *************** xmlXPathRegisterAllFunctions(xmlXPathCon *** 5250,5263 **** xmlXPathLastFunction); xmlXPathRegisterFunc(ctxt, (const xmlChar *)"lang", xmlXPathLangFunction); ! xmlXPathRegisterFunc(ctxt, (const xmlChar *)"local-part", ! xmlXPathLocalPartFunction); xmlXPathRegisterFunc(ctxt, (const xmlChar *)"not", xmlXPathNotFunction); xmlXPathRegisterFunc(ctxt, (const xmlChar *)"name", xmlXPathNameFunction); ! xmlXPathRegisterFunc(ctxt, (const xmlChar *)"namespace", ! xmlXPathNamespaceFunction); xmlXPathRegisterFunc(ctxt, (const xmlChar *)"normalize-space", xmlXPathNormalizeFunction); xmlXPathRegisterFunc(ctxt, (const xmlChar *)"normalize", --- 5334,5347 ---- xmlXPathLastFunction); xmlXPathRegisterFunc(ctxt, (const xmlChar *)"lang", xmlXPathLangFunction); ! xmlXPathRegisterFunc(ctxt, (const xmlChar *)"local-name", ! xmlXPathLocalNameFunction); xmlXPathRegisterFunc(ctxt, (const xmlChar *)"not", xmlXPathNotFunction); xmlXPathRegisterFunc(ctxt, (const xmlChar *)"name", xmlXPathNameFunction); ! xmlXPathRegisterFunc(ctxt, (const xmlChar *)"namespace-uri", ! xmlXPathNamespaceURIFunction); xmlXPathRegisterFunc(ctxt, (const xmlChar *)"normalize-space", xmlXPathNormalizeFunction); xmlXPathRegisterFunc(ctxt, (const xmlChar *)"normalize", diff -p origin/include/libxml/xpathInternals.h devel/include/libxml/xpathInternals.h *** origin/include/libxml/xpathInternals.h Wed Oct 25 15:10:59 2000 --- devel/include/libxml/xpathInternals.h Thu Oct 26 00:24:29 2000 *************** void xmlXPathLastFunction(xmlXPathParser *** 148,155 **** void xmlXPathPositionFunction(xmlXPathParserContextPtr ctxt, int nargs); void xmlXPathCountFunction(xmlXPathParserContextPtr ctxt, int nargs); void xmlXPathIdFunction(xmlXPathParserContextPtr ctxt, int nargs); ! void xmlXPathLocalPartFunction(xmlXPathParserContextPtr ctxt, int nargs); ! void xmlXPathNamespaceFunction(xmlXPathParserContextPtr ctxt, int nargs); void xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs); void xmlXPathStringLengthFunction(xmlXPathParserContextPtr ctxt, int nargs); void xmlXPathConcatFunction(xmlXPathParserContextPtr ctxt, int nargs); --- 148,155 ---- void xmlXPathPositionFunction(xmlXPathParserContextPtr ctxt, int nargs); void xmlXPathCountFunction(xmlXPathParserContextPtr ctxt, int nargs); void xmlXPathIdFunction(xmlXPathParserContextPtr ctxt, int nargs); ! void xmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt, int nargs); ! void xmlXPathNamespaceURIFunction(xmlXPathParserContextPtr ctxt, int nargs); void xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs); void xmlXPathStringLengthFunction(xmlXPathParserContextPtr ctxt, int nargs); void xmlXPathConcatFunction(xmlXPathParserContextPtr ctxt, int nargs);