📄 xpointer.c
字号:
if (list == NULL)
list = tmp;
else {
if (last != NULL)
xmlAddNextSibling(last, tmp);
else
xmlAddChild(parent, tmp);
}
last = NULL;
parent = tmp;
if (index2 > 1) {
end = xmlXPtrGetNthChild(cur, index2 - 1);
index2 = 0;
}
if ((cur == start) && (index1 > 1)) {
cur = xmlXPtrGetNthChild(cur, index1 - 1);
index1 = 0;
} else {
cur = cur->children;
}
/*
* Now gather the remaining nodes from cur to end
*/
continue; /* while */
}
} else if ((cur == start) &&
(list == NULL) /* looks superfluous but ... */ ) {
if ((cur->type == XML_TEXT_NODE) ||
(cur->type == XML_CDATA_SECTION_NODE)) {
const xmlChar *content = cur->content;
if (content == NULL) {
tmp = xmlNewTextLen(NULL, 0);
} else {
if (index1 > 1) {
content += (index1 - 1);
}
tmp = xmlNewText(content);
}
last = list = tmp;
} else {
if ((cur == start) && (index1 > 1)) {
tmp = xmlCopyNode(cur, 0);
list = tmp;
parent = tmp;
last = NULL;
cur = xmlXPtrGetNthChild(cur, index1 - 1);
index1 = 0;
/*
* Now gather the remaining nodes from cur to end
*/
continue; /* while */
}
tmp = xmlCopyNode(cur, 1);
list = tmp;
parent = NULL;
last = tmp;
}
} else {
tmp = NULL;
switch (cur->type) {
case XML_DTD_NODE:
case XML_ELEMENT_DECL:
case XML_ATTRIBUTE_DECL:
case XML_ENTITY_NODE:
/* Do not copy DTD informations */
break;
case XML_ENTITY_DECL:
TODO /* handle crossing entities -> stack needed */
break;
case XML_XINCLUDE_START:
case XML_XINCLUDE_END:
/* don't consider it part of the tree content */
break;
case XML_ATTRIBUTE_NODE:
/* Humm, should not happen ! */
STRANGE
break;
default:
tmp = xmlCopyNode(cur, 1);
break;
}
if (tmp != NULL) {
if ((list == NULL) || ((last == NULL) && (parent == NULL))) {
STRANGE
return(NULL);
}
if (last != NULL)
xmlAddNextSibling(last, tmp);
else {
xmlAddChild(parent, tmp);
last = tmp;
}
}
}
/*
* Skip to next node in document order
*/
if ((list == NULL) || ((last == NULL) && (parent == NULL))) {
STRANGE
return(NULL);
}
cur = xmlXPtrAdvanceNode(cur, NULL);
}
return(list);
}
/**
* xmlXPtrBuildNodeList:
* @obj: the XPointer result from the evaluation.
*
* Build a node list tree copy of the XPointer result.
* This will drop Attributes and Namespace declarations.
*
* Returns an xmlNodePtr list or NULL.
* the caller has to free the node tree.
*/
xmlNodePtr
xmlXPtrBuildNodeList(xmlXPathObjectPtr obj) {
xmlNodePtr list = NULL, last = NULL;
int i;
if (obj == NULL)
return(NULL);
switch (obj->type) {
case XPATH_NODESET: {
xmlNodeSetPtr set = obj->nodesetval;
if (set == NULL)
return(NULL);
for (i = 0;i < set->nodeNr;i++) {
if (set->nodeTab[i] == NULL)
continue;
switch (set->nodeTab[i]->type) {
case XML_TEXT_NODE:
case XML_CDATA_SECTION_NODE:
case XML_ELEMENT_NODE:
case XML_ENTITY_REF_NODE:
case XML_ENTITY_NODE:
case XML_PI_NODE:
case XML_COMMENT_NODE:
case XML_DOCUMENT_NODE:
case XML_HTML_DOCUMENT_NODE:
#ifdef LIBXML_DOCB_ENABLED
case XML_DOCB_DOCUMENT_NODE:
#endif
case XML_XINCLUDE_START:
case XML_XINCLUDE_END:
break;
case XML_ATTRIBUTE_NODE:
case XML_NAMESPACE_DECL:
case XML_DOCUMENT_TYPE_NODE:
case XML_DOCUMENT_FRAG_NODE:
case XML_NOTATION_NODE:
case XML_DTD_NODE:
case XML_ELEMENT_DECL:
case XML_ATTRIBUTE_DECL:
case XML_ENTITY_DECL:
continue; /* for */
}
if (last == NULL)
list = last = xmlCopyNode(set->nodeTab[i], 1);
else {
xmlAddNextSibling(last, xmlCopyNode(set->nodeTab[i], 1));
if (last->next != NULL)
last = last->next;
}
}
break;
}
case XPATH_LOCATIONSET: {
xmlLocationSetPtr set = (xmlLocationSetPtr) obj->user;
if (set == NULL)
return(NULL);
for (i = 0;i < set->locNr;i++) {
if (last == NULL)
list = last = xmlXPtrBuildNodeList(set->locTab[i]);
else
xmlAddNextSibling(last,
xmlXPtrBuildNodeList(set->locTab[i]));
if (last != NULL) {
while (last->next != NULL)
last = last->next;
}
}
break;
}
case XPATH_RANGE:
return(xmlXPtrBuildRangeNodeList(obj));
case XPATH_POINT:
return(xmlCopyNode(obj->user, 0));
default:
break;
}
return(list);
}
/************************************************************************
* *
* XPointer functions *
* *
************************************************************************/
/**
* xmlXPtrNbLocChildren:
* @node: an xmlNodePtr
*
* Count the number of location children of @node or the length of the
* string value in case of text/PI/Comments nodes
*
* Returns the number of location children
*/
static int
xmlXPtrNbLocChildren(xmlNodePtr node) {
int ret = 0;
if (node == NULL)
return(-1);
switch (node->type) {
case XML_HTML_DOCUMENT_NODE:
case XML_DOCUMENT_NODE:
case XML_ELEMENT_NODE:
node = node->children;
while (node != NULL) {
if (node->type == XML_ELEMENT_NODE)
ret++;
node = node->next;
}
break;
case XML_ATTRIBUTE_NODE:
return(-1);
case XML_PI_NODE:
case XML_COMMENT_NODE:
case XML_TEXT_NODE:
case XML_CDATA_SECTION_NODE:
case XML_ENTITY_REF_NODE:
ret = xmlStrlen(node->content);
break;
default:
return(-1);
}
return(ret);
}
/**
* xmlXPtrHereFunction:
* @ctxt: the XPointer Parser context
* @nargs: the number of args
*
* Function implementing here() operation
* as described in 5.4.3
*/
void
xmlXPtrHereFunction(xmlXPathParserContextPtr ctxt, int nargs) {
CHECK_ARITY(0);
if (ctxt->context->here == NULL)
XP_ERROR(XPTR_SYNTAX_ERROR);
valuePush(ctxt, xmlXPtrNewLocationSetNodes(ctxt->context->here, NULL));
}
/**
* xmlXPtrOriginFunction:
* @ctxt: the XPointer Parser context
* @nargs: the number of args
*
* Function implementing origin() operation
* as described in 5.4.3
*/
void
xmlXPtrOriginFunction(xmlXPathParserContextPtr ctxt, int nargs) {
CHECK_ARITY(0);
if (ctxt->context->origin == NULL)
XP_ERROR(XPTR_SYNTAX_ERROR);
valuePush(ctxt, xmlXPtrNewLocationSetNodes(ctxt->context->origin, NULL));
}
/**
* xmlXPtrStartPointFunction:
* @ctxt: the XPointer Parser context
* @nargs: the number of args
*
* Function implementing start-point() operation
* as described in 5.4.3
* ----------------
* location-set start-point(location-set)
*
* For each location x in the argument location-set, start-point adds a
* location of type point to the result location-set. That point represents
* the start point of location x and is determined by the following rules:
*
* - If x is of type point, the start point is x.
* - If x is of type range, the start point is the start point of x.
* - If x is of type root, element, text, comment, or processing instruction,
* - the container node of the start point is x and the index is 0.
* - If x is of type attribute or namespace, the function must signal a
* syntax error.
* ----------------
*
*/
void
xmlXPtrStartPointFunction(xmlXPathParserContextPtr ctxt, int nargs) {
xmlXPathObjectPtr tmp, obj, point;
xmlLocationSetPtr newset = NULL;
xmlLocationSetPtr oldset = NULL;
CHECK_ARITY(1);
if ((ctxt->value == NULL) ||
((ctxt->value->type != XPATH_LOCATIONSET) &&
(ctxt->value->type != XPATH_NODESET)))
XP_ERROR(XPATH_INVALID_TYPE)
obj = valuePop(ctxt);
if (obj->type == XPATH_NODESET) {
/*
* First convert to a location set
*/
tmp = xmlXPtrNewLocationSetNodeSet(obj->nodesetval);
xmlXPathFreeObject(obj);
obj = tmp;
}
newset = xmlXPtrLocationSetCreate(NULL);
if (newset == NULL) {
xmlXPathFreeObject(obj);
XP_ERROR(XPATH_MEMORY_ERROR);
}
oldset = (xmlLocationSetPtr) obj->user;
if (oldset != NULL) {
int i;
for (i = 0; i < oldset->locNr; i++) {
tmp = oldset->locTab[i];
if (tmp == NULL)
continue;
point = NULL;
switch (tmp->type) {
case XPATH_POINT:
point = xmlXPtrNewPoint(tmp->user, tmp->index);
break;
case XPATH_RANGE: {
xmlNodePtr node = tmp->user;
if (node != NULL) {
if (node->type == XML_ATTRIBUTE_NODE) {
/* TODO: Namespace Nodes ??? */
xmlXPathFreeObject(obj);
xmlXPtrFreeLocationSet(newset);
XP_ERROR(XPTR_SYNTAX_ERROR);
}
point = xmlXPtrNewPoint(node, tmp->index);
}
break;
}
default:
/*** Should we raise an error ?
xmlXPathFreeObject(obj);
xmlXPathFreeObject(newset);
XP_ERROR(XPATH_INVALID_TYPE)
***/
break;
}
if (point != NULL)
xmlXPtrLocationSetAdd(newset, point);
}
}
xmlXPathFreeObject(obj);
valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
}
/**
* xmlXPtrEndPointFunction:
* @ctxt: the XPointer Parser context
* @nargs: the number of args
*
* Function implementing end-point() operation
* as described in 5.4.3
* ----------------------------
* location-set end-point(location-set)
*
* For each location x in the argument location-set, end-point adds a
* location of type point to the result location-set. That point represents
* the end point of location x and is determined by the following rules:
*
* - If x is of type point, the resulting point is x.
* - If x is of type range, the resulting point is the end point of x.
* - If x is of type root or element, the container node of the resulting
* point is x and the index is the number of location children of x.
* - If x is of type text, comment, or processing instruction, the container
* node of the resulting point is x and the index is the length of the
* string-value of x.
* - If x is of type attribute or namespace, the function must signal a
* syntax error.
* ----------------------------
*/
void
xmlXPtrEndPointFunction(xmlXPathParserContextPtr ctxt, int nargs) {
xmlXPathObjectPtr tmp, obj, point;
xmlLocationSetPtr newset = NULL;
xmlLocationSetPtr oldset = NULL;
CHECK_ARITY(1);
if ((ctxt->value == NULL) ||
((ctxt->value->type != XPATH_LOCATIONSET) &&
(ctxt->value->type != XPATH_NODESET)))
XP_ERROR(XPATH_INVALID_TYPE)
obj = valuePop(ctxt);
if (obj->type == XPATH_NODESET) {
/*
* First convert to a location set
*/
tmp = xmlXPtrNewLocationSetNodeSet(obj->nodesetval);
xmlXPathFreeObject(obj);
obj = tmp;
}
newset = xmlXPtrLocationSetCreate(NULL);
oldset = (xmlLocationSetPtr) obj->user;
if (oldset != NULL) {
int i;
for (i = 0; i < oldset->locNr; i++) {
tmp = oldset->locTab[i];
if (tmp == NULL)
continue;
point = NULL;
switch (tmp->type) {
case XPATH_POINT:
point = xmlXPtrNewPoint(tmp->user, tmp->index);
break;
case XPATH_RANGE: {
xmlNodePtr node = tmp->user2;
if (node != NULL) {
if (node->type == XML_ATTRIBUTE_NODE) {
/* TODO: Namespace Nodes ??? */
xmlXPathFreeObject(obj);
xmlXPtrFreeLocationSet(newset);
XP_ERROR(XPTR_SYNTAX_ERROR);
}
point = xmlXPtrNewPoint(node, tmp->index2);
} else if (tmp->user == NULL) {
point = xmlXPtrNewPoint(node,
xmlXPtrNbLocChildren(node));
}
break;
}
default:
/*** Should we raise an error ?
xmlXPathFreeObject(obj);
xmlXPathFreeObject(newset);
XP_ERROR(XPATH_INVALID_TYPE)
***/
break;
}
if (point != NULL)
xmlXPtrLocationSetAdd(newset, point);
}
}
xmlXPathFreeObject(obj);
valuePush(ctxt, xmlXPtrWrapLocationSet(newset));
}
/**
* xmlXPtrCoveringRange:
* @ctxt: the XPointer Parser context
* @loc: the location for which the covering range must be computed
*
* A covering range is a range that wholly encompasses a location
* Section 5.3.3. Covering Ranges for All Location Types
* http://www.w3.org/TR/xptr#N2267
*
* Returns a new location or NULL in case of error
*/
static xmlXPathObjectPtr
xmlXPtrCoveringRange(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr loc) {
if (loc == NULL)
return(NULL);
if ((ctxt == NULL) || (ctxt->context == NULL) ||
(ctxt->context->doc == NULL))
return(NULL);
switch (loc->type) {
case XPATH_POINT:
return(xmlXPtrNewRange(loc->user, loc->index,
loc->user, loc->index));
case XPATH_RANGE:
if (loc->user2 != NULL) {
return(xmlXPtrNewRange(loc->user, loc->index,
loc->user2, loc->index2));
} else {
xmlNodePtr node = (xmlNodePtr) loc->user;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -