1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2025-03-31 06:50:06 +03:00

added merlin-c14n-two.tar.gz tests for c14n/exc-c14n and slightly modified

* result/c14n/exc-without-comments/merlin-c14n-two-*
  result/c14n/without-comments/merlin-c14n-two-*
  test/c14n/exc-without-comments/merlin-c14n-two-*
  test/c14n/without-comments/merlin-c14n-two-*
  testC14N.c Makefile.am: added merlin-c14n-two.tar.gz tests for
c14n/exc-c14n and slightly modified test script to handle
these test cases
* c14n.c: fixed bugs for complicated nodes set (namespace
without node and others from merlin-c14n-two.tar.gz)
* include/libxml/xpathInternals.h win32/dsp/libxml2.def.src
win32/libxml2.def.src: "opened" xmlXPathNodeSetFreeNs() function
for xmlsec performance patch
* xpath.c: fixed self::node() for namespaces and attributes
This commit is contained in:
Aleksey Sanin 2002-06-04 04:27:06 +00:00
parent c57f9c1210
commit f8cb6dda89
8 changed files with 357 additions and 147 deletions

View File

@ -1,3 +1,19 @@
Mon Jun 3 21:21:26 2002 Aleksey Sanin <aleksey@aleksey.com>
* result/c14n/exc-without-comments/merlin-c14n-two-*
result/c14n/without-comments/merlin-c14n-two-*
test/c14n/exc-without-comments/merlin-c14n-two-*
test/c14n/without-comments/merlin-c14n-two-*
testC14N.c Makefile.am: added merlin-c14n-two.tar.gz tests for
c14n/exc-c14n and slightly modified test script to handle
these test cases
* c14n.c: fixed bugs for complicated nodes set (namespace
without node and others from merlin-c14n-two.tar.gz)
* include/libxml/xpathInternals.h win32/dsp/libxml2.def.src
win32/libxml2.def.src: "opened" xmlXPathNodeSetFreeNs() function
for xmlsec performance patch
* xpath.c: fixed self::node() for namespaces and attributes
Fri May 31 12:16:48 2002 Aleksey Sanin <aleksey@aleksey.com>
* Makefile.am: updated c14n tests suite

View File

@ -612,29 +612,27 @@ Automatatests: testAutomata$(EXEEXT)
fi ; fi ; done)
C14Ntests : testC14N$(EXEEXT)
@echo "##"
@echo "## C14N and XPath regression tests"
@echo "##"
-@(for m in with-comments without-comments exc-without-comments ; do \
echo "##"; \
echo "## C14N regression tests: $$m"; \
echo "##"; \
for i in $(srcdir)/test/c14n/$$m/*.xml ; do \
if [ ! -d $$i ] ; then \
name=`basename $$i .xml`; \
echo Testing $$name; \
echo Testing $$m/$$name; \
cmdline="$(CHECKER) $(top_builddir)/testC14N --$$m $$i"; \
if [ -e $(srcdir)/test/c14n/$$m/$$name.xpath ] ; then \
xpathFile=$(srcdir)/test/c14n/$$m/$$name.xpath; \
else \
xpathFile=""; \
cmdline="$$cmdline $(srcdir)/test/c14n/$$m/$$name.xpath"; \
if [ -e $(srcdir)/test/c14n/$$m/$$name.ns ] ; then \
cmdline="$$cmdline '`cat $(srcdir)/test/c14n/$$m/$$name.ns`'"; \
fi; \
fi; \
if [ -e $(srcdir)/test/c14n/$$m/$$name.ns ] ; then \
nsList=`cat $(srcdir)/test/c14n/$$m/$$name.ns`; \
else \
nsList=""; \
fi; \
$(CHECKER) $(top_builddir)/testC14N --$$m $$i $$xpathFile $$nsList > $(srcdir)/test/c14n/test.tmp; \
$$cmdline > $(srcdir)/test/c14n/test.tmp; \
if [ $$? -eq 0 ]; then \
diff $(srcdir)/result/c14n/$$m/$$name $(srcdir)/test/c14n/test.tmp; \
if [ $$? -ne 0 ]; then \
echo "Test failed"; \
cat $(srcdir)/test/c14n/test.tmp; \
fi; \
else \
echo "C14N failed"; \

407
c14n.c
View File

@ -38,12 +38,25 @@ typedef enum {
XMLC14N_AFTER_DOCUMENT_ELEMENT = 2
} xmlC14NPosition;
typedef struct _xmlC14NNamespaces {
int nsNr; /* number of nodes in the set */
typedef struct _xmlC14NVisibleNsStack {
int nsCurEnd; /* number of nodes in the set */
int nsPrevStart; /* the begginning of the stack for previous visible node */
int nsPrevEnd; /* the end of the stack for previous visible node */
int nsMax; /* size of the array as allocated */
int nsPos; /* the begginning of the stack for this node */
xmlNsPtr *nsTab; /* array of nodes in no particular order */
} xmlC14NNamespaces, *xmlC14NNamespacesPtr;
} xmlC14NVisibleNsStack, *xmlC14NVisibleNsStackPtr;
static xmlC14NVisibleNsStackPtr xmlC14NVisibleNsStackCreate (void);
static void xmlC14NVisibleNsStackDestroy (xmlC14NVisibleNsStackPtr cur);
static void xmlC14NVisibleNsStackAdd (xmlC14NVisibleNsStackPtr cur,
xmlNsPtr ns);
static void xmlC14NVisibleNsStackSave (xmlC14NVisibleNsStackPtr cur,
xmlC14NVisibleNsStackPtr state);
static void xmlC14NVisibleNsStackRestore (xmlC14NVisibleNsStackPtr cur,
xmlC14NVisibleNsStackPtr state);
static void xmlC14NVisibleNsStackShift (xmlC14NVisibleNsStackPtr cur);
static int xmlC14NVisibleNsStackFind (xmlC14NVisibleNsStackPtr cur,
xmlNsPtr ns,
int exclusive);
typedef struct _xmlC14NCtx {
/* input parameters */
@ -55,7 +68,7 @@ typedef struct _xmlC14NCtx {
/* position in the XML document */
xmlC14NPosition pos;
int parent_is_doc;
xmlC14NNamespacesPtr ns_rendered;
xmlC14NVisibleNsStackPtr ns_rendered;
/* exclusive canonicalization */
int exclusive;
@ -91,36 +104,45 @@ static xmlChar *xmlC11NNormalizeString(const xmlChar * input,
************************************************************************/
#define XML_NAMESPACES_DEFAULT 16
static xmlC14NNamespacesPtr
xmlC14NNamespacesCreate() {
xmlC14NNamespacesPtr ret;
static xmlC14NVisibleNsStackPtr
xmlC14NVisibleNsStackCreate(void) {
xmlC14NVisibleNsStackPtr ret;
ret = (xmlC14NNamespacesPtr) xmlMalloc(sizeof(xmlC14NNamespaces));
ret = (xmlC14NVisibleNsStackPtr) xmlMalloc(sizeof(xmlC14NVisibleNsStack));
if (ret == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlC14NNamespacesCreate: out of memory\n");
"xmlC14NVisibleNsStackCreate: out of memory\n");
return(NULL);
}
memset(ret, 0 , (size_t) sizeof(xmlC14NNamespaces));
memset(ret, 0 , (size_t) sizeof(xmlC14NVisibleNsStack));
return(ret);
}
static void
xmlC14NNamespacesDestroy(xmlC14NNamespacesPtr cur) {
xmlC14NVisibleNsStackDestroy(xmlC14NVisibleNsStackPtr cur) {
if(cur == NULL) {
#ifdef DEBUG_C14N
xmlGenericError(xmlGenericErrorContext,
"xmlC14NVisibleNsStackAdd: cur is null.\n");
#endif
return;
}
if(cur->nsTab != NULL) {
memset(cur->nsTab, 0, cur->nsMax * sizeof(xmlNsPtr));
xmlFree(cur->nsTab);
}
memset(cur, 0, sizeof(xmlC14NNamespaces));
memset(cur, 0, sizeof(xmlC14NVisibleNsStack));
xmlFree(cur);
}
static void xmlC14NNamespacesAdd(xmlC14NNamespacesPtr cur, xmlNsPtr ns) {
if((cur == NULL) || (ns == NULL)) {
static void
xmlC14NVisibleNsStackAdd(xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns) {
if(cur == NULL) {
#ifdef DEBUG_C14N
xmlGenericError(xmlGenericErrorContext,
"xmlC14NVisibleNsStackAdd: cur is null.\n");
#endif
return;
}
@ -128,12 +150,12 @@ static void xmlC14NNamespacesAdd(xmlC14NNamespacesPtr cur, xmlNsPtr ns) {
cur->nsTab = (xmlNsPtr*) xmlMalloc(XML_NAMESPACES_DEFAULT * sizeof(xmlNsPtr));
if (cur->nsTab == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlC14NNamespacesAdd: out of memory\n");
"xmlC14NVisibleNsStackAdd: 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) {
} else if(cur->nsMax == cur->nsCurEnd) {
xmlNsPtr *tmp;
int tmpSize;
@ -141,13 +163,111 @@ static void xmlC14NNamespacesAdd(xmlC14NNamespacesPtr cur, xmlNsPtr ns) {
tmp = (xmlNsPtr*) xmlRealloc(cur->nsTab, tmpSize * sizeof(xmlNsPtr));
if (tmp == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlC14NNamespacesAdd: out of memory\n");
"xmlC14NVisibleNsStackAdd: out of memory\n");
return;
}
cur->nsTab = tmp;
cur->nsMax = tmpSize;
}
cur->nsTab[cur->nsNr++] = ns;
cur->nsTab[cur->nsCurEnd++] = ns;
}
static void
xmlC14NVisibleNsStackSave(xmlC14NVisibleNsStackPtr cur, xmlC14NVisibleNsStackPtr state) {
if((cur == NULL) || (state == NULL)) {
#ifdef DEBUG_C14N
xmlGenericError(xmlGenericErrorContext,
"xmlC14NVisibleNsStackSave: cur or state is null.\n");
#endif
return;
}
state->nsCurEnd = cur->nsCurEnd;
state->nsPrevStart = cur->nsPrevStart;
state->nsPrevEnd = cur->nsPrevEnd;
}
static void
xmlC14NVisibleNsStackRestore(xmlC14NVisibleNsStackPtr cur, xmlC14NVisibleNsStackPtr state) {
if((cur == NULL) || (state == NULL)) {
#ifdef DEBUG_C14N
xmlGenericError(xmlGenericErrorContext,
"xmlC14NVisibleNsStackRestore: cur or state is null.\n");
#endif
return;
}
cur->nsCurEnd = state->nsCurEnd;
cur->nsPrevStart = state->nsPrevStart;
cur->nsPrevEnd = state->nsPrevEnd;
}
static void
xmlC14NVisibleNsStackShift(xmlC14NVisibleNsStackPtr cur) {
if(cur == NULL) {
#ifdef DEBUG_C14N
xmlGenericError(xmlGenericErrorContext,
"xmlC14NVisibleNsStackRestore: cur is null.\n");
#endif
return;
}
cur->nsPrevStart = cur->nsPrevEnd;
cur->nsPrevEnd = cur->nsCurEnd;
}
static int
xmlC14NStrEqual(const xmlChar *str1, const xmlChar *str2) {
if (str1 == str2) return(1);
if (str1 == NULL) return((*str2) == '\0');
if (str2 == NULL) return((*str1) == '\0');
do {
if (*str1++ != *str2) return(0);
} while (*str2++);
return(1);
}
/**
* xmlC14NVisibleNsStackFind:
* @ctx the C14N context
* @ns the namespace to check
*
* Checks whether the given namespace was already rendered or not
*
* Returns 1 if we already wrote this namespace or 0 otherwise
*/
static int
xmlC14NVisibleNsStackFind(xmlC14NVisibleNsStackPtr cur, xmlNsPtr ns, int exclusive)
{
int i;
const xmlChar *prefix;
const xmlChar *href;
int emptyNs;
if(cur == NULL) {
#ifdef DEBUG_C14N
xmlGenericError(xmlGenericErrorContext,
"xmlC14NVisibleNsStackFind: cur is null.\n");
#endif
return (0);
}
/*
* if the default namespace xmlns="" is not defined yet then
* we do not want to print it out
*/
prefix = ((ns == NULL) || (ns->prefix == NULL)) ? BAD_CAST "" : ns->prefix;
href = ((ns == NULL) || (ns->href == NULL)) ? BAD_CAST "" : ns->href;
emptyNs = (xmlC14NStrEqual(prefix, NULL) && xmlC14NStrEqual(href, NULL));
if (cur->nsTab != NULL) {
int start = (exclusive || emptyNs) ? 0 : cur->nsPrevStart;
for (i = cur->nsCurEnd - 1; i >= start; --i) {
xmlNsPtr ns1 = cur->nsTab[i];
if(xmlC14NStrEqual(prefix, (ns1 != NULL) ? ns1->prefix : NULL)) {
return(xmlC14NStrEqual(href, (ns1 != NULL) ? ns1->href : NULL));
}
}
}
return(emptyNs);
}
@ -179,6 +299,30 @@ xmlC14NIsVisible(xmlC14NCtxPtr ctx, void *node)
return (1);
}
static int
xmlC14NIsNsVisible(xmlC14NCtxPtr ctx, xmlNsPtr ns, xmlNodePtr cur)
{
xmlNs ns1;
if(ns == NULL) {
return(1);
}
memcpy(&ns1, ns, sizeof(ns1));
ns1.next = (xmlNsPtr)cur;
/*
* If the input is an XPath node-set, then the node-set must explicitly
* contain every node to be rendered to the canonical form.
*/
if ((ctx->visible_nodes != NULL) &&
(!xmlXPathNodeSetContains(ctx->visible_nodes, (xmlNodePtr) &ns1)))
{
return (0);
}
return (1);
}
/**
* xmlC14NIsXmlNs:
* @ns: the namespace to check
@ -200,45 +344,9 @@ xmlC14NIsXmlNs(xmlNsPtr ns)
"http://www.w3.org/XML/1998/namespace")));
}
/**
* xmlExcC14NIsRendered:
* @ctx the C14N context
* @ns the namespace to check
*
* Checks whether the given namespace was already rendered or not
*
* Returns 1 if we already wrote this namespace or 0 otherwise
*/
static int
xmlExcC14NIsRendered(xmlC14NCtxPtr ctx, xmlNsPtr ns)
{
int i;
int emptyNs;
if ((ctx == NULL) || (ctx->ns_rendered == NULL) || (ns == NULL)) {
return (0);
}
/*
* if the default namespace xmlns="" is not defined yet then
* we do not want to print it out
*/
emptyNs = ((xmlStrlen(ns->prefix) == 0) && (xmlStrlen(ns->href) == 0));
if (ctx->ns_rendered->nsTab != NULL) {
int pos = (emptyNs) ? 0 : ctx->ns_rendered->nsPos;
for (i = ctx->ns_rendered->nsNr - 1; i >= pos; --i) {
xmlNsPtr ns1 = ctx->ns_rendered->nsTab[i];
if (xmlStrEqual(ns1->prefix, ns->prefix)) {
return (xmlStrEqual(ns1->href, ns->href));
}
}
}
return(emptyNs);
}
/**
* xmlC14NNamespacesCompare:
* xmlC14NNsCompare:
* @ns1: the pointer to first namespace
* @ns2: the pointer to second namespace
*
@ -247,7 +355,7 @@ xmlExcC14NIsRendered(xmlC14NCtxPtr ctx, xmlNsPtr ns)
* Returns -1 if ns1 < ns2, 0 if ns1 == ns2 or 1 if ns1 > ns2.
*/
static int
xmlC14NNamespacesCompare(xmlNsPtr ns1, xmlNsPtr ns2)
xmlC14NNsCompare(xmlNsPtr ns1, xmlNsPtr ns2)
{
if (ns1 == ns2)
return (0);
@ -288,7 +396,9 @@ xmlC14NPrintNamespaces(const xmlNsPtr ns, xmlC14NCtxPtr ctx)
} else {
xmlOutputBufferWriteString(ctx->buf, " xmlns=\"");
}
xmlOutputBufferWriteString(ctx->buf, (const char *) ns->href);
if(ns->href != NULL) {
xmlOutputBufferWriteString(ctx->buf, (const char *) ns->href);
}
xmlOutputBufferWriteString(ctx->buf, "\"");
return (1);
}
@ -333,7 +443,7 @@ xmlC14NPrintNamespaces(const xmlNsPtr ns, xmlC14NCtxPtr ctx)
* Returns 0 on success or -1 on fail.
*/
static int
xmlC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur)
xmlC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
{
xmlNsPtr ns;
xmlListPtr list;
@ -350,7 +460,7 @@ xmlC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur)
* Create a sorted list to store element namespaces
*/
list =
xmlListCreate(NULL, (xmlListDataCompare) xmlC14NNamespacesCompare);
xmlListCreate(NULL, (xmlListDataCompare) xmlC14NNsCompare);
if (list == NULL) {
#ifdef DEBUG_C14N
xmlGenericError(xmlGenericErrorContext,
@ -374,30 +484,56 @@ xmlC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur)
}
}
} else {
xmlNodePtr node;
int i;
int emptyNs = 0;
/*
* 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];
node = ctx->visible_nodes->nodeTab[i];
if((node != NULL) && (node->type == XML_NAMESPACE_DECL)) {
ns = (xmlNsPtr)node;
if((ns != NULL) && (ns->next == (xmlNsPtr)cur) && !xmlC14NIsXmlNs(ns)) {
if(!xmlExcC14NIsRendered(ctx, ns)) {
if(((xmlNodePtr)(ns->next) == cur) && !xmlC14NIsXmlNs(ns)) {
if(!xmlC14NVisibleNsStackFind(ctx->ns_rendered, ns, 0)) {
xmlListInsert(list, ns);
}
xmlC14NNamespacesAdd(ctx->ns_rendered, ns);
if(visible) {
xmlC14NVisibleNsStackAdd(ctx->ns_rendered, ns);
}
if(xmlStrlen(ns->prefix) == 0) {
emptyNs = 1;
}
}
}
}
/**
* if the first node is not the default namespace node (a node with no
* namespace URI and no local name), then generate a space followed by
* xmlns="" if and only if the following conditions are met:
* - the element E that owns the axis is in the node-set
* - the nearest ancestor element of E in the node-set has a default
* namespace node in the node-set (default namespace nodes always
* have non-empty values in XPath)
*/
if(visible && !emptyNs) {
xmlNs ns1;
memset(&ns1, 0, sizeof(ns1));
if(!xmlC14NVisibleNsStackFind(ctx->ns_rendered, &ns1, 0)) {
xmlC14NPrintNamespaces(&ns1, ctx);
}
}
}
/*
* print out all elements from list
*/
xmlListWalk(list, (xmlListWalker) xmlC14NPrintNamespaces,
(const void *) ctx);
xmlListWalk(list, (xmlListWalker) xmlC14NPrintNamespaces, (const void *) ctx);
/*
* Cleanup
@ -438,11 +574,13 @@ xmlC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur)
* Returns 0 on success or -1 on fail.
*/
static int
xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur)
xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
{
xmlListPtr list;
xmlAttrPtr attr;
xmlNsPtr ns;
xmlNs default_ns;
if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) {
#ifdef DEBUG_C14N
@ -452,7 +590,7 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur)
return (-1);
}
if ((!ctx->exclusive) || (ctx->ns_rendered == NULL)) {
if(!ctx->exclusive) {
#ifdef DEBUG_C14N
xmlGenericError(xmlGenericErrorContext,
"xmlExcC14NProcessNamespacesAxis: called for non-exclusive canonization or rendered stack is NULL.\n");
@ -460,12 +598,12 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur)
return (-1);
}
memset(&default_ns, 0, sizeof(default_ns));
/*
* Create a sorted list to store element namespaces
*/
list =
xmlListCreate(NULL, (xmlListDataCompare) xmlC14NNamespacesCompare);
list = xmlListCreate(NULL, (xmlListDataCompare) xmlC14NNsCompare);
if (list == NULL) {
#ifdef DEBUG_C14N
xmlGenericError(xmlGenericErrorContext,
@ -480,13 +618,19 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur)
* 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);
if ((ns != NULL) && (!xmlC14NIsXmlNs(ns)) && (xmlListSearch(list, ns) == NULL)) {
if(!xmlExcC14NIsRendered(ctx, ns)) {
xmlListInsert(list, ns);
if(visible) {
ns = (cur->ns != NULL) ? cur->ns : xmlSearchNs(ctx->doc, cur, NULL);
if ((ns != NULL) && (!xmlC14NIsXmlNs(ns)) && (xmlListSearch(list, ns) == NULL) &&
xmlC14NIsNsVisible(ctx, ns, cur)) {
if(!xmlC14NVisibleNsStackFind(ctx->ns_rendered, ns, 1)) {
xmlListInsert(list, ns);
}
if(visible) {
xmlC14NVisibleNsStackAdd(ctx->ns_rendered, ns);
}
}
xmlC14NNamespacesAdd(ctx->ns_rendered, ns);
}
attr = cur->properties;
while (attr != NULL) {
/*
@ -495,11 +639,14 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur)
* do not apply directly to attributes")
*/
if ((attr->ns != NULL) && xmlC14NIsVisible(ctx, attr) &&
xmlC14NIsNsVisible(ctx, attr->ns, cur) &&
(!xmlC14NIsXmlNs(attr->ns)) && (xmlListSearch(list, attr->ns) == NULL)) {
if(!xmlExcC14NIsRendered(ctx, attr->ns)) {
if(!xmlC14NVisibleNsStackFind(ctx->ns_rendered, attr->ns, 1)) {
xmlListInsert(list, attr->ns);
}
xmlC14NNamespacesAdd(ctx->ns_rendered, attr->ns);
if(visible) {
xmlC14NVisibleNsStackAdd(ctx->ns_rendered, attr->ns);
}
}
attr = attr->next;
}
@ -521,12 +668,21 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur)
prefix = NULL;
}
ns = xmlSearchNs(ctx->doc, cur, prefix);
if ((ns != NULL) && (!xmlC14NIsXmlNs(ns))) {
if (xmlListSearch(list, ns) == NULL) {
if(!xmlExcC14NIsRendered(ctx, ns)) {
if((ns != NULL) && (!xmlC14NIsXmlNs(ns))) {
int ns_visible = xmlC14NIsNsVisible(ctx, ns, cur);
if(!ns_visible && (prefix == NULL)) {
ns = &default_ns;
ns_visible = 1;
}
if (ns_visible) {
if(!xmlC14NVisibleNsStackFind(ctx->ns_rendered, ns, 1)) {
xmlListInsert(list, ns);
}
xmlC14NNamespacesAdd(ctx->ns_rendered, ns);
if(visible) {
xmlC14NVisibleNsStackAdd(ctx->ns_rendered,
(ns == &default_ns) ? NULL : ns);
}
}
}
}
@ -535,8 +691,7 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur)
/*
* print out all elements from list
*/
xmlListWalk(list, (xmlListWalker) xmlC14NPrintNamespaces,
(const void *) ctx);
xmlListWalk(list, (xmlListWalker) xmlC14NPrintNamespaces, (const void *) ctx);
/*
* Cleanup
@ -548,7 +703,7 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur)
/**
* xmlC14NAttrsCompare:
* @attr1: the pointer to first attr
* @attr1: the pointer tls o first attr
* @attr2: the pointer to second attr
*
* Prints the given attribute to the output buffer from C14N context.
@ -748,8 +903,7 @@ xmlC14NProcessAttrsAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur)
/*
* print out all elements from list
*/
xmlListWalk(list, (xmlListWalker) xmlC14NPrintAttrs,
(const void *) ctx);
xmlListWalk(list, (xmlListWalker) xmlC14NPrintAttrs, (const void *) ctx);
/*
* Cleanup
@ -836,8 +990,7 @@ static int
xmlC14NProcessElementNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
{
int ret;
int ns_rendered_pos = 0;
int ns_rendered_nr = 0;
xmlC14NVisibleNsStack state;
int parent_is_doc = 0;
if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) {
@ -863,13 +1016,9 @@ xmlC14NProcessElementNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
/*
* Save ns_rendered stack position for exclusive
* processing
* Save ns_rendered stack position
*/
if (ctx->ns_rendered != NULL) {
ns_rendered_pos = ctx->ns_rendered->nsPos;
ns_rendered_nr = ctx->ns_rendered->nsNr;
}
xmlC14NVisibleNsStackSave(ctx->ns_rendered, &state);
if (visible) {
if (ctx->parent_is_doc) {
@ -886,32 +1035,37 @@ xmlC14NProcessElementNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
xmlOutputBufferWriteString(ctx->buf, ":");
}
xmlOutputBufferWriteString(ctx->buf, (const char *) cur->name);
}
if (ctx->exclusive) {
ret = xmlExcC14NProcessNamespacesAxis(ctx, cur);
} else {
ret = xmlC14NProcessNamespacesAxis(ctx, cur);
}
if (ret < 0) {
if (!ctx->exclusive) {
ret = xmlC14NProcessNamespacesAxis(ctx, cur, visible);
} else {
ret = xmlExcC14NProcessNamespacesAxis(ctx, cur, visible);
}
if (ret < 0) {
#ifdef DEBUG_C14N
xmlGenericError(xmlGenericErrorContext,
"xmlC14NProcessElementNode: xmlC14NProcessNamespacesAxis failed.\n");
xmlGenericError(xmlGenericErrorContext,
"xmlC14NProcessElementNode: xmlC14NProcessNamespacesAxis failed.\n");
#endif
return (-1);
}
if (ctx->ns_rendered != NULL) {
ctx->ns_rendered->nsPos = ns_rendered_nr;
return (-1);
}
/* todo: shouldn't this go to "visible only"? */
if(visible) {
xmlC14NVisibleNsStackShift(ctx->ns_rendered);
}
if(visible) {
ret = xmlC14NProcessAttrsAxis(ctx, cur);
if (ret < 0) {
#ifdef DEBUG_C14N
xmlGenericError(xmlGenericErrorContext,
"xmlC14NProcessElementNode: xmlC14NProcessAttrsAxis failed.\n");
#endif
return (-1);
}
}
ret = xmlC14NProcessAttrsAxis(ctx, cur);
if (ret < 0) {
#ifdef DEBUG_C14N
xmlGenericError(xmlGenericErrorContext,
"xmlC14NProcessElementNode: xmlC14NProcessAttrsAxis failed.\n");
#endif
return (-1);
}
if (visible) {
xmlOutputBufferWriteString(ctx->buf, ">");
}
if (cur->children != NULL) {
@ -941,13 +1095,9 @@ xmlC14NProcessElementNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
}
/*
* Restore ns_rendered stack position for exclusive
* processing
* Restore ns_rendered stack position
*/
if (ctx->ns_rendered != NULL) {
ctx->ns_rendered->nsPos = ns_rendered_pos;
ctx->ns_rendered->nsNr = ns_rendered_nr;
}
xmlC14NVisibleNsStackRestore(ctx->ns_rendered, &state);
return (0);
}
@ -1210,7 +1360,7 @@ xmlC14NFreeCtx(xmlC14NCtxPtr ctx)
}
if (ctx->ns_rendered != NULL) {
xmlC14NNamespacesDestroy(ctx->ns_rendered);
xmlC14NVisibleNsStackDestroy(ctx->ns_rendered);
}
xmlFree(ctx);
}
@ -1288,7 +1438,14 @@ xmlC14NNewCtx(xmlDocPtr doc, xmlNodeSetPtr nodes,
ctx->buf = buf;
ctx->parent_is_doc = 1;
ctx->pos = XMLC14N_BEFORE_DOCUMENT_ELEMENT;
ctx->ns_rendered = xmlC14NNamespacesCreate();
ctx->ns_rendered = xmlC14NVisibleNsStackCreate();
if(ctx->ns_rendered == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlC14NNewCtx: xmlC14NVisibleNsStackCreate failed\n");
xmlC14NFreeCtx(ctx);
return (NULL);
}
/*
* Set "exclusive" flag, create a nodes set for namespaces

View File

@ -571,6 +571,12 @@ void xmlXPathFloorFunction(xmlXPathParserContextPtr ctxt, int nargs);
void xmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt, int nargs);
void xmlXPathRoundFunction(xmlXPathParserContextPtr ctxt, int nargs);
void xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs);
/**
* Really internal functions
*/
void xmlXPathNodeSetFreeNs(xmlNsPtr ns);
#ifdef __cplusplus
}
#endif

View File

@ -46,8 +46,7 @@ load_xpath_expr (xmlDocPtr parent_doc, const char* filename);
xmlChar **parse_list(xmlChar *str);
void
print_xpath_nodes(xmlXPathObjectPtr ptr);
void print_xpath_nodes(xmlNodeSetPtr nodes);
static int
test_c14n(const char* xml_filename, int with_comments, int exclusive,
@ -184,11 +183,18 @@ xmlChar **parse_list(xmlChar *str) {
xmlChar **buffer;
xmlChar **out = NULL;
int buffer_size = 0;
int len;
if(str == NULL) {
return(NULL);
}
len = strlen(str);
if((str[0] == '\'') && (str[len - 1] == '\'')) {
str[len - 1] = '\0';
str++;
len -= 2;
}
/*
* allocate an translation buffer.
*/
@ -298,7 +304,7 @@ load_xpath_expr (xmlDocPtr parent_doc, const char* filename) {
return(NULL);
}
/* print_xpath_nodes(xpath); */
/* print_xpath_nodes(xpath->nodesetval); */
xmlFree(expr);
xmlXPathFreeContext(ctx);
@ -307,21 +313,40 @@ load_xpath_expr (xmlDocPtr parent_doc, const char* filename) {
}
void
print_xpath_nodes(xmlXPathObjectPtr ptr) {
print_xpath_nodes(xmlNodeSetPtr nodes) {
xmlNodePtr cur;
int i;
if(ptr == NULL || ptr->nodesetval == NULL ){
if(nodes == NULL ){
fprintf(stderr, "Error: no nodes set defined\n");
return;
}
for(i = 0; i < ptr->nodesetval->nodeNr; ++i) {
cur = ptr->nodesetval->nodeTab[i];
fprintf(stderr, "node %s. type %d\n", cur->name, cur->type);
fprintf(stderr, "Nodes Set:\n-----\n");
for(i = 0; i < nodes->nodeNr; ++i) {
if(nodes->nodeTab[i]->type == XML_NAMESPACE_DECL) {
xmlNsPtr ns;
ns = (xmlNsPtr)nodes->nodeTab[i];
cur = (xmlNodePtr)ns->next;
fprintf(stderr, "namespace \"%s\"=\"%s\" for node %s:%s\n",
ns->prefix, ns->href,
(cur->ns) ? cur->ns->prefix : BAD_CAST "", cur->name);
} else if(nodes->nodeTab[i]->type == XML_ELEMENT_NODE) {
cur = nodes->nodeTab[i];
fprintf(stderr, "element node \"%s:%s\"\n",
(cur->ns) ? cur->ns->prefix : BAD_CAST "", cur->name);
} else {
cur = nodes->nodeTab[i];
fprintf(stderr, "node \"%s\": type %d\n", cur->name, cur->type);
}
}
}
#else
#include <stdio.h>
int main(int argc, char **argv) {

View File

@ -1335,6 +1335,9 @@ EXPORTS
xmlXPathCeilingFunction
xmlXPathRoundFunction
xmlXPathBooleanFunction
/* really internal functions */
xmlXPathNodeSetFreeNs
#endif /* LIBXML_XPATH_ENABLED */

View File

@ -1541,6 +1541,9 @@ xmlCleanupPredefinedEntities
xmlXPathCeilingFunction
xmlXPathRoundFunction
xmlXPathBooleanFunction
/* really internal functions */
xmlXPathNodeSetFreeNs
#endif /* LIBXML_XPATH_ENABLED */

View File

@ -1489,7 +1489,7 @@ xmlXPathNodeSetDupNs(xmlNodePtr node, xmlNsPtr ns) {
* the namespace nodes are duplicated and the next pointer is set to the
* parent node in the XPath semantic. Check if such a node need to be freed
*/
static void
void
xmlXPathNodeSetFreeNs(xmlNsPtr ns) {
if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL))
return;
@ -8736,6 +8736,8 @@ xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
((cur->type == XML_DOCUMENT_NODE) ||
(cur->type == XML_HTML_DOCUMENT_NODE) ||
(cur->type == XML_ELEMENT_NODE) ||
(cur->type == XML_NAMESPACE_DECL) ||
(cur->type == XML_ATTRIBUTE_NODE) ||
(cur->type == XML_PI_NODE) ||
(cur->type == XML_COMMENT_NODE) ||
(cur->type == XML_CDATA_SECTION_NODE) ||