mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-08-01 10:06:59 +03:00
propagating xpath ancesstors node fix to c14n plus small performance
* c14n.c: propagating xpath ancesstors node fix to c14n plus small performance improvement to reduce number of mallocs * xpath.c: fixed ancestors axis processing for namespace nodes
This commit is contained in:
@ -1,3 +1,10 @@
|
|||||||
|
Thu May 30 21:23:06 2002 Aleksey Sanin <aleksey@aleksey.com>
|
||||||
|
|
||||||
|
* c14n.c: propagating xpath ancesstors node fix to c14n
|
||||||
|
plus small performance improvement to reduce number of
|
||||||
|
mallocs
|
||||||
|
* xpath.c: fixed ancestors axis processing for namespace nodes
|
||||||
|
|
||||||
Wed May 29 10:21:39 CEST 2002 Daniel Veillard <daniel@veillard.com>
|
Wed May 29 10:21:39 CEST 2002 Daniel Veillard <daniel@veillard.com>
|
||||||
|
|
||||||
* SAX.c parser.c tree.c include/libxml/tree.h: performance patch from
|
* SAX.c parser.c tree.c include/libxml/tree.h: performance patch from
|
||||||
|
176
c14n.c
176
c14n.c
@ -38,6 +38,12 @@ typedef enum {
|
|||||||
XMLC14N_AFTER_DOCUMENT_ELEMENT = 2
|
XMLC14N_AFTER_DOCUMENT_ELEMENT = 2
|
||||||
} xmlC14NPosition;
|
} xmlC14NPosition;
|
||||||
|
|
||||||
|
typedef struct _xmlC14NNamespaces {
|
||||||
|
int nsNr; /* number of nodes in the set */
|
||||||
|
int nsMax; /* size of the array as allocated */
|
||||||
|
xmlNsPtr *nsTab; /* array of nodes in no particular order */
|
||||||
|
} xmlC14NNamespaces, *xmlC14NNamespacesPtr;
|
||||||
|
|
||||||
typedef struct _xmlC14NCtx {
|
typedef struct _xmlC14NCtx {
|
||||||
/* input parameters */
|
/* input parameters */
|
||||||
xmlDocPtr doc;
|
xmlDocPtr doc;
|
||||||
@ -48,10 +54,10 @@ typedef struct _xmlC14NCtx {
|
|||||||
/* position in the XML document */
|
/* position in the XML document */
|
||||||
xmlC14NPosition pos;
|
xmlC14NPosition pos;
|
||||||
int parent_is_doc;
|
int parent_is_doc;
|
||||||
|
xmlC14NNamespacesPtr ns_rendered;
|
||||||
|
|
||||||
/* exclusive canonicalization */
|
/* exclusive canonicalization */
|
||||||
int exclusive;
|
int exclusive;
|
||||||
xmlNodeSetPtr ns_rendered;
|
|
||||||
xmlChar **inclusive_ns_prefixes;
|
xmlChar **inclusive_ns_prefixes;
|
||||||
} xmlC14NCtx, *xmlC14NCtxPtr;
|
} xmlC14NCtx, *xmlC14NCtxPtr;
|
||||||
|
|
||||||
@ -82,6 +88,67 @@ static xmlChar *xmlC11NNormalizeString(const xmlChar * input,
|
|||||||
* The implementation internals *
|
* The implementation internals *
|
||||||
* *
|
* *
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
|
#define XML_NAMESPACES_DEFAULT 16
|
||||||
|
|
||||||
|
static xmlC14NNamespacesPtr
|
||||||
|
xmlC14NNamespacesCreate() {
|
||||||
|
xmlC14NNamespacesPtr ret;
|
||||||
|
|
||||||
|
ret = (xmlC14NNamespacesPtr) xmlMalloc(sizeof(xmlC14NNamespaces));
|
||||||
|
if (ret == NULL) {
|
||||||
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
|
"xmlC14NNamespacesCreate: out of memory\n");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
memset(ret, 0 , (size_t) sizeof(xmlC14NNamespaces));
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
xmlC14NNamespacesDestroy(xmlC14NNamespacesPtr cur) {
|
||||||
|
if(cur == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(cur->nsTab != NULL) {
|
||||||
|
memset(cur->nsTab, 0, cur->nsMax * sizeof(xmlNsPtr));
|
||||||
|
xmlFree(cur->nsTab);
|
||||||
|
}
|
||||||
|
memset(cur, 0, sizeof(xmlC14NNamespaces));
|
||||||
|
xmlFree(cur);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void xmlC14NNamespacesAdd(xmlC14NNamespacesPtr cur, xmlNsPtr ns) {
|
||||||
|
if((cur == NULL) || (ns == NULL)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur->nsTab == NULL) {
|
||||||
|
cur->nsTab = (xmlNsPtr*) xmlMalloc(XML_NAMESPACES_DEFAULT * sizeof(xmlNsPtr));
|
||||||
|
if (cur->nsTab == NULL) {
|
||||||
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
|
"xmlC14NNamespacesAdd: out of memory\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memset(cur->nsTab, 0 , XML_NAMESPACES_DEFAULT * sizeof(xmlNsPtr));
|
||||||
|
cur->nsMax = XML_NAMESPACES_DEFAULT;
|
||||||
|
} else if(cur->nsMax == cur->nsNr) {
|
||||||
|
xmlNsPtr *tmp;
|
||||||
|
int tmpSize;
|
||||||
|
|
||||||
|
tmpSize = 2 * cur->nsMax;
|
||||||
|
tmp = (xmlNsPtr*) xmlRealloc(cur->nsTab, tmpSize * sizeof(xmlNsPtr));
|
||||||
|
if (tmp == NULL) {
|
||||||
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
|
"xmlC14NNamespacesAdd: out of memory\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cur->nsTab = tmp;
|
||||||
|
cur->nsMax = tmpSize;
|
||||||
|
}
|
||||||
|
cur->nsTab[cur->nsNr++] = ns;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlC14NIsVisible:
|
* xmlC14NIsVisible:
|
||||||
@ -150,9 +217,9 @@ xmlExcC14NIsRendered(xmlC14NCtxPtr ctx, xmlNsPtr ns)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->ns_rendered->nodeTab != NULL) {
|
if (ctx->ns_rendered->nsTab != NULL) {
|
||||||
for (i = ctx->ns_rendered->nodeNr - 1; i >= 0; --i) {
|
for (i = ctx->ns_rendered->nsNr - 1; i >= 0; --i) {
|
||||||
xmlNsPtr ns1 = (xmlNsPtr) ctx->ns_rendered->nodeTab[i];
|
xmlNsPtr ns1 = (xmlNsPtr) ctx->ns_rendered->nsTab[i];
|
||||||
|
|
||||||
if (xmlStrEqual(ns1->prefix, ns->prefix)) {
|
if (xmlStrEqual(ns1->prefix, ns->prefix)) {
|
||||||
return (xmlStrEqual(ns1->href, ns->href));
|
return (xmlStrEqual(ns1->href, ns->href));
|
||||||
@ -267,8 +334,6 @@ xmlC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur)
|
|||||||
xmlNsPtr ns;
|
xmlNsPtr ns;
|
||||||
xmlListPtr list;
|
xmlListPtr list;
|
||||||
xmlNodePtr visible_parent;
|
xmlNodePtr visible_parent;
|
||||||
xmlNodePtr node;
|
|
||||||
xmlNsPtr prev;
|
|
||||||
|
|
||||||
if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) {
|
if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) {
|
||||||
#ifdef DEBUG_C14N
|
#ifdef DEBUG_C14N
|
||||||
@ -293,53 +358,46 @@ xmlC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur)
|
|||||||
|
|
||||||
/* find nearest visible parent */
|
/* find nearest visible parent */
|
||||||
visible_parent = cur->parent;
|
visible_parent = cur->parent;
|
||||||
while ((visible_parent != NULL) &&
|
while ((visible_parent != NULL) && (!xmlC14NIsVisible(ctx, visible_parent))) {
|
||||||
(!xmlC14NIsVisible(ctx, visible_parent))) {
|
|
||||||
visible_parent = visible_parent->parent;
|
visible_parent = visible_parent->parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if(ctx->visible_nodes == NULL) {
|
||||||
* todo: the libxml XPath implementation does not create
|
xmlNodePtr node;
|
||||||
* nodes for all namespaces known to the node (i.e. for namespaces
|
|
||||||
* defined in node parents). By this we need to now walk thru
|
/*
|
||||||
* all namespace in current node and all invisible ancesstors
|
* the libxml does not create nodes for all namespaces known
|
||||||
*/
|
* to the node (i.e. for namespaces defined in node parents).
|
||||||
node = cur;
|
* By this we need to now walk thru all namespace in current
|
||||||
while (cur != visible_parent) {
|
* node and all invisible ancesstors
|
||||||
for (ns = cur->nsDef; ns != NULL; ns = ns->next) {
|
*/
|
||||||
/*
|
node = cur;
|
||||||
* first of all ignore default "xml" namespace and
|
while (cur != visible_parent) {
|
||||||
* already included namespace
|
for (ns = cur->nsDef; ns != NULL; ns = ns->next) {
|
||||||
*/
|
if(!xmlC14NIsXmlNs(ns) && !xmlExcC14NIsRendered(ctx, ns)) {
|
||||||
if ((xmlC14NIsXmlNs(ns)) || (xmlListSearch(list, ns) != NULL)) {
|
xmlListInsert(list, ns);
|
||||||
continue;
|
xmlC14NNamespacesAdd(ctx->ns_rendered, ns);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cur = cur->parent;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All visible namespace nodes are in the nodes set
|
||||||
|
*/
|
||||||
|
for(i = 0; i < ctx->visible_nodes->nodeNr; i++) {
|
||||||
|
if(ctx->visible_nodes->nodeTab[i]->type == XML_NAMESPACE_DECL) {
|
||||||
|
ns = (xmlNsPtr) ctx->visible_nodes->nodeTab[i];
|
||||||
|
|
||||||
|
if((ns != NULL) && (ns->next == (xmlNsPtr)cur) &&
|
||||||
|
!xmlC14NIsXmlNs(ns) && !xmlExcC14NIsRendered(ctx, ns)) {
|
||||||
|
xmlListInsert(list, ns);
|
||||||
|
xmlC14NNamespacesAdd(ctx->ns_rendered, ns);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
prev = xmlSearchNs(ctx->doc, node, ns->prefix);
|
}
|
||||||
if(prev != ns) {
|
|
||||||
/* we already processed a namespace with this name */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Lookup nearest namespace after visible parent having
|
|
||||||
* the same prefix. Namespace included if and only if one of
|
|
||||||
* the following:
|
|
||||||
* - another namespace having the same prefix but
|
|
||||||
* different value found or
|
|
||||||
* - there is no namespaces having the same prefix and
|
|
||||||
* it is not a default xmlns="" namespace (empty prefix
|
|
||||||
* and empty href)
|
|
||||||
*/
|
|
||||||
prev = xmlSearchNs(ctx->doc, visible_parent, ns->prefix);
|
|
||||||
if ((prev == NULL) && ((xmlStrlen(ns->prefix) > 0) ||
|
|
||||||
(xmlStrlen(ns->href) > 0))) {
|
|
||||||
xmlListInsert(list, ns);
|
|
||||||
} else if ((prev != NULL)
|
|
||||||
&& (!xmlStrEqual(ns->href, prev->href))) {
|
|
||||||
xmlListInsert(list, ns);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cur = cur->parent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -355,6 +413,7 @@ xmlC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xmlExcC14NProcessNamespacesAxis:
|
* xmlExcC14NProcessNamespacesAxis:
|
||||||
* @ctx: the C14N context
|
* @ctx: the C14N context
|
||||||
@ -426,12 +485,13 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur)
|
|||||||
* First of all, add all namespaces required by current node
|
* First of all, add all namespaces required by current node
|
||||||
* (i.e. node namespace and all attribute namespaces)
|
* (i.e. node namespace and all attribute namespaces)
|
||||||
* we also need to check for default "xml:" namespace
|
* we also need to check for default "xml:" namespace
|
||||||
|
* todo: shouldn't we check for namespaces "visibility"?
|
||||||
*/
|
*/
|
||||||
ns = (cur->ns != NULL) ? cur->ns : xmlSearchNs(ctx->doc, cur, NULL);
|
ns = (cur->ns != NULL) ? cur->ns : xmlSearchNs(ctx->doc, cur, NULL);
|
||||||
if ((ns != NULL) && (!xmlC14NIsXmlNs(ns)) &&
|
if ((ns != NULL) && (!xmlC14NIsXmlNs(ns)) &&
|
||||||
(xmlListSearch(list, ns) == NULL) && !xmlExcC14NIsRendered(ctx, ns)) {
|
(xmlListSearch(list, ns) == NULL) && !xmlExcC14NIsRendered(ctx, ns)) {
|
||||||
xmlListInsert(list, ns);
|
xmlListInsert(list, ns);
|
||||||
xmlXPathNodeSetAdd(ctx->ns_rendered, (xmlNodePtr) ns);
|
xmlC14NNamespacesAdd(ctx->ns_rendered, ns);
|
||||||
}
|
}
|
||||||
attr = cur->properties;
|
attr = cur->properties;
|
||||||
while (attr != NULL) {
|
while (attr != NULL) {
|
||||||
@ -444,7 +504,7 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur)
|
|||||||
(!xmlC14NIsXmlNs(attr->ns)) &&
|
(!xmlC14NIsXmlNs(attr->ns)) &&
|
||||||
(xmlListSearch(list, attr->ns) == NULL) && (!xmlExcC14NIsRendered(ctx, attr->ns))) {
|
(xmlListSearch(list, attr->ns) == NULL) && (!xmlExcC14NIsRendered(ctx, attr->ns))) {
|
||||||
xmlListInsert(list, attr->ns);
|
xmlListInsert(list, attr->ns);
|
||||||
xmlXPathNodeSetAdd(ctx->ns_rendered, (xmlNodePtr) attr->ns);
|
xmlC14NNamespacesAdd(ctx->ns_rendered, attr->ns);
|
||||||
}
|
}
|
||||||
attr = attr->next;
|
attr = attr->next;
|
||||||
}
|
}
|
||||||
@ -470,7 +530,7 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur)
|
|||||||
if (xmlListSearch(list, ns) == NULL &&
|
if (xmlListSearch(list, ns) == NULL &&
|
||||||
!xmlExcC14NIsRendered(ctx, ns)) {
|
!xmlExcC14NIsRendered(ctx, ns)) {
|
||||||
xmlListInsert(list, ns);
|
xmlListInsert(list, ns);
|
||||||
xmlXPathNodeSetAdd(ctx->ns_rendered, (xmlNodePtr) ns);
|
xmlC14NNamespacesAdd(ctx->ns_rendered, ns);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -809,8 +869,8 @@ xmlC14NProcessElementNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
|
|||||||
* Save ns_rendered stack position for exclusive
|
* Save ns_rendered stack position for exclusive
|
||||||
* processing
|
* processing
|
||||||
*/
|
*/
|
||||||
if ((ctx->exclusive) && (ctx->ns_rendered != NULL)) {
|
if (ctx->ns_rendered != NULL) {
|
||||||
ns_rendered_pos = ctx->ns_rendered->nodeNr;
|
ns_rendered_pos = ctx->ns_rendered->nsNr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (visible) {
|
if (visible) {
|
||||||
@ -883,8 +943,8 @@ xmlC14NProcessElementNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
|
|||||||
* Restore ns_rendered stack position for exclusive
|
* Restore ns_rendered stack position for exclusive
|
||||||
* processing
|
* processing
|
||||||
*/
|
*/
|
||||||
if ((ctx->exclusive) && (ctx->ns_rendered != NULL)) {
|
if (ctx->ns_rendered != NULL) {
|
||||||
ctx->ns_rendered->nodeNr = ns_rendered_pos;
|
ctx->ns_rendered->nsNr = ns_rendered_pos;
|
||||||
}
|
}
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@ -1148,7 +1208,7 @@ xmlC14NFreeCtx(xmlC14NCtxPtr ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->ns_rendered != NULL) {
|
if (ctx->ns_rendered != NULL) {
|
||||||
xmlXPathFreeNodeSet(ctx->ns_rendered);
|
xmlC14NNamespacesDestroy(ctx->ns_rendered);
|
||||||
}
|
}
|
||||||
xmlFree(ctx);
|
xmlFree(ctx);
|
||||||
}
|
}
|
||||||
@ -1226,6 +1286,7 @@ xmlC14NNewCtx(xmlDocPtr doc, xmlNodeSetPtr nodes,
|
|||||||
ctx->buf = buf;
|
ctx->buf = buf;
|
||||||
ctx->parent_is_doc = 1;
|
ctx->parent_is_doc = 1;
|
||||||
ctx->pos = XMLC14N_BEFORE_DOCUMENT_ELEMENT;
|
ctx->pos = XMLC14N_BEFORE_DOCUMENT_ELEMENT;
|
||||||
|
ctx->ns_rendered = xmlC14NNamespacesCreate();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set "exclusive" flag, create a nodes set for namespaces
|
* Set "exclusive" flag, create a nodes set for namespaces
|
||||||
@ -1233,7 +1294,6 @@ xmlC14NNewCtx(xmlDocPtr doc, xmlNodeSetPtr nodes,
|
|||||||
*/
|
*/
|
||||||
if (exclusive) {
|
if (exclusive) {
|
||||||
ctx->exclusive = 1;
|
ctx->exclusive = 1;
|
||||||
ctx->ns_rendered = xmlXPathNodeSetCreate(NULL);
|
|
||||||
ctx->inclusive_ns_prefixes = inclusive_ns_prefixes;
|
ctx->inclusive_ns_prefixes = inclusive_ns_prefixes;
|
||||||
}
|
}
|
||||||
return (ctx);
|
return (ctx);
|
||||||
|
15
xpath.c
15
xpath.c
@ -5200,6 +5200,15 @@ xmlXPathNextAncestor(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
|
|||||||
|
|
||||||
return(att->parent);
|
return(att->parent);
|
||||||
}
|
}
|
||||||
|
case XML_NAMESPACE_DECL: {
|
||||||
|
xmlNsPtr ns = (xmlNsPtr) ctxt->context->node;
|
||||||
|
|
||||||
|
if ((ns->next != NULL) &&
|
||||||
|
(ns->next->type != XML_NAMESPACE_DECL))
|
||||||
|
return((xmlNodePtr) ns->next);
|
||||||
|
/* Bad, how did that namespace ended-up there ? */
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
case XML_DOCUMENT_NODE:
|
case XML_DOCUMENT_NODE:
|
||||||
case XML_DOCUMENT_TYPE_NODE:
|
case XML_DOCUMENT_TYPE_NODE:
|
||||||
case XML_DOCUMENT_FRAG_NODE:
|
case XML_DOCUMENT_FRAG_NODE:
|
||||||
@ -5208,12 +5217,6 @@ xmlXPathNextAncestor(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
|
|||||||
case XML_DOCB_DOCUMENT_NODE:
|
case XML_DOCB_DOCUMENT_NODE:
|
||||||
#endif
|
#endif
|
||||||
return(NULL);
|
return(NULL);
|
||||||
case XML_NAMESPACE_DECL:
|
|
||||||
/*
|
|
||||||
* this should not hapen a namespace can't be
|
|
||||||
* the ancestor of another node
|
|
||||||
*/
|
|
||||||
return(NULL);
|
|
||||||
}
|
}
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user