Fixes in the plane: - xpath.c: fixed a [] evaluation problem reported -
Fixes in the plane:
- xpath.c: fixed a [] evaluation problem reported
- test/XPath/tests/simpleaddr: extended test
- result/XPath/simpleaddr: updated result
Daniel
diff --git a/xpath.c b/xpath.c
index 98f37c0..89b139f 100644
--- a/xpath.c
+++ b/xpath.c
@@ -204,6 +204,7 @@
XPATH_OP_FUNCTION,
XPATH_OP_ARG,
XPATH_OP_PREDICATE,
+ XPATH_OP_FILTER,
XPATH_OP_SORT
#ifdef LIBXML_XPTR_ENABLED
,XPATH_OP_RANGETO
@@ -378,6 +379,9 @@
return(comp->nbStep++);
}
+#define PUSH_FULL_EXPR(op, op1, op2, val, val2, val3, val4, val5) \
+ xmlXPathCompExprAdd(ctxt->comp, (op1), (op2), \
+ (op), (val), (val2), (val3), (val4), (val5))
#define PUSH_LONG_EXPR(op, val, val2, val3, val4, val5) \
xmlXPathCompExprAdd(ctxt->comp, ctxt->comp->last, -1, \
(op), (val), (val2), (val3), (val4), (val5))
@@ -782,6 +786,7 @@
}
case XPATH_OP_ARG: fprintf(output, "ARG"); break;
case XPATH_OP_PREDICATE: fprintf(output, "PREDICATE"); break;
+ case XPATH_OP_FILTER: fprintf(output, "FILTER"); break;
default:
fprintf(output, "UNKNOWN %d\n", op->op); return;
}
@@ -1096,6 +1101,9 @@
cur = ctxt->cur;
base = ctxt->base;
+ if ((cur == NULL) || (base == NULL))
+ return;
+
while ((cur > base) && ((*cur == '\n') || (*cur == '\r'))) {
cur--;
}
@@ -1376,7 +1384,7 @@
*/
xmlNodeSetPtr
xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
- int i, j, initNr;
+ int i, j, initNr, skip;
if (val2 == NULL) return(val1);
if (val1 == NULL) {
@@ -1389,8 +1397,15 @@
/*
* check against doublons
*/
- for (j = 0; j < initNr; j++)
- if (val1->nodeTab[j] == val2->nodeTab[i]) continue;
+ skip = 0;
+ for (j = 0; j < initNr; j++) {
+ if (val1->nodeTab[j] == val2->nodeTab[i]) {
+ skip = 1;
+ break;
+ }
+ }
+ if (skip)
+ continue;
/*
* grow the nodeTab if needed
@@ -2555,12 +2570,12 @@
ns1 = arg1->nodesetval;
ns2 = arg2->nodesetval;
- if (ns1->nodeNr <= 0) {
+ if ((ns1 == NULL) || (ns1->nodeNr <= 0)) {
xmlXPathFreeObject(arg1);
xmlXPathFreeObject(arg2);
return(0);
}
- if (ns2->nodeNr <= 0) {
+ if ((ns2 == NULL) || (ns2->nodeNr <= 0)) {
xmlXPathFreeObject(arg1);
xmlXPathFreeObject(arg2);
return(0);
@@ -2685,6 +2700,8 @@
((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
return(0);
ns = arg->nodesetval;
+ if (ns == NULL)
+ return(0);
if (ns->nodeNr <= 0)
return(0);
for (i = 0;i < ns->nodeNr;i++) {
@@ -3752,339 +3769,6 @@
#define IS_FUNCTION 200
-/**
- * xmlXPathNodeCollectAndTest:
- * @ctxt: the XPath Parser context
- * @axis: the XPath axis
- * @test: the XPath test
- * @type: the XPath type
- * @prefix: the namesapce prefix if any
- * @name: the name used in the search if any
- *
- * This is the function implementing a step: based on the current list
- * of nodes, it builds up a new list, looking at all nodes under that
- * axis and selecting them.
- *
- * Returns the new NodeSet resulting from the search.
- */
-static void
-xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt, xmlXPathAxisVal axis,
- xmlXPathTestVal test, xmlXPathTypeVal type,
- const xmlChar *prefix, const xmlChar *name) {
-#ifdef DEBUG_STEP
- int n = 0, t = 0;
-#endif
- int i;
- xmlNodeSetPtr ret;
- xmlXPathTraversalFunction next = NULL;
- void (*addNode)(xmlNodeSetPtr, xmlNodePtr);
- xmlNodePtr cur = NULL;
- xmlXPathObjectPtr obj;
- xmlNodeSetPtr nodelist;
- xmlNodePtr tmp;
-
- CHECK_TYPE(XPATH_NODESET);
- obj = valuePop(ctxt);
- addNode = xmlXPathNodeSetAdd;
-
-#ifdef DEBUG_STEP
- xmlGenericError(xmlGenericErrorContext,
- "new step : ");
-#endif
- switch (axis) {
- case AXIS_ANCESTOR:
-#ifdef DEBUG_STEP
- xmlGenericError(xmlGenericErrorContext,
- "axis 'ancestors' ");
-#endif
- next = xmlXPathNextAncestor; break;
- case AXIS_ANCESTOR_OR_SELF:
-#ifdef DEBUG_STEP
- xmlGenericError(xmlGenericErrorContext,
- "axis 'ancestors-or-self' ");
-#endif
- next = xmlXPathNextAncestorOrSelf; break;
- case AXIS_ATTRIBUTE:
-#ifdef DEBUG_STEP
- xmlGenericError(xmlGenericErrorContext,
- "axis 'attributes' ");
-#endif
- next = xmlXPathNextAttribute; break;
- break;
- case AXIS_CHILD:
-#ifdef DEBUG_STEP
- xmlGenericError(xmlGenericErrorContext,
- "axis 'child' ");
-#endif
- next = xmlXPathNextChild; break;
- case AXIS_DESCENDANT:
-#ifdef DEBUG_STEP
- xmlGenericError(xmlGenericErrorContext,
- "axis 'descendant' ");
-#endif
- next = xmlXPathNextDescendant; break;
- case AXIS_DESCENDANT_OR_SELF:
-#ifdef DEBUG_STEP
- xmlGenericError(xmlGenericErrorContext,
- "axis 'descendant-or-self' ");
-#endif
- next = xmlXPathNextDescendantOrSelf; break;
- case AXIS_FOLLOWING:
-#ifdef DEBUG_STEP
- xmlGenericError(xmlGenericErrorContext,
- "axis 'following' ");
-#endif
- next = xmlXPathNextFollowing; break;
- case AXIS_FOLLOWING_SIBLING:
-#ifdef DEBUG_STEP
- xmlGenericError(xmlGenericErrorContext,
- "axis 'following-siblings' ");
-#endif
- next = xmlXPathNextFollowingSibling; break;
- case AXIS_NAMESPACE:
-#ifdef DEBUG_STEP
- xmlGenericError(xmlGenericErrorContext,
- "axis 'namespace' ");
-#endif
- next = (xmlXPathTraversalFunction) xmlXPathNextNamespace; break;
- break;
- case AXIS_PARENT:
-#ifdef DEBUG_STEP
- xmlGenericError(xmlGenericErrorContext,
- "axis 'parent' ");
-#endif
- next = xmlXPathNextParent; break;
- case AXIS_PRECEDING:
-#ifdef DEBUG_STEP
- xmlGenericError(xmlGenericErrorContext,
- "axis 'preceding' ");
-#endif
- next = xmlXPathNextPreceding; break;
- case AXIS_PRECEDING_SIBLING:
-#ifdef DEBUG_STEP
- xmlGenericError(xmlGenericErrorContext,
- "axis 'preceding-sibling' ");
-#endif
- next = xmlXPathNextPrecedingSibling; break;
- case AXIS_SELF:
-#ifdef DEBUG_STEP
- xmlGenericError(xmlGenericErrorContext,
- "axis 'self' ");
-#endif
- next = xmlXPathNextSelf; break;
- }
- if (next == NULL)
- return;
-
- nodelist = obj->nodesetval;
- if ((nodelist != NULL) &&
- (nodelist->nodeNr <= 1))
- addNode = xmlXPathNodeSetAddUnique;
- else
- addNode = xmlXPathNodeSetAdd;
- ret = xmlXPathNodeSetCreate(NULL);
-#ifdef DEBUG_STEP
- xmlGenericError(xmlGenericErrorContext,
- " context contains %d nodes\n",
- nodelist->nodeNr);
- switch (test) {
- case NODE_TEST_NODE:
- xmlGenericError(xmlGenericErrorContext,
- " searching all nodes\n");
- break;
- case NODE_TEST_NONE:
- xmlGenericError(xmlGenericErrorContext,
- " searching for none !!!\n");
- break;
- case NODE_TEST_TYPE:
- xmlGenericError(xmlGenericErrorContext,
- " searching for type %d\n", type);
- break;
- case NODE_TEST_PI:
- xmlGenericError(xmlGenericErrorContext,
- " searching for PI !!!\n");
- break;
- case NODE_TEST_ALL:
- xmlGenericError(xmlGenericErrorContext,
- " searching for *\n");
- break;
- case NODE_TEST_NS:
- xmlGenericError(xmlGenericErrorContext,
- " searching for namespace %s\n",
- prefix);
- break;
- case NODE_TEST_NAME:
- xmlGenericError(xmlGenericErrorContext,
- " searching for name %s\n", name);
- if (prefix != NULL)
- xmlGenericError(xmlGenericErrorContext,
- " with namespace %s\n",
- prefix);
- break;
- }
- xmlGenericError(xmlGenericErrorContext, "Testing : ");
-#endif
- /*
- * 2.3 Node Tests
- * - For the attribute axis, the principal node type is attribute.
- * - For the namespace axis, the principal node type is namespace.
- * - For other axes, the principal node type is element.
- *
- * A node test * is true for any node of the
- * principal node type. For example, child::* willi
- * select all element children of the context node
- */
- tmp = ctxt->context->node;
- for (i = 0;i < nodelist->nodeNr; i++) {
- ctxt->context->node = nodelist->nodeTab[i];
-
- cur = NULL;
- do {
- cur = next(ctxt, cur);
- if (cur == NULL) break;
-#ifdef DEBUG_STEP
- t++;
- xmlGenericError(xmlGenericErrorContext, " %s", cur->name);
-#endif
- switch (test) {
- case NODE_TEST_NONE:
- ctxt->context->node = tmp;
- STRANGE
- return;
- case NODE_TEST_TYPE:
- if ((cur->type == type) ||
- ((type == NODE_TYPE_NODE) &&
- ((cur->type == XML_DOCUMENT_NODE) ||
- (cur->type == XML_HTML_DOCUMENT_NODE) ||
- (cur->type == XML_ELEMENT_NODE) ||
- (cur->type == XML_PI_NODE) ||
- (cur->type == XML_COMMENT_NODE) ||
- (cur->type == XML_CDATA_SECTION_NODE) ||
- (cur->type == XML_TEXT_NODE)))) {
-#ifdef DEBUG_STEP
- n++;
-#endif
- addNode(ret, cur);
- }
- break;
- case NODE_TEST_PI:
- if (cur->type == XML_PI_NODE) {
- if ((name != NULL) &&
- (!xmlStrEqual(name, cur->name)))
- break;
-#ifdef DEBUG_STEP
- n++;
-#endif
- addNode(ret, cur);
- }
- break;
- case NODE_TEST_ALL:
- if (axis == AXIS_ATTRIBUTE) {
- if (cur->type == XML_ATTRIBUTE_NODE) {
-#ifdef DEBUG_STEP
- n++;
-#endif
- addNode(ret, cur);
- }
- } else if (axis == AXIS_NAMESPACE) {
- if (cur->type == XML_NAMESPACE_DECL) {
-#ifdef DEBUG_STEP
- n++;
-#endif
- addNode(ret, cur);
- }
- } else {
- if ((cur->type == XML_ELEMENT_NODE) ||
- (cur->type == XML_DOCUMENT_NODE) ||
- (cur->type == XML_HTML_DOCUMENT_NODE)) {
- if (prefix == NULL) {
-#ifdef DEBUG_STEP
- n++;
-#endif
- addNode(ret, cur);
- } else if ((cur->ns != NULL) &&
- (xmlStrEqual(prefix,
- cur->ns->href))) {
-#ifdef DEBUG_STEP
- n++;
-#endif
- addNode(ret, cur);
- }
- }
- }
- break;
- case NODE_TEST_NS: {
- TODO;
- break;
- }
- case NODE_TEST_NAME:
- switch (cur->type) {
- case XML_ELEMENT_NODE:
- if (xmlStrEqual(name, cur->name)) {
- if (prefix == NULL) {
- if ((cur->ns == NULL) ||
- (cur->ns->prefix == NULL)) {
-#ifdef DEBUG_STEP
- n++;
-#endif
- addNode(ret, cur);
- }
- } else {
- if ((cur->ns != NULL) &&
- (xmlStrEqual(prefix,
- cur->ns->href))) {
-#ifdef DEBUG_STEP
- n++;
-#endif
- addNode(ret, cur);
- }
- }
- }
- break;
- case XML_ATTRIBUTE_NODE: {
- xmlAttrPtr attr = (xmlAttrPtr) cur;
- if (xmlStrEqual(name, attr->name)) {
- if (prefix == NULL) {
- if ((attr->ns == NULL) ||
- (attr->ns->prefix == NULL)) {
-#ifdef DEBUG_STEP
- n++;
-#endif
- addNode(ret, (xmlNodePtr) attr);
- }
- } else {
- if ((attr->ns != NULL) &&
- (xmlStrEqual(prefix,
- attr->ns->href))) {
-#ifdef DEBUG_STEP
- n++;
-#endif
- addNode(ret, (xmlNodePtr) attr);
- }
- }
- }
- break;
- }
- case XML_NAMESPACE_DECL: {
- TODO;
- break;
- }
- default:
- break;
- }
- break;
- }
- } while (cur != NULL);
- }
- ctxt->context->node = tmp;
-#ifdef DEBUG_STEP
- xmlGenericError(xmlGenericErrorContext,
- "\nExamined %d nodes, found %d nodes at that step\n", t, n);
-#endif
- xmlXPathFreeObject(obj);
- valuePush(ctxt, xmlXPathWrapNodeSet(ret));
-}
-
/************************************************************************
* *
@@ -5280,7 +4964,7 @@
XP_ERROR(XPATH_INVALID_TYPE);
cur = valuePop(ctxt);
- if (cur->nodesetval->nodeNr == 0) {
+ if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
valuePush(ctxt, xmlXPathNewFloat(0.0));
} else {
valuePush(ctxt,
@@ -5392,7 +5076,7 @@
* implementation.
*/
static void xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt);
-static void xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt);
+static void xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter);
static void xmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt);
#ifdef VMS
static void xmlXPathCompRelLocationPath(xmlXPathParserContextPtr ctxt);
@@ -5865,7 +5549,7 @@
SKIP_BLANKS;
while (CUR == '[') {
- xmlXPathCompPredicate(ctxt);
+ xmlXPathCompPredicate(ctxt, 1);
SKIP_BLANKS;
}
@@ -6358,6 +6042,7 @@
/**
* xmlXPathCompPredicate:
* @ctxt: the XPath Parser context
+ * @filter: act as a filter
*
* [8] Predicate ::= '[' PredicateExpr ']'
* [9] PredicateExpr ::= Expr
@@ -6365,7 +6050,7 @@
* Compile a predicate expression
*/
static void
-xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt) {
+xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter) {
int op1 = ctxt->comp->last;
SKIP_BLANKS;
@@ -6383,7 +6068,10 @@
XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
}
- PUSH_BINARY_EXPR(XPATH_OP_PREDICATE, op1, ctxt->comp->last, 0, 0);
+ if (filter)
+ PUSH_BINARY_EXPR(XPATH_OP_FILTER, op1, ctxt->comp->last, 0, 0);
+ else
+ PUSH_BINARY_EXPR(XPATH_OP_PREDICATE, op1, ctxt->comp->last, 0, 0);
NEXT;
SKIP_BLANKS;
@@ -6637,8 +6325,9 @@
xmlChar *name = NULL;
const xmlChar *prefix = NULL;
xmlXPathTestVal test;
- xmlXPathAxisVal axis;
+ xmlXPathAxisVal axis = 0;
xmlXPathTypeVal type;
+ int op1;
/*
* The modification needed for XPointer change to the production
@@ -6647,7 +6336,7 @@
if (ctxt->xptr) {
name = xmlXPathParseNCName(ctxt);
if ((name != NULL) && (xmlStrEqual(name, BAD_CAST "range-to"))) {
- int op1 = ctxt->comp->last;
+ int op2 = ctxt->comp->last;
xmlFree(name);
SKIP_BLANKS;
if (CUR != '(') {
@@ -6657,7 +6346,7 @@
SKIP_BLANKS;
xmlXPathCompileExpr(ctxt);
- PUSH_BINARY_EXPR(XPATH_OP_RANGETO, op1, ctxt->comp->last, 0, 0);
+ PUSH_BINARY_EXPR(XPATH_OP_RANGETO, op2, ctxt->comp->last, 0, 0);
CHECK_ERROR;
SKIP_BLANKS;
@@ -6704,19 +6393,23 @@
"Basis : computing new set\n");
#endif
- PUSH_LONG_EXPR(XPATH_OP_COLLECT, axis, test, type,
- (void *)prefix, (void *)name);
-
#ifdef DEBUG_STEP
xmlGenericError(xmlGenericErrorContext, "Basis : ");
xmlGenericErrorContextNodeSet(stdout, ctxt->value->nodesetval);
#endif
eval_predicates:
+ op1 = ctxt->comp->last;
+ ctxt->comp->last = -1;
+
SKIP_BLANKS;
while (CUR == '[') {
- xmlXPathCompPredicate(ctxt);
+ xmlXPathCompPredicate(ctxt, 0);
}
+
+ PUSH_FULL_EXPR(XPATH_OP_COLLECT, op1, ctxt->comp->last, axis,
+ test, type, (void *)prefix, (void *)name);
+
}
#ifdef DEBUG_STEP
xmlGenericError(xmlGenericErrorContext, "Step : ");
@@ -6821,6 +6514,366 @@
* *
************************************************************************/
+static void
+xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op);
+
+/**
+ * xmlXPathNodeCollectAndTest:
+ * @ctxt: the XPath Parser context
+ * @op: the XPath precompiled step operation
+ *
+ * This is the function implementing a step: based on the current list
+ * of nodes, it builds up a new list, looking at all nodes under that
+ * axis and selecting them it also do the predicate filtering
+ *
+ * Pushes the new NodeSet resulting from the search.
+ */
+static void
+xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
+ xmlXPathStepOpPtr op) {
+ xmlXPathAxisVal axis = op->value;
+ xmlXPathTestVal test = op->value2;
+ xmlXPathTypeVal type = op->value3;
+ const xmlChar *prefix = op->value4;
+ const xmlChar *name = op->value5;
+
+#ifdef DEBUG_STEP
+ int n = 0, t = 0;
+#endif
+ int i;
+ xmlNodeSetPtr ret, list;
+ xmlXPathTraversalFunction next = NULL;
+ void (*addNode)(xmlNodeSetPtr, xmlNodePtr);
+ xmlNodePtr cur = NULL;
+ xmlXPathObjectPtr obj;
+ xmlNodeSetPtr nodelist;
+ xmlNodePtr tmp;
+
+ CHECK_TYPE(XPATH_NODESET);
+ obj = valuePop(ctxt);
+ addNode = xmlXPathNodeSetAdd;
+
+#ifdef DEBUG_STEP
+ xmlGenericError(xmlGenericErrorContext,
+ "new step : ");
+#endif
+ switch (axis) {
+ case AXIS_ANCESTOR:
+#ifdef DEBUG_STEP
+ xmlGenericError(xmlGenericErrorContext,
+ "axis 'ancestors' ");
+#endif
+ next = xmlXPathNextAncestor; break;
+ case AXIS_ANCESTOR_OR_SELF:
+#ifdef DEBUG_STEP
+ xmlGenericError(xmlGenericErrorContext,
+ "axis 'ancestors-or-self' ");
+#endif
+ next = xmlXPathNextAncestorOrSelf; break;
+ case AXIS_ATTRIBUTE:
+#ifdef DEBUG_STEP
+ xmlGenericError(xmlGenericErrorContext,
+ "axis 'attributes' ");
+#endif
+ next = xmlXPathNextAttribute; break;
+ break;
+ case AXIS_CHILD:
+#ifdef DEBUG_STEP
+ xmlGenericError(xmlGenericErrorContext,
+ "axis 'child' ");
+#endif
+ next = xmlXPathNextChild; break;
+ case AXIS_DESCENDANT:
+#ifdef DEBUG_STEP
+ xmlGenericError(xmlGenericErrorContext,
+ "axis 'descendant' ");
+#endif
+ next = xmlXPathNextDescendant; break;
+ case AXIS_DESCENDANT_OR_SELF:
+#ifdef DEBUG_STEP
+ xmlGenericError(xmlGenericErrorContext,
+ "axis 'descendant-or-self' ");
+#endif
+ next = xmlXPathNextDescendantOrSelf; break;
+ case AXIS_FOLLOWING:
+#ifdef DEBUG_STEP
+ xmlGenericError(xmlGenericErrorContext,
+ "axis 'following' ");
+#endif
+ next = xmlXPathNextFollowing; break;
+ case AXIS_FOLLOWING_SIBLING:
+#ifdef DEBUG_STEP
+ xmlGenericError(xmlGenericErrorContext,
+ "axis 'following-siblings' ");
+#endif
+ next = xmlXPathNextFollowingSibling; break;
+ case AXIS_NAMESPACE:
+#ifdef DEBUG_STEP
+ xmlGenericError(xmlGenericErrorContext,
+ "axis 'namespace' ");
+#endif
+ next = (xmlXPathTraversalFunction) xmlXPathNextNamespace; break;
+ break;
+ case AXIS_PARENT:
+#ifdef DEBUG_STEP
+ xmlGenericError(xmlGenericErrorContext,
+ "axis 'parent' ");
+#endif
+ next = xmlXPathNextParent; break;
+ case AXIS_PRECEDING:
+#ifdef DEBUG_STEP
+ xmlGenericError(xmlGenericErrorContext,
+ "axis 'preceding' ");
+#endif
+ next = xmlXPathNextPreceding; break;
+ case AXIS_PRECEDING_SIBLING:
+#ifdef DEBUG_STEP
+ xmlGenericError(xmlGenericErrorContext,
+ "axis 'preceding-sibling' ");
+#endif
+ next = xmlXPathNextPrecedingSibling; break;
+ case AXIS_SELF:
+#ifdef DEBUG_STEP
+ xmlGenericError(xmlGenericErrorContext,
+ "axis 'self' ");
+#endif
+ next = xmlXPathNextSelf; break;
+ }
+ if (next == NULL)
+ return;
+
+ nodelist = obj->nodesetval;
+ if (nodelist == NULL) {
+ xmlXPathFreeObject(obj);
+ valuePush(ctxt, xmlXPathWrapNodeSet(NULL));
+ return;
+ }
+ addNode = xmlXPathNodeSetAddUnique;
+ ret = NULL;
+#ifdef DEBUG_STEP
+ xmlGenericError(xmlGenericErrorContext,
+ " context contains %d nodes\n",
+ nodelist->nodeNr);
+ switch (test) {
+ case NODE_TEST_NODE:
+ xmlGenericError(xmlGenericErrorContext,
+ " searching all nodes\n");
+ break;
+ case NODE_TEST_NONE:
+ xmlGenericError(xmlGenericErrorContext,
+ " searching for none !!!\n");
+ break;
+ case NODE_TEST_TYPE:
+ xmlGenericError(xmlGenericErrorContext,
+ " searching for type %d\n", type);
+ break;
+ case NODE_TEST_PI:
+ xmlGenericError(xmlGenericErrorContext,
+ " searching for PI !!!\n");
+ break;
+ case NODE_TEST_ALL:
+ xmlGenericError(xmlGenericErrorContext,
+ " searching for *\n");
+ break;
+ case NODE_TEST_NS:
+ xmlGenericError(xmlGenericErrorContext,
+ " searching for namespace %s\n",
+ prefix);
+ break;
+ case NODE_TEST_NAME:
+ xmlGenericError(xmlGenericErrorContext,
+ " searching for name %s\n", name);
+ if (prefix != NULL)
+ xmlGenericError(xmlGenericErrorContext,
+ " with namespace %s\n",
+ prefix);
+ break;
+ }
+ xmlGenericError(xmlGenericErrorContext, "Testing : ");
+#endif
+ /*
+ * 2.3 Node Tests
+ * - For the attribute axis, the principal node type is attribute.
+ * - For the namespace axis, the principal node type is namespace.
+ * - For other axes, the principal node type is element.
+ *
+ * A node test * is true for any node of the
+ * principal node type. For example, child::* willi
+ * select all element children of the context node
+ */
+ tmp = ctxt->context->node;
+ for (i = 0;i < nodelist->nodeNr; i++) {
+ ctxt->context->node = nodelist->nodeTab[i];
+
+ cur = NULL;
+ list = xmlXPathNodeSetCreate(NULL);
+ do {
+ cur = next(ctxt, cur);
+ if (cur == NULL) break;
+#ifdef DEBUG_STEP
+ t++;
+ xmlGenericError(xmlGenericErrorContext, " %s", cur->name);
+#endif
+ switch (test) {
+ case NODE_TEST_NONE:
+ ctxt->context->node = tmp;
+ STRANGE
+ return;
+ case NODE_TEST_TYPE:
+ if ((cur->type == type) ||
+ ((type == NODE_TYPE_NODE) &&
+ ((cur->type == XML_DOCUMENT_NODE) ||
+ (cur->type == XML_HTML_DOCUMENT_NODE) ||
+ (cur->type == XML_ELEMENT_NODE) ||
+ (cur->type == XML_PI_NODE) ||
+ (cur->type == XML_COMMENT_NODE) ||
+ (cur->type == XML_CDATA_SECTION_NODE) ||
+ (cur->type == XML_TEXT_NODE)))) {
+#ifdef DEBUG_STEP
+ n++;
+#endif
+ addNode(list, cur);
+ }
+ break;
+ case NODE_TEST_PI:
+ if (cur->type == XML_PI_NODE) {
+ if ((name != NULL) &&
+ (!xmlStrEqual(name, cur->name)))
+ break;
+#ifdef DEBUG_STEP
+ n++;
+#endif
+ addNode(list, cur);
+ }
+ break;
+ case NODE_TEST_ALL:
+ if (axis == AXIS_ATTRIBUTE) {
+ if (cur->type == XML_ATTRIBUTE_NODE) {
+#ifdef DEBUG_STEP
+ n++;
+#endif
+ addNode(list, cur);
+ }
+ } else if (axis == AXIS_NAMESPACE) {
+ if (cur->type == XML_NAMESPACE_DECL) {
+#ifdef DEBUG_STEP
+ n++;
+#endif
+ addNode(list, cur);
+ }
+ } else {
+ if ((cur->type == XML_ELEMENT_NODE) ||
+ (cur->type == XML_DOCUMENT_NODE) ||
+ (cur->type == XML_HTML_DOCUMENT_NODE)) {
+ if (prefix == NULL) {
+#ifdef DEBUG_STEP
+ n++;
+#endif
+ addNode(list, cur);
+ } else if ((cur->ns != NULL) &&
+ (xmlStrEqual(prefix,
+ cur->ns->href))) {
+#ifdef DEBUG_STEP
+ n++;
+#endif
+ addNode(list, cur);
+ }
+ }
+ }
+ break;
+ case NODE_TEST_NS: {
+ TODO;
+ break;
+ }
+ case NODE_TEST_NAME:
+ switch (cur->type) {
+ case XML_ELEMENT_NODE:
+ if (xmlStrEqual(name, cur->name)) {
+ if (prefix == NULL) {
+ if ((cur->ns == NULL) ||
+ (cur->ns->prefix == NULL)) {
+#ifdef DEBUG_STEP
+ n++;
+#endif
+ addNode(list, cur);
+ }
+ } else {
+ if ((cur->ns != NULL) &&
+ (xmlStrEqual(prefix,
+ cur->ns->href))) {
+#ifdef DEBUG_STEP
+ n++;
+#endif
+ addNode(list, cur);
+ }
+ }
+ }
+ break;
+ case XML_ATTRIBUTE_NODE: {
+ xmlAttrPtr attr = (xmlAttrPtr) cur;
+ if (xmlStrEqual(name, attr->name)) {
+ if (prefix == NULL) {
+ if ((attr->ns == NULL) ||
+ (attr->ns->prefix == NULL)) {
+#ifdef DEBUG_STEP
+ n++;
+#endif
+ addNode(list, (xmlNodePtr) attr);
+ }
+ } else {
+ if ((attr->ns != NULL) &&
+ (xmlStrEqual(prefix,
+ attr->ns->href))) {
+#ifdef DEBUG_STEP
+ n++;
+#endif
+ addNode(list, (xmlNodePtr) attr);
+ }
+ }
+ }
+ break;
+ }
+ case XML_NAMESPACE_DECL: {
+ TODO;
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+ }
+ } while (cur != NULL);
+
+ /*
+ * If there is some predicate filtering do it now
+ */
+ if (op->ch2 != -1) {
+ xmlXPathObjectPtr obj2;
+
+ valuePush(ctxt, xmlXPathWrapNodeSet(list));
+ xmlXPathCompOpEval(ctxt, &ctxt->comp->steps[op->ch2]);
+ CHECK_TYPE(XPATH_NODESET);
+ obj2 = valuePop(ctxt);
+ list = obj2->nodesetval;
+ obj2->nodesetval = NULL;
+ xmlXPathFreeObject(obj2);
+ }
+ if (ret == NULL) {
+ ret = list;
+ } else {
+ ret = xmlXPathNodeSetMerge(ret, list);
+ xmlXPathFreeNodeSet(list);
+ }
+ }
+ ctxt->context->node = tmp;
+#ifdef DEBUG_STEP
+ xmlGenericError(xmlGenericErrorContext,
+ "\nExamined %d nodes, found %d nodes at that step\n", t, n);
+#endif
+ xmlXPathFreeObject(obj);
+ valuePush(ctxt, xmlXPathWrapNodeSet(ret));
+}
+
/**
* xmlXPathCompOpEval:
* @ctxt: the XPath parser context with the compiled expression
@@ -6929,12 +6982,14 @@
xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
ctxt->context->node = NULL;
return;
- case XPATH_OP_COLLECT:
- if (op->ch1 != -1)
- xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
- xmlXPathNodeCollectAndTest(ctxt, op->value, op->value2,
- op->value3, op->value4, op->value5);
+ case XPATH_OP_COLLECT: {
+ if (op->ch1 == -1)
+ return;
+
+ xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
+ xmlXPathNodeCollectAndTest(ctxt, op);
return;
+ }
case XPATH_OP_VALUE:
valuePush(ctxt,
xmlXPathObjectCopy((xmlXPathObjectPtr) op->value4));
@@ -6995,7 +7050,8 @@
if (op->ch2 != -1)
xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
return;
- case XPATH_OP_PREDICATE: {
+ case XPATH_OP_PREDICATE:
+ case XPATH_OP_FILTER: {
xmlXPathObjectPtr res;
xmlXPathObjectPtr obj, tmp;
xmlNodeSetPtr newset = NULL;
@@ -7315,6 +7371,8 @@
return(res->floatval == ctxt->proximityPosition);
case XPATH_NODESET:
case XPATH_XSLT_TREE:
+ if (res->nodesetval == NULL)
+ return(0);
return(res->nodesetval->nodeNr != 0);
case XPATH_STRING:
return((res->stringval != NULL) &&