mirror of
https://github.com/GNOME/libxml2.git
synced 2025-02-23 18:29:14 +08:00
added a more convenient extension API for value and context managing Now
* include/libxml/xpath{,Internals}.h xpath.c: added a more convenient extension API for value and context managing Now handles external objects through xmlXPathPopExternal, xmlXPathWrapExternal and xmlXPathReturnExternal. Added functions for sets operations (intersection, etc.)
This commit is contained in:
parent
220907319a
commit
f06a3d8b53
10
ChangeLog
10
ChangeLog
@ -1,3 +1,11 @@
|
||||
Mon Jul 16 06:32:44 CEST 2001 Thomas Broyer <tbroyer@ltgt.net>
|
||||
|
||||
* include/libxml/xpath{,Internals}.h xpath.c: added a more
|
||||
convenient extension API for value and context managing
|
||||
Now handles external objects through xmlXPathPopExternal,
|
||||
xmlXPathWrapExternal and xmlXPathReturnExternal.
|
||||
Added functions for sets operations (intersection, etc.)
|
||||
|
||||
Mon Jul 16 20:05:27 CEST 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
|
||||
|
||||
* include/libxml/parserInternals.h include/libxml/HTMLparser.h
|
||||
@ -5,7 +13,7 @@ Mon Jul 16 20:05:27 CEST 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
|
||||
HTMLparser.c: cleanup of global variables, marking some
|
||||
const or private.
|
||||
|
||||
Sun Jul 16 00:17:15 CEST 2001 Thomas Broyer <tbroyer@ltgt.net>
|
||||
Mon Jul 16 00:17:15 CEST 2001 Thomas Broyer <tbroyer@ltgt.net>
|
||||
|
||||
* include/libxml/xpath.h: exported xmlXPath{NAN,PINF,NINF}
|
||||
fixed xmlXPathNodeSetItem when passing index=0
|
||||
|
@ -288,12 +288,40 @@ LIBXML_DLL_IMPORT extern double xmlXPathPINF;
|
||||
LIBXML_DLL_IMPORT extern double xmlXPathNINF;
|
||||
|
||||
/* These macros may later turn into functions */
|
||||
/**
|
||||
* xmlXPathNodeSetGetLength:
|
||||
* @ns: a node-set
|
||||
*
|
||||
* Implement a functionnality similar to the DOM NodeList.length
|
||||
*
|
||||
* Returns the number of nodes in the node-set.
|
||||
*/
|
||||
#define xmlXPathNodeSetGetLength(ns) ((ns) ? (ns)->nodeNr : 0)
|
||||
/**
|
||||
* xmlXPathNodeSetItem:
|
||||
* @ns: a node-set
|
||||
* @index: index of a node in the set
|
||||
*
|
||||
* Implements a functionnality similar to the DOM NodeList.item()
|
||||
*
|
||||
* Returns the xmlNodePtr at the given @index in @ns or NULL if
|
||||
* @index is out of range (0 to length-1)
|
||||
*/
|
||||
#define xmlXPathNodeSetItem(ns, index) \
|
||||
((((ns) != NULL) && \
|
||||
((index) >= 0) && ((index) < (ns)->nodeNr)) ? \
|
||||
(ns)->nodeTab[(index)] \
|
||||
: NULL)
|
||||
/**
|
||||
* xmlXPathNodeSetIsEmpty:
|
||||
* @ns: a node-set
|
||||
*
|
||||
* Checks whether @ns is empty or not
|
||||
*
|
||||
* Returns %TRUE if @ns is an empty node-set
|
||||
*/
|
||||
#define xmlXPathNodeSetIsEmpty(ns) \
|
||||
(((ns) == NULL) || ((ns)->nodeNr == 0) || ((ns)->nodeTab == NULL))
|
||||
|
||||
|
||||
void xmlXPathFreeObject (xmlXPathObjectPtr obj);
|
||||
|
@ -27,6 +27,173 @@ extern "C" {
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* Many of these macros may later turn into functions. They
|
||||
* shouldn't be used in #ifdef's preprocessor instructions.
|
||||
*/
|
||||
/**
|
||||
* xmlXPathSetError:
|
||||
* @ctxt: an XPath parser context
|
||||
* @err: an xmlXPathError code
|
||||
*
|
||||
* Raises an error.
|
||||
*/
|
||||
#define xmlXPathSetError(ctxt, err) \
|
||||
{ xmlXPatherror((ctxt), __FILE__, __LINE__, (err)); \
|
||||
(ctxt)->error = (err); }
|
||||
/**
|
||||
* xmlXPathSetArityError:
|
||||
* @ctxt: an XPath parser context
|
||||
*
|
||||
* Raises an XPATH_INVALID_ARITY error
|
||||
*/
|
||||
#define xmlXPathSetArityError(ctxt) \
|
||||
xmlXPathSetError((ctxt), XPATH_INVALID_ARITY)
|
||||
/**
|
||||
* xmlXPathSetTypeError:
|
||||
* @ctxt: an XPath parser context
|
||||
*
|
||||
* Raises an XPATH_INVALID_TYPE error
|
||||
*/
|
||||
#define xmlXPathSetTypeError(ctxt) \
|
||||
xmlXPathSetError((ctxt), XPATH_INVALID_TYPE)
|
||||
/**
|
||||
* xmlXPathGetError:
|
||||
* @ctxt: an XPath parser context
|
||||
*
|
||||
* Returns the context error
|
||||
*/
|
||||
#define xmlXPathGetError(ctxt) ((ctxt)->error)
|
||||
/**
|
||||
* xmlXPathCheckError:
|
||||
* @ctxt: an XPath parser context
|
||||
*
|
||||
* Returns true if an error has been raised, false otherwise.
|
||||
*/
|
||||
#define xmlXPathCheckError(ctxt) ((ctxt)->error != XPATH_EXPRESSION_OK)
|
||||
|
||||
/**
|
||||
* xmlXPathGetDocument:
|
||||
* @ctxt: an XPath parser context
|
||||
*
|
||||
* Returns the context document
|
||||
*/
|
||||
#define xmlXPathGetDocument(ctxt) ((ctxt)->context->doc)
|
||||
/**
|
||||
* xmlXPathGetContextNode:
|
||||
* @ctxt: an XPath parser context
|
||||
*
|
||||
* Returns the context node
|
||||
*/
|
||||
#define xmlXPathGetContextNode(ctxt) ((ctxt)->context->node)
|
||||
|
||||
int xmlXPathPopBoolean (xmlXPathParserContextPtr ctxt);
|
||||
double xmlXPathPopNumber (xmlXPathParserContextPtr ctxt);
|
||||
xmlChar * xmlXPathPopString (xmlXPathParserContextPtr ctxt);
|
||||
xmlNodeSetPtr xmlXPathPopNodeSet (xmlXPathParserContextPtr ctxt);
|
||||
void * xmlXPathPopExternal (xmlXPathParserContextPtr ctxt);
|
||||
|
||||
/**
|
||||
* xmlXPathReturnBoolean:
|
||||
* @ctxt: an XPath parser context
|
||||
* @val: a boolean
|
||||
*
|
||||
* Pushes the boolean @val on the context stack
|
||||
*/
|
||||
#define xmlXPathReturnBoolean(ctxt, val) \
|
||||
valuePush((ctxt), xmlXPathNewBoolean(val))
|
||||
/**
|
||||
* xmlXPathReturnTrue:
|
||||
* @ctxt: an XPath parser context
|
||||
*
|
||||
* Pushes true on the context stack
|
||||
*/
|
||||
#define xmlXPathReturnTrue(ctxt) xmlXPathReturnBoolean((ctxt), 1)
|
||||
/**
|
||||
* xmlXPathReturnFalse:
|
||||
* @ctxt: an XPath parser context
|
||||
*
|
||||
* Pushes false on the context stack
|
||||
*/
|
||||
#define xmlXPathReturnFalse(ctxt) xmlXPathReturnBoolean((ctxt), 0)
|
||||
/**
|
||||
* xmlXPathReturnNumber:
|
||||
* @ctxt: an XPath parser context
|
||||
* @val: a double
|
||||
*
|
||||
* Pushes the double @val on the context stack
|
||||
*/
|
||||
#define xmlXPathReturnNumber(ctxt, val) \
|
||||
valuePush((ctxt), xmlXPathNewFloat(val))
|
||||
/**
|
||||
* xmlXPathReturnString:
|
||||
* @ctxt: an XPath parser context
|
||||
* @str: a string
|
||||
*
|
||||
* Pushes the string @str on the context stack
|
||||
*/
|
||||
#define xmlXPathReturnString(ctxt, str) \
|
||||
valuePush((ctxt), xmlXPathWrapString(str))
|
||||
/**
|
||||
* xmlXPathReturnEmptyString:
|
||||
* @ctxt: an XPath parser context
|
||||
*
|
||||
* Pushes an empty string on the stack
|
||||
*/
|
||||
#define xmlXPathReturnEmptyString(ctxt) \
|
||||
valuePush((ctxt), xmlXPathNewCString(""))
|
||||
/**
|
||||
* xmlXPathReturnNodeSet:
|
||||
* @ctxt: an XPath parser context
|
||||
* @ns: a node-set
|
||||
*
|
||||
* Pushes the node-set @ns on the context stack
|
||||
*/
|
||||
#define xmlXPathReturnNodeSet(ctxt, ns) \
|
||||
valuePush((ctxt), xmlXPathWrapNodeSet(ns))
|
||||
/**
|
||||
* xmlXPathReturnEmptyNodeSet:
|
||||
* @ctxt: an XPath parser context
|
||||
*
|
||||
* Pushes an empty node-set on the context stack
|
||||
*/
|
||||
#define xmlXPathReturnEmptyNodeSet(ctxt, ns) \
|
||||
valuePush((ctxt), xmlXPathNewNodeSet(NULL))
|
||||
/**
|
||||
* xmlXPathReturnExternal:
|
||||
* @ctxt: an XPath parser context
|
||||
* @val: user data
|
||||
*
|
||||
* Pushes user data on the context stack
|
||||
*/
|
||||
#define xmlXPathReturnExternal(ctxt, val) \
|
||||
valuePush((ctxt), xmlXPathWrapExternal(val))
|
||||
|
||||
/**
|
||||
* xmlXPathStackIsNodeSet:
|
||||
* @ctxt: an XPath parser context
|
||||
*
|
||||
* Returns true if the current object on the stack is a node-set
|
||||
*/
|
||||
#define xmlXPathStackIsNodeSet(ctxt) \
|
||||
(((ctxt)->value != NULL) \
|
||||
&& (((ctxt)->value->type == XPATH_NODESET) \
|
||||
|| ((ctxt)->value->type == XPATH_XSLT_TREE)))
|
||||
|
||||
/**
|
||||
* xmlXPathEmptyNodeSet:
|
||||
* @ns: a node-set
|
||||
*
|
||||
* Empties a node-set
|
||||
*/
|
||||
#define xmlXPathEmptyNodeSet(ns) \
|
||||
{ while ((ns)->nodeNr > 0) (ns)->nodeTab[(ns)->nodeNr--] = NULL; }
|
||||
|
||||
/**
|
||||
* These macros shouldn't be used anymore. Prefer above functions
|
||||
* and macros.
|
||||
*/
|
||||
|
||||
/**
|
||||
* CHECK_ERROR:
|
||||
*
|
||||
@ -123,7 +290,7 @@ extern "C" {
|
||||
xmlXPathBooleanFunction(ctxt, 1);
|
||||
|
||||
/*
|
||||
* Varibale Lookup forwarding
|
||||
* Variable Lookup forwarding
|
||||
*/
|
||||
typedef xmlXPathObjectPtr
|
||||
(*xmlXPathVariableLookupFunc) (void *ctxt,
|
||||
@ -148,6 +315,40 @@ void xmlXPathDebugDumpObject (FILE *output,
|
||||
void xmlXPathDebugDumpCompExpr(FILE *output,
|
||||
xmlXPathCompExprPtr comp,
|
||||
int depth);
|
||||
|
||||
/**
|
||||
* NodeSet handling
|
||||
*/
|
||||
xmlNodeSetPtr xmlXPathDifference (xmlNodeSetPtr nodes1,
|
||||
xmlNodeSetPtr nodes2);
|
||||
xmlNodeSetPtr xmlXPathIntersection (xmlNodeSetPtr nodes1,
|
||||
xmlNodeSetPtr nodes2);
|
||||
|
||||
xmlNodeSetPtr xmlXPathDistinctSorted (xmlNodeSetPtr nodes);
|
||||
xmlNodeSetPtr xmlXPathDistinct (xmlNodeSetPtr nodes);
|
||||
|
||||
int xmlXPathHasSameNodes (xmlNodeSetPtr nodes1,
|
||||
xmlNodeSetPtr nodes2);
|
||||
|
||||
xmlNodeSetPtr xmlXPathNodeLeadingSorted (xmlNodeSetPtr nodes,
|
||||
xmlNodePtr node);
|
||||
xmlNodeSetPtr xmlXPathLeadingSorted (xmlNodeSetPtr nodes1,
|
||||
xmlNodeSetPtr nodes2);
|
||||
xmlNodeSetPtr xmlXPathNodeLeading (xmlNodeSetPtr nodes,
|
||||
xmlNodePtr node);
|
||||
xmlNodeSetPtr xmlXPathLeading (xmlNodeSetPtr nodes1,
|
||||
xmlNodeSetPtr nodes2);
|
||||
|
||||
xmlNodeSetPtr xmlXPathNodeTrailingSorted (xmlNodeSetPtr nodes,
|
||||
xmlNodePtr node);
|
||||
xmlNodeSetPtr xmlXPathTrailingSorted (xmlNodeSetPtr nodes1,
|
||||
xmlNodeSetPtr nodes2);
|
||||
xmlNodeSetPtr xmlXPathNodeTrailing (xmlNodeSetPtr nodes,
|
||||
xmlNodePtr node);
|
||||
xmlNodeSetPtr xmlXPathTrailing (xmlNodeSetPtr nodes1,
|
||||
xmlNodeSetPtr nodes2);
|
||||
|
||||
|
||||
/**
|
||||
* Extending a context
|
||||
*/
|
||||
@ -244,6 +445,7 @@ void xmlXPathFreeNodeSet(xmlNodeSetPtr obj);
|
||||
xmlXPathObjectPtr xmlXPathNewNodeSet(xmlNodePtr val);
|
||||
xmlXPathObjectPtr xmlXPathNewNodeSetList(xmlNodeSetPtr val);
|
||||
xmlXPathObjectPtr xmlXPathWrapNodeSet(xmlNodeSetPtr val);
|
||||
xmlXPathObjectPtr xmlXPathWrapExternal(void *val);
|
||||
void xmlXPathFreeNodeSetList(xmlXPathObjectPtr obj);
|
||||
|
||||
|
||||
|
537
xpath.c
537
xpath.c
@ -941,6 +941,137 @@ extern type name##Pop(xmlXPathParserContextPtr ctxt) { \
|
||||
|
||||
PUSH_AND_POP(xmlXPathObjectPtr, value)
|
||||
|
||||
/**
|
||||
* xmlXPathPopBoolean:
|
||||
* @ctxt: an XPath parser context
|
||||
*
|
||||
* Pops a boolean from the stack, handling conversion if needed.
|
||||
* Check error with #xmlXPathCheckError.
|
||||
*
|
||||
* Returns the boolean
|
||||
*/
|
||||
int
|
||||
xmlXPathPopBoolean (xmlXPathParserContextPtr ctxt) {
|
||||
xmlXPathObjectPtr obj;
|
||||
int ret;
|
||||
|
||||
obj = valuePop(ctxt);
|
||||
if (obj == NULL) {
|
||||
xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
|
||||
return(0);
|
||||
}
|
||||
ret = xmlXPathCastToBoolean(obj);
|
||||
xmlXPathFreeObject(obj);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlXPathPopNumber:
|
||||
* @ctxt: an XPath parser context
|
||||
*
|
||||
* Pops a number from the stack, handling conversion if needed.
|
||||
* Check error with #xmlXPathCheckError.
|
||||
*
|
||||
* Returns the number
|
||||
*/
|
||||
double
|
||||
xmlXPathPopNumber (xmlXPathParserContextPtr ctxt) {
|
||||
xmlXPathObjectPtr obj;
|
||||
double ret;
|
||||
|
||||
obj = valuePop(ctxt);
|
||||
if (obj == NULL) {
|
||||
xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
|
||||
return(0);
|
||||
}
|
||||
ret = xmlXPathCastToNumber(obj);
|
||||
xmlXPathFreeObject(obj);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlXPathPopString:
|
||||
* @ctxt: an XPath parser context
|
||||
*
|
||||
* Pops a string from the stack, handling conversion if needed.
|
||||
* Check error with #xmlXPathCheckError.
|
||||
*
|
||||
* Returns the string
|
||||
*/
|
||||
xmlChar *
|
||||
xmlXPathPopString (xmlXPathParserContextPtr ctxt) {
|
||||
xmlXPathObjectPtr obj;
|
||||
xmlChar * ret;
|
||||
|
||||
obj = valuePop(ctxt);
|
||||
if (obj == NULL) {
|
||||
xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
|
||||
return(NULL);
|
||||
}
|
||||
ret = xmlXPathCastToString(obj);
|
||||
/* TODO: needs refactoring somewhere else */
|
||||
if (obj->stringval == ret)
|
||||
obj->stringval = NULL;
|
||||
xmlXPathFreeObject(obj);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlXPathPopNodeSet:
|
||||
* @ctxt: an XPath parser context
|
||||
*
|
||||
* Pops a node-set from the stack, handling conversion if needed.
|
||||
* Check error with #xmlXPathCheckError.
|
||||
*
|
||||
* Returns the node-set
|
||||
*/
|
||||
xmlNodeSetPtr
|
||||
xmlXPathPopNodeSet (xmlXPathParserContextPtr ctxt) {
|
||||
xmlXPathObjectPtr obj;
|
||||
xmlNodeSetPtr ret;
|
||||
|
||||
if (ctxt->value == NULL) {
|
||||
xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
|
||||
return(NULL);
|
||||
}
|
||||
if (!xmlXPathStackIsNodeSet(ctxt)) {
|
||||
xmlXPathSetTypeError(ctxt);
|
||||
return(NULL);
|
||||
}
|
||||
obj = valuePop(ctxt);
|
||||
ret = obj->nodesetval;
|
||||
xmlXPathFreeNodeSetList(obj);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlXPathPopExternal:
|
||||
* @ctxt: an XPath parser context
|
||||
*
|
||||
* Pops an external oject from the stack, handling conversion if needed.
|
||||
* Check error with #xmlXPathCheckError.
|
||||
*
|
||||
* Returns the object
|
||||
*/
|
||||
void *
|
||||
xmlXPathPopExternal (xmlXPathParserContextPtr ctxt) {
|
||||
xmlXPathObjectPtr obj;
|
||||
void * ret;
|
||||
|
||||
if (ctxt->value == NULL) {
|
||||
xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
|
||||
return(NULL);
|
||||
}
|
||||
if (ctxt->value->type != XPATH_USERS) {
|
||||
xmlXPathSetTypeError(ctxt);
|
||||
return(NULL);
|
||||
}
|
||||
obj = valuePop(ctxt);
|
||||
ret = obj->user;
|
||||
xmlXPathFreeObject(obj);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Macros for accessing the content. Those should be used only by the parser,
|
||||
* and not exported.
|
||||
@ -1120,9 +1251,7 @@ const char *xmlXPathErrorMessages[] = {
|
||||
* @line: the line number
|
||||
* @no: the error number
|
||||
*
|
||||
* Create a new xmlNodeSetPtr of type double and of value @val
|
||||
*
|
||||
* Returns the newly created object.
|
||||
* Formats an error message.
|
||||
*/
|
||||
void
|
||||
xmlXPatherror(xmlXPathParserContextPtr ctxt, const char *file,
|
||||
@ -1320,6 +1449,26 @@ xmlXPathNodeSetCreate(xmlNodePtr val) {
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlXPathNodeSetContains:
|
||||
* @cur: the node-set
|
||||
* @val: the node
|
||||
*
|
||||
* checks whether @cur contains @val
|
||||
*
|
||||
* Returns true (1) if @cur contains @val, false (0) otherwise
|
||||
*/
|
||||
int
|
||||
xmlXPathNodeSetContains (xmlNodeSetPtr cur, xmlNodePtr val) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cur->nodeNr; i++) {
|
||||
if (cur->nodeTab[i] == val)
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlXPathNodeSetAdd:
|
||||
* @cur: the initial node set
|
||||
@ -1724,6 +1873,364 @@ xmlXPathFreeNodeSetList(xmlXPathObjectPtr obj) {
|
||||
xmlFree(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlXPathDifference:
|
||||
* @nodes1: a node-set
|
||||
* @nodes2: a node-set
|
||||
*
|
||||
* Implements the EXSLT - Sets difference() function:
|
||||
* node-set set:difference (node-set, node-set)
|
||||
*
|
||||
* Returns the difference between the two node sets, or nodes1 if
|
||||
* nodes2 is empty
|
||||
*/
|
||||
xmlNodeSetPtr
|
||||
xmlXPathDifference (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
|
||||
xmlNodeSetPtr ret;
|
||||
int i, l1;
|
||||
xmlNodePtr cur;
|
||||
|
||||
if (xmlXPathNodeSetIsEmpty(nodes2))
|
||||
return(nodes1);
|
||||
|
||||
ret = xmlXPathNodeSetCreate(NULL);
|
||||
if (xmlXPathNodeSetIsEmpty(nodes1))
|
||||
return(ret);
|
||||
|
||||
l1 = xmlXPathNodeSetGetLength(nodes1);
|
||||
|
||||
for (i = 0; i < l1; i++) {
|
||||
cur = xmlXPathNodeSetItem(nodes1, i);
|
||||
if (!xmlXPathNodeSetContains(nodes2, cur))
|
||||
xmlXPathNodeSetAddUnique(ret, cur);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlXPathIntersection:
|
||||
* @nodes1: a node-set
|
||||
* @nodes2: a node-set
|
||||
*
|
||||
* Implements the EXSLT - Sets intersection() function:
|
||||
* node-set set:intersection (node-set, node-set)
|
||||
*
|
||||
* Returns a node set comprising the nodes that are within both the
|
||||
* node sets passed as arguments
|
||||
*/
|
||||
xmlNodeSetPtr
|
||||
xmlXPathIntersection (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
|
||||
xmlNodeSetPtr ret = xmlXPathNodeSetCreate(NULL);
|
||||
int i, l1;
|
||||
xmlNodePtr cur;
|
||||
|
||||
if (xmlXPathNodeSetIsEmpty(nodes1))
|
||||
return(ret);
|
||||
if (xmlXPathNodeSetIsEmpty(nodes2))
|
||||
return(ret);
|
||||
|
||||
l1 = xmlXPathNodeSetGetLength(nodes1);
|
||||
|
||||
for (i = 0; i < l1; i++) {
|
||||
cur = xmlXPathNodeSetItem(nodes1, i);
|
||||
if (xmlXPathNodeSetContains(nodes2, cur))
|
||||
xmlXPathNodeSetAddUnique(ret, cur);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlXPathDistinctSorted:
|
||||
* @nodes: a node-set, sorted by document order
|
||||
*
|
||||
* Implements the EXSLT - Sets distinct() function:
|
||||
* node-set set:distinct (node-set)
|
||||
*
|
||||
* Returns a subset of the nodes contained in @nodes, or @nodes if
|
||||
* it is empty
|
||||
*/
|
||||
xmlNodeSetPtr
|
||||
xmlXPathDistinctSorted (xmlNodeSetPtr nodes) {
|
||||
xmlNodeSetPtr ret;
|
||||
xmlHashTablePtr hash;
|
||||
int i, l;
|
||||
xmlChar * strval;
|
||||
xmlNodePtr cur;
|
||||
|
||||
if (xmlXPathNodeSetIsEmpty(nodes))
|
||||
return(nodes);
|
||||
|
||||
ret = xmlXPathNodeSetCreate(NULL);
|
||||
l = xmlXPathNodeSetGetLength(nodes);
|
||||
hash = xmlHashCreate (l);
|
||||
for (i = 0; i < l; i++) {
|
||||
cur = xmlXPathNodeSetItem(nodes, i);
|
||||
strval = xmlXPathCastNodeToString(cur);
|
||||
if (xmlHashLookup(hash, strval) == NULL) {
|
||||
xmlHashAddEntry(hash, strval, strval);
|
||||
xmlXPathNodeSetAddUnique(ret, cur);
|
||||
} else {
|
||||
xmlFree(strval);
|
||||
}
|
||||
}
|
||||
xmlHashFree(hash, (xmlHashDeallocator) xmlFree);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlXPathDistinct:
|
||||
* @nodes: a node-set
|
||||
*
|
||||
* Implements the EXSLT - Sets distinct() function:
|
||||
* node-set set:distinct (node-set)
|
||||
* @nodes is sorted by document order, then #exslSetsDistinctSorted
|
||||
* is called with the sorted node-set
|
||||
*
|
||||
* Returns a subset of the nodes contained in @nodes, or @nodes if
|
||||
* it is empty
|
||||
*/
|
||||
xmlNodeSetPtr
|
||||
xmlXPathDistinct (xmlNodeSetPtr nodes) {
|
||||
if (xmlXPathNodeSetIsEmpty(nodes))
|
||||
return(nodes);
|
||||
|
||||
xmlXPathNodeSetSort(nodes);
|
||||
return(xmlXPathDistinctSorted(nodes));
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlXPathHasSameNodes:
|
||||
* @nodes1: a node-set
|
||||
* @nodes2: a node-set
|
||||
*
|
||||
* Implements the EXSLT - Sets has-same-nodes function:
|
||||
* boolean set:has-same-node(node-set, node-set)
|
||||
*
|
||||
* Returns true (1) if @nodes1 shares any node with @nodes2, false (0)
|
||||
* otherwise
|
||||
*/
|
||||
int
|
||||
xmlXPathHasSameNodes (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
|
||||
int i, l;
|
||||
xmlNodePtr cur;
|
||||
|
||||
if (xmlXPathNodeSetIsEmpty(nodes1) ||
|
||||
xmlXPathNodeSetIsEmpty(nodes2))
|
||||
return(0);
|
||||
|
||||
l = xmlXPathNodeSetGetLength(nodes1);
|
||||
for (i = 0; i < l; i++) {
|
||||
cur = xmlXPathNodeSetItem(nodes1, i);
|
||||
if (xmlXPathNodeSetContains(nodes2, cur))
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlXPathNodeLeadingSorted:
|
||||
* @nodes: a node-set, sorted by document order
|
||||
* @node: a node
|
||||
*
|
||||
* Implements the EXSLT - Sets leading() function:
|
||||
* node-set set:leading (node-set, node-set)
|
||||
*
|
||||
* Returns the nodes in @nodes that precede @node in document order,
|
||||
* @nodes if @node is NULL or an empty node-set if @nodes
|
||||
* doesn't contain @node
|
||||
*/
|
||||
xmlNodeSetPtr
|
||||
xmlXPathNodeLeadingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) {
|
||||
int i, l;
|
||||
xmlNodePtr cur;
|
||||
xmlNodeSetPtr ret;
|
||||
|
||||
if (node == NULL)
|
||||
return(nodes);
|
||||
|
||||
ret = xmlXPathNodeSetCreate(NULL);
|
||||
if (xmlXPathNodeSetIsEmpty(nodes) ||
|
||||
(!xmlXPathNodeSetContains(nodes, node)))
|
||||
return(ret);
|
||||
|
||||
l = xmlXPathNodeSetGetLength(nodes);
|
||||
for (i = 0; i < l; i++) {
|
||||
cur = xmlXPathNodeSetItem(nodes, i);
|
||||
if (cur == node)
|
||||
break;
|
||||
xmlXPathNodeSetAddUnique(ret, cur);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlXPathNodeLeading:
|
||||
* @nodes: a node-set
|
||||
* @node: a node
|
||||
*
|
||||
* Implements the EXSLT - Sets leading() function:
|
||||
* node-set set:leading (node-set, node-set)
|
||||
* @nodes is sorted by document order, then #exslSetsNodeLeadingSorted
|
||||
* is called.
|
||||
*
|
||||
* Returns the nodes in @nodes that precede @node in document order,
|
||||
* @nodes if @node is NULL or an empty node-set if @nodes
|
||||
* doesn't contain @node
|
||||
*/
|
||||
xmlNodeSetPtr
|
||||
xmlXPathNodeLeading (xmlNodeSetPtr nodes, xmlNodePtr node) {
|
||||
xmlXPathNodeSetSort(nodes);
|
||||
return(xmlXPathNodeLeadingSorted(nodes, node));
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlXPathLeadingSorted:
|
||||
* @nodes1: a node-set, sorted by document order
|
||||
* @nodes2: a node-set, sorted by document order
|
||||
*
|
||||
* Implements the EXSLT - Sets leading() function:
|
||||
* node-set set:leading (node-set, node-set)
|
||||
*
|
||||
* Returns the nodes in @nodes1 that precede the first node in @nodes2
|
||||
* in document order, @nodes1 if @nodes2 is NULL or empty or
|
||||
* an empty node-set if @nodes1 doesn't contain @nodes2
|
||||
*/
|
||||
xmlNodeSetPtr
|
||||
xmlXPathLeadingSorted (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
|
||||
if (xmlXPathNodeSetIsEmpty(nodes2))
|
||||
return(nodes1);
|
||||
return(xmlXPathNodeLeadingSorted(nodes1,
|
||||
xmlXPathNodeSetItem(nodes2, 1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlXPathLeading:
|
||||
* @nodes1: a node-set
|
||||
* @nodes2: a node-set
|
||||
*
|
||||
* Implements the EXSLT - Sets leading() function:
|
||||
* node-set set:leading (node-set, node-set)
|
||||
* @nodes1 and @nodes2 are sorted by document order, then
|
||||
* #exslSetsLeadingSorted is called.
|
||||
*
|
||||
* Returns the nodes in @nodes1 that precede the first node in @nodes2
|
||||
* in document order, @nodes1 if @nodes2 is NULL or empty or
|
||||
* an empty node-set if @nodes1 doesn't contain @nodes2
|
||||
*/
|
||||
xmlNodeSetPtr
|
||||
xmlXPathLeading (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
|
||||
if (xmlXPathNodeSetIsEmpty(nodes2))
|
||||
return(nodes1);
|
||||
if (xmlXPathNodeSetIsEmpty(nodes1))
|
||||
return(xmlXPathNodeSetCreate(NULL));
|
||||
xmlXPathNodeSetSort(nodes1);
|
||||
xmlXPathNodeSetSort(nodes2);
|
||||
return(xmlXPathNodeLeadingSorted(nodes1,
|
||||
xmlXPathNodeSetItem(nodes2, 1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlXPathNodeTrailingSorted:
|
||||
* @nodes: a node-set, sorted by document order
|
||||
* @node: a node
|
||||
*
|
||||
* Implements the EXSLT - Sets trailing() function:
|
||||
* node-set set:trailing (node-set, node-set)
|
||||
*
|
||||
* Returns the nodes in @nodes that follow @node in document order,
|
||||
* @nodes if @node is NULL or an empty node-set if @nodes
|
||||
* doesn't contain @node
|
||||
*/
|
||||
xmlNodeSetPtr
|
||||
xmlXPathNodeTrailingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) {
|
||||
int i, l;
|
||||
xmlNodePtr cur;
|
||||
xmlNodeSetPtr ret;
|
||||
|
||||
if (node == NULL)
|
||||
return(nodes);
|
||||
|
||||
ret = xmlXPathNodeSetCreate(NULL);
|
||||
if (xmlXPathNodeSetIsEmpty(nodes) ||
|
||||
(!xmlXPathNodeSetContains(nodes, node)))
|
||||
return(ret);
|
||||
|
||||
l = xmlXPathNodeSetGetLength(nodes);
|
||||
for (i = 0; i < l; i++) {
|
||||
cur = xmlXPathNodeSetItem(nodes, i);
|
||||
if (cur == node)
|
||||
break;
|
||||
xmlXPathNodeSetAddUnique(ret, cur);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlXPathNodeTrailing:
|
||||
* @nodes: a node-set
|
||||
* @node: a node
|
||||
*
|
||||
* Implements the EXSLT - Sets trailing() function:
|
||||
* node-set set:trailing (node-set, node-set)
|
||||
* @nodes is sorted by document order, then #xmlXPathNodeTrailingSorted
|
||||
* is called.
|
||||
*
|
||||
* Returns the nodes in @nodes that follow @node in document order,
|
||||
* @nodes if @node is NULL or an empty node-set if @nodes
|
||||
* doesn't contain @node
|
||||
*/
|
||||
xmlNodeSetPtr
|
||||
xmlXPathNodeTrailing (xmlNodeSetPtr nodes, xmlNodePtr node) {
|
||||
xmlXPathNodeSetSort(nodes);
|
||||
return(xmlXPathNodeTrailingSorted(nodes, node));
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlXPathTrailingSorted:
|
||||
* @nodes1: a node-set, sorted by document order
|
||||
* @nodes2: a node-set, sorted by document order
|
||||
*
|
||||
* Implements the EXSLT - Sets trailing() function:
|
||||
* node-set set:trailing (node-set, node-set)
|
||||
*
|
||||
* Returns the nodes in @nodes1 that follow the first node in @nodes2
|
||||
* in document order, @nodes1 if @nodes2 is NULL or empty or
|
||||
* an empty node-set if @nodes1 doesn't contain @nodes2
|
||||
*/
|
||||
xmlNodeSetPtr
|
||||
xmlXPathTrailingSorted (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
|
||||
if (xmlXPathNodeSetIsEmpty(nodes2))
|
||||
return(nodes1);
|
||||
return(xmlXPathNodeTrailingSorted(nodes1,
|
||||
xmlXPathNodeSetItem(nodes2, 0)));
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlXPathTrailing:
|
||||
* @nodes1: a node-set
|
||||
* @nodes2: a node-set
|
||||
*
|
||||
* Implements the EXSLT - Sets trailing() function:
|
||||
* node-set set:trailing (node-set, node-set)
|
||||
* @nodes1 and @nodes2 are sorted by document order, then
|
||||
* #xmlXPathTrailingSorted is called.
|
||||
*
|
||||
* Returns the nodes in @nodes1 that follow the first node in @nodes2
|
||||
* in document order, @nodes1 if @nodes2 is NULL or empty or
|
||||
* an empty node-set if @nodes1 doesn't contain @nodes2
|
||||
*/
|
||||
xmlNodeSetPtr
|
||||
xmlXPathTrailing (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
|
||||
if (xmlXPathNodeSetIsEmpty(nodes2))
|
||||
return(nodes1);
|
||||
if (xmlXPathNodeSetIsEmpty(nodes1))
|
||||
return(xmlXPathNodeSetCreate(NULL));
|
||||
xmlXPathNodeSetSort(nodes1);
|
||||
xmlXPathNodeSetSort(nodes2);
|
||||
return(xmlXPathNodeTrailingSorted(nodes1,
|
||||
xmlXPathNodeSetItem(nodes2, 0)));
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* *
|
||||
* Routines to handle extra functions *
|
||||
@ -2191,6 +2698,30 @@ xmlXPathWrapCString (char * val) {
|
||||
return(xmlXPathWrapString((xmlChar *)(val)));
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlXPathWrapExternal:
|
||||
* @val: the user data
|
||||
*
|
||||
* Wraps the @val data into an XPath object.
|
||||
*
|
||||
* Returns the newly created object.
|
||||
*/
|
||||
xmlXPathObjectPtr
|
||||
xmlXPathWrapExternal (void *val) {
|
||||
xmlXPathObjectPtr ret;
|
||||
|
||||
ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
|
||||
if (ret == NULL) {
|
||||
xmlGenericError(xmlGenericErrorContext,
|
||||
"xmlXPathWrapString: out of memory\n");
|
||||
return(NULL);
|
||||
}
|
||||
memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
|
||||
ret->type = XPATH_USERS;
|
||||
ret->user = val;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlXPathObjectCopy:
|
||||
* @val: the original object
|
||||
|
Loading…
Reference in New Issue
Block a user