diff --git a/ChangeLog b/ChangeLog index 905bc3bc..4f0d88a3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +Mon Jan 15 20:24:18 CET 2001 Daniel Veillard + + * xpath.c: fixed the comaprision of values and nodelists, + need to compare nodelist still ... + * debugXML.c: avoided a possible core dump + * HTMLparser.c: cleanup + * nanohttp.c: contributed fix. + * tree.c: fixes in properties handling added xmlSetNsProp + needed by libxslt + * xpathInternals.h: exported xmlXPathBooleanFunction, added a + comment + * TODO: updated + Sat Jan 6 22:05:09 CET 2001 Daniel Veillard * parser.c parserInternals.c: applied Bjorn Reese optimization diff --git a/HTMLparser.c b/HTMLparser.c index a395c7cd..eedda554 100644 --- a/HTMLparser.c +++ b/HTMLparser.c @@ -926,7 +926,7 @@ htmlCheckParagraph(htmlParserCtxtPtr ctxt) { return(1); } if (!htmlOmittedDefaultValue) - return; + return(0); for (i = 0; htmlNoContentElements[i] != NULL; i++) { if (xmlStrEqual(tag, BAD_CAST htmlNoContentElements[i])) { #ifdef DEBUG @@ -4575,6 +4575,16 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { #ifdef DEBUG_PUSH xmlGenericError(xmlGenericErrorContext, "HPP: entering CONTENT\n"); +#endif + break; + case XML_PARSER_IGNORE: + xmlGenericError(xmlGenericErrorContext, + "HPP: internal error, state == XML_PARSER_IGNORE\n"); + ctxt->instate = XML_PARSER_CONTENT; + ctxt->checkIndex = 0; +#ifdef DEBUG_PUSH + xmlGenericError(xmlGenericErrorContext, + "HPP: entering CONTENT\n"); #endif break; } diff --git a/TODO b/TODO index 49d8ee0e..343d2f46 100644 --- a/TODO +++ b/TODO @@ -35,7 +35,12 @@ TODO: - htmlParseDoc has parameter encoding which is not used. Function htmlCreateDocParserCtxt ignore it. - bug reported by Michael Meallin on validation problems + => Actually means I need to add support (and warn) for non-deterministic + content model. - fix realloc() usage. +- compliance to XML-Namespace checking, see section 6 of + http://www.w3.org/TR/REC-xml-names/ +- Fix output of TODO: ===== diff --git a/debugXML.c b/debugXML.c index 9764885f..0be578e6 100644 --- a/debugXML.c +++ b/debugXML.c @@ -510,7 +510,7 @@ void xmlDebugDumpOneNode(FILE *output, xmlNodePtr node, int depth) { case XML_ELEMENT_NODE: fprintf(output, shift); fprintf(output, "ELEMENT "); - if (node->ns != NULL) { + if ((node->ns != NULL) && (node->ns->prefix != NULL)) { xmlDebugDumpString(output, node->ns->prefix); fprintf(output, ":"); } diff --git a/include/libxml/valid.h b/include/libxml/valid.h index 54babdde..a7eb675d 100644 --- a/include/libxml/valid.h +++ b/include/libxml/valid.h @@ -81,6 +81,10 @@ typedef xmlIDTable *xmlIDTablePtr; typedef struct _xmlHashTable xmlRefTable; typedef xmlRefTable *xmlRefTablePtr; +/* helper */ +xmlChar * xmlSplitQName2 (const xmlChar *name, + xmlChar **prefix); + /* Notation */ xmlNotationPtr xmlAddNotationDecl (xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, diff --git a/include/libxml/xpathInternals.h b/include/libxml/xpathInternals.h index 6967c90f..5126dc7d 100644 --- a/include/libxml/xpathInternals.h +++ b/include/libxml/xpathInternals.h @@ -110,6 +110,7 @@ xmlXPathParserContextPtr xmlXPathContextPtr ctxt); void xmlXPathFreeParserContext (xmlXPathParserContextPtr ctxt); +/* TODO: remap to xmlXPathValuePop and Push */ xmlXPathObjectPtr valuePop (xmlXPathParserContextPtr ctxt); int valuePush (xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value); @@ -204,6 +205,7 @@ void xmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs); void xmlXPathFloorFunction(xmlXPathParserContextPtr ctxt, int nargs); void xmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt, int nargs); void xmlXPathRoundFunction(xmlXPathParserContextPtr ctxt, int nargs); +void xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs); #ifdef __cplusplus } #endif diff --git a/nanohttp.c b/nanohttp.c index 3502e195..cf30c530 100644 --- a/nanohttp.c +++ b/nanohttp.c @@ -377,6 +377,7 @@ xmlNanoHTTPNewCtxt(const char *URL) { memset(ret, 0, sizeof(xmlNanoHTTPCtxt)); ret->port = 80; ret->returnValue = 0; + ret->fd = -1; xmlNanoHTTPScanURL(ret, URL); diff --git a/tree.c b/tree.c index 9a725a04..92db1f13 100644 --- a/tree.c +++ b/tree.c @@ -2425,6 +2425,8 @@ xmlCopyNamespaceList(xmlNsPtr cur) { return(ret); } +static xmlNodePtr +xmlStaticCopyNodeList(xmlNodePtr node, xmlDocPtr doc, xmlNodePtr parent); /** * xmlCopyProp: * @target: the element where the attribute will be grafted @@ -2439,7 +2441,9 @@ xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) { xmlAttrPtr ret; if (cur == NULL) return(NULL); - if (cur->parent != NULL) + if (target != NULL) + ret = xmlNewDocProp(target->doc, cur->name, NULL); + else if (cur->parent != NULL) ret = xmlNewDocProp(cur->parent->doc, cur->name, NULL); else if (cur->children != NULL) ret = xmlNewDocProp(cur->children->doc, cur->name, NULL); @@ -2459,11 +2463,11 @@ xmlCopyProp(xmlNodePtr target, xmlAttrPtr cur) { if (cur->children != NULL) { xmlNodePtr tmp; - ret->children = xmlCopyNodeList(cur->children); + ret->children = xmlStaticCopyNodeList(cur->children, ret->doc, (xmlNodePtr) ret); ret->last = NULL; tmp = ret->children; while (tmp != NULL) { - tmp->parent = (xmlNodePtr)ret; + /* tmp->parent = (xmlNodePtr)ret; */ if (tmp->next == NULL) ret->last = tmp; tmp = tmp->next; @@ -4022,10 +4026,14 @@ xmlGetProp(xmlNodePtr node, const xmlChar *name) { */ xmlChar * xmlGetNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *namespace) { - xmlAttrPtr prop = node->properties; + xmlAttrPtr prop; xmlDocPtr doc; xmlNsPtr ns; + if (node == NULL) + return(NULL); + + prop = node->properties; if (namespace == NULL) return(xmlGetProp(node, name)); while (prop != NULL) { @@ -4118,6 +4126,73 @@ xmlSetProp(xmlNodePtr node, const xmlChar *name, const xmlChar *value) { return(prop); } +/** + * xmlSetNsProp: + * @node: the node + * @ns: the namespace definition + * @name: the attribute name + * @value: the attribute value + * + * Set (or reset) an attribute carried by a node. + * The ns structure must be in scope, this is not checked. + * + * Returns the attribute pointer. + */ +xmlAttrPtr +xmlSetNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name, + const xmlChar *value) { + xmlAttrPtr prop; + + if ((node == NULL) || (name == NULL)) + return(NULL); + + if (ns == NULL) + return(xmlSetProp(node, name, value)); + if (ns->href == NULL) + return(NULL); + prop = node->properties; + + while (prop != NULL) { + /* + * One need to have + * - same attribute names + * - and the attribute carrying that namespace + * or + * no namespace on the attribute and the element carrying it + */ + if ((xmlStrEqual(prop->name, name)) && + (((prop->ns == NULL) && (node->ns != NULL) && + (xmlStrEqual(node->ns->href, ns->href))) || + ((prop->ns != NULL) && (xmlStrEqual(prop->ns->href, ns->href))))) { + if (prop->children != NULL) + xmlFreeNodeList(prop->children); + prop->children = NULL; + prop->last = NULL; + prop->ns = ns; + if (value != NULL) { + xmlChar *buffer; + xmlNodePtr tmp; + + buffer = xmlEncodeEntitiesReentrant(node->doc, value); + prop->children = xmlStringGetNodeList(node->doc, buffer); + prop->last = NULL; + tmp = prop->children; + while (tmp != NULL) { + tmp->parent = (xmlNodePtr) prop; + if (tmp->next == NULL) + prop->last = tmp; + tmp = tmp->next; + } + xmlFree(buffer); + } + return(prop); + } + prop = prop->next; + } + prop = xmlNewNsProp(node, ns, name, value); + return(prop); +} + /** * xmlNodeIsText: * @node: the node diff --git a/valid.h b/valid.h index 54babdde..a7eb675d 100644 --- a/valid.h +++ b/valid.h @@ -81,6 +81,10 @@ typedef xmlIDTable *xmlIDTablePtr; typedef struct _xmlHashTable xmlRefTable; typedef xmlRefTable *xmlRefTablePtr; +/* helper */ +xmlChar * xmlSplitQName2 (const xmlChar *name, + xmlChar **prefix); + /* Notation */ xmlNotationPtr xmlAddNotationDecl (xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, diff --git a/xpath.c b/xpath.c index d87318c8..45976a58 100644 --- a/xpath.c +++ b/xpath.c @@ -1485,6 +1485,178 @@ void xmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs); arg = valuePop(ctxt); \ } +/** + * xmlXPathCompareNodeSetFloat: + * @ctxt: the XPath Parser context + * @inf: less than (1) or greater than (0) + * @strict: is the comparison strict + * @arg: the node set + * @f: the value + * + * Implement the compare operation between a nodeset and a number + * @ns < @val (1, 1, ... + * @ns <= @val (1, 0, ... + * @ns > @val (0, 1, ... + * @ns >= @val (0, 0, ... + * + * If one object to be compared is a node-set and the other is a number, + * then the comparison will be true if and only if there is a node in the + * node-set such that the result of performing the comparison on the number + * to be compared and on the result of converting the string-value of that + * node to a number using the number function is true. + * + * Returns 0 or 1 depending on the results of the test. + */ +int +xmlXPathCompareNodeSetFloat(xmlXPathParserContextPtr ctxt, int inf, int strict, + xmlXPathObjectPtr arg, xmlXPathObjectPtr f) { + int i, ret = 0; + xmlNodeSetPtr ns; + xmlChar *str2; + + if ((f == NULL) || (arg == NULL) || (arg->type != XPATH_NODESET)) { + xmlXPathFreeObject(arg); + xmlXPathFreeObject(f); + return(0); + } + ns = arg->nodesetval; + for (i = 0;i < ns->nodeNr;i++) { + str2 = xmlNodeGetContent(ns->nodeTab[i]); + if (str2 != NULL) { + valuePush(ctxt, + xmlXPathNewString(str2)); + xmlFree(str2); + xmlXPathNumberFunction(ctxt, 1); + valuePush(ctxt, xmlXPathObjectCopy(f)); + ret = xmlXPathCompareValues(ctxt, inf, strict); + if (ret) + break; + } + } + xmlXPathFreeObject(arg); + xmlXPathFreeObject(f); + return(ret); +} + +/** + * xmlXPathCompareNodeSetString: + * @ctxt: the XPath Parser context + * @inf: less than (1) or greater than (0) + * @strict: is the comparison strict + * @arg: the node set + * @s: the value + * + * Implement the compare operation between a nodeset and a string + * @ns < @val (1, 1, ... + * @ns <= @val (1, 0, ... + * @ns > @val (0, 1, ... + * @ns >= @val (0, 0, ... + * + * If one object to be compared is a node-set and the other is a string, + * then the comparison will be true if and only if there is a node in + * the node-set such that the result of performing the comparison on the + * string-value of the node and the other string is true. + * + * Returns 0 or 1 depending on the results of the test. + */ +int +xmlXPathCompareNodeSetString(xmlXPathParserContextPtr ctxt, int inf, int strict, + xmlXPathObjectPtr arg, xmlXPathObjectPtr s) { + int i, ret = 0; + xmlNodeSetPtr ns; + xmlChar *str2; + + if ((s == NULL) || (arg == NULL) || (arg->type != XPATH_NODESET)) { + xmlXPathFreeObject(arg); + xmlXPathFreeObject(s); + return(0); + } + ns = arg->nodesetval; + for (i = 0;i < ns->nodeNr;i++) { + str2 = xmlNodeGetContent(ns->nodeTab[i]); + if (str2 != NULL) { + valuePush(ctxt, + xmlXPathNewString(str2)); + xmlFree(str2); + valuePush(ctxt, xmlXPathObjectCopy(s)); + ret = xmlXPathCompareValues(ctxt, inf, strict); + if (ret) + break; + } + } + xmlXPathFreeObject(arg); + xmlXPathFreeObject(s); + return(ret); +} + +/** + * xmlXPathCompareNodeSets: + * @ctxt: the XPath Parser context + * @op: less than (-1), equal (0) or greater than (1) + * @strict: is the comparison strict + * @ns1: the fist node set + * @ns2: the second node set + * + * Implement the compare operation on nodesets: + * + * If both objects to be compared are node-sets, then the comparison will be true if + * and only if there is a node in the first node-set and a node in the second node-set + * such that the result of performing the comparison on the string-values of the two + * nodes is true. + */ +int +xmlXPathCompareNodeSets(xmlXPathParserContextPtr ctxt, int inf, int strict, + xmlXPathObjectPtr ns1, xmlXPathObjectPtr ns2) { + TODO + return(0); +} + +/** + * xmlXPathCompareNodeSetValue: + * @ctxt: the XPath Parser context + * @inf: less than (1) or greater than (0) + * @strict: is the comparison strict + * @arg: the node set + * @val: the value + * + * Implement the compare operation between a nodeset and a value + * @ns < @val (1, 1, ... + * @ns <= @val (1, 0, ... + * @ns > @val (0, 1, ... + * @ns >= @val (0, 0, ... + * + * If one object to be compared is a node-set and the other is a boolean, then the + * comparison will be true if and only if the result of performing the comparison + * on the boolean and on the result of converting the node-set to a boolean using + * the boolean function is true. + * + * Returns 0 or 1 depending on the results of the test. + */ +int +xmlXPathCompareNodeSetValue(xmlXPathParserContextPtr ctxt, int inf, int strict, + xmlXPathObjectPtr arg, xmlXPathObjectPtr val) { + if ((val == NULL) || (arg == NULL) || (arg->type != XPATH_NODESET)) + return(0); + + switch(val->type) { + case XPATH_NUMBER: + return(xmlXPathCompareNodeSetFloat(ctxt, inf, strict, arg, val)); + case XPATH_NODESET: + return(xmlXPathCompareNodeSets(ctxt, inf, strict, arg, val)); + case XPATH_STRING: + return(xmlXPathCompareNodeSetString(ctxt, inf, strict, arg, val)); + case XPATH_BOOLEAN: + valuePush(ctxt, arg); + xmlXPathBooleanFunction(ctxt, 1); + valuePush(ctxt, val); + return(xmlXPathCompareValues(ctxt, inf, strict)); + default: + TODO + return(0); + } + return(0); +} + /** * xmlXPathEqualNodeSetString * @arg: the nodeset object argument @@ -1781,10 +1953,11 @@ xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) { return(ret); } + /** * xmlXPathCompareValues: * @ctxt: the XPath Parser context - * @inf: less than (1) or greater than (2) + * @inf: less than (1) or greater than (0) * @strict: is the comparison strict * * Implement the compare operation on XPath objects: @@ -1802,6 +1975,8 @@ xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) { * will be true if and only if the first number is greater than the second * number. The >= comparison will be true if and only if the first number * is greater than or equal to the second number. + * + * Returns 1 if the comparaison succeeded, 0 if it failed */ int xmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict) { @@ -1809,20 +1984,29 @@ xmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict) { xmlXPathObjectPtr arg1, arg2; arg2 = valuePop(ctxt); - if ((arg2 == NULL) || (arg2->type == XPATH_NODESET)) { - if (arg2 != NULL) - xmlXPathFreeObject(arg2); + if (arg2 == NULL) { XP_ERROR0(XPATH_INVALID_OPERAND); } arg1 = valuePop(ctxt); - if ((arg1 == NULL) || (arg1->type == XPATH_NODESET)) { - if (arg1 != NULL) - xmlXPathFreeObject(arg1); + if (arg1 == NULL) { xmlXPathFreeObject(arg2); XP_ERROR0(XPATH_INVALID_OPERAND); } + if ((arg2->type == XPATH_NODESET) || (arg1->type == XPATH_NODESET)) { + if ((arg2->type == XPATH_NODESET) && (arg1->type == XPATH_NODESET)) { + ret = xmlXPathCompareNodeSets(ctxt, inf, strict, arg1, arg2); + } else { + if (arg1->type == XPATH_NODESET) { + ret = xmlXPathCompareNodeSetValue(ctxt, inf, strict, arg1, arg2); + } else { + ret = xmlXPathCompareNodeSetValue(ctxt, !inf, !strict, arg2, arg2); + } + } + return(ret); + } + if (arg1->type != XPATH_NUMBER) { valuePush(ctxt, arg1); xmlXPathNumberFunction(ctxt, 1); @@ -4674,6 +4858,10 @@ xmlXPathEvalPathExpr(xmlXPathParserContextPtr ctxt) { #endif lc = 1; break; + } else if ((NXT(len) == '<') || (NXT(len) == '>') || + (NXT(len) == '=')) { + lc = 1; + break; } else { XP_ERROR(XPATH_EXPR_ERROR); } diff --git a/xpathInternals.h b/xpathInternals.h index 6967c90f..5126dc7d 100644 --- a/xpathInternals.h +++ b/xpathInternals.h @@ -110,6 +110,7 @@ xmlXPathParserContextPtr xmlXPathContextPtr ctxt); void xmlXPathFreeParserContext (xmlXPathParserContextPtr ctxt); +/* TODO: remap to xmlXPathValuePop and Push */ xmlXPathObjectPtr valuePop (xmlXPathParserContextPtr ctxt); int valuePush (xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value); @@ -204,6 +205,7 @@ void xmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs); void xmlXPathFloorFunction(xmlXPathParserContextPtr ctxt, int nargs); void xmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt, int nargs); void xmlXPathRoundFunction(xmlXPathParserContextPtr ctxt, int nargs); +void xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs); #ifdef __cplusplus } #endif