[xml] c14n 1.1 support (patch)



Daniel,

Please find attached a patch that adds support for the new
version of c14n (http://www.w3.org/TR/xml-c14n11/). I am
getting questions about it in the xmlsec mailing list and
I finally decided to implement it. I would greatly appreciate
if you can accept this patch and push it into the gnome git
repository (note, that there are some new files/folders added
for the new test cases).

Thank you in advance,
Aleksey Sanin



diff --git a/Makefile.am b/Makefile.am
index 800a766..236c26b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -923,7 +923,7 @@ VTimingtests: xmllint$(EXEEXT)
 
 C14Ntests : testC14N$(EXEEXT)
        @echo "## C14N and XPath regression tests"
-       -@(for m in with-comments without-comments exc-without-comments ; do \
+       -@(for m in with-comments without-comments 1-1-without-comments exc-without-comments ; do \
            for i in $(srcdir)/test/c14n/$$m/*.xml ; do  \
                if [ ! -d $$i ] ; then \
                    name=`basename $$i .xml`; \
diff --git a/c14n.c b/c14n.c
index f333297..5ebaeca 100644
--- a/c14n.c
+++ b/c14n.c
@@ -60,9 +60,11 @@ typedef struct _xmlC14NCtx {
     xmlC14NPosition pos;
     int parent_is_doc;
     xmlC14NVisibleNsStackPtr ns_rendered;
+    
+    /* C14N mode */
+    xmlC14NMode mode;
 
     /* exclusive canonicalization */
-    int exclusive;
     xmlChar **inclusive_ns_prefixes;
 
     /* error number */
@@ -91,8 +93,8 @@ static int                    xmlC14NIsNodeInNodeset          (xmlNodeSetPtr nodes,
 
 
 
-static int xmlC14NProcessNode(xmlC14NCtxPtr ctx, xmlNodePtr cur);
-static int xmlC14NProcessNodeList(xmlC14NCtxPtr ctx, xmlNodePtr cur);
+static int xmlC14NProcessNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int all_parents_visible);
+static int xmlC14NProcessNodeList(xmlC14NCtxPtr ctx, xmlNodePtr cur, int all_parents_visible);
 typedef enum {
     XMLC14N_NORMALIZE_ATTR = 0,
     XMLC14N_NORMALIZE_COMMENT = 1,
@@ -117,6 +119,9 @@ static xmlChar *xmlC11NNormalizeString(const xmlChar * input,
        (ctx)->is_visible_callback((ctx)->user_data, \
                (xmlNodePtr)(node), (xmlNodePtr)(parent)) : 1)
 
+#define        xmlC14NIsExclusive( ctx ) \
+    ( (ctx)->mode == XML_C14N_EXCLUSIVE_1_0 )
+
 /************************************************************************
  *                                                                     *
  *             Some factorized error routines                          *
@@ -492,9 +497,7 @@ xmlC14NIsXmlNs(xmlNsPtr ns)
 {
     return ((ns != NULL) &&
             (xmlStrEqual(ns->prefix, BAD_CAST "xml")) &&
-            (xmlStrEqual(ns->href,
-                         BAD_CAST
-                         "http://www.w3.org/XML/1998/namespace";)));
+            (xmlStrEqual(ns->href, XML_XML_NAMESPACE)));
 }
 
 
@@ -713,7 +716,7 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
         return (-1);
     }
 
-    if(!ctx->exclusive) {
+    if(!xmlC14NIsExclusive(ctx)) {
         xmlC14NErrParam("processing namespaces axis (exc c14n)");
         return (-1);
 
@@ -845,6 +848,25 @@ xmlExcC14NProcessNamespacesAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
 
 
 /**
+ * xmlC14NIsXmlAttr:
+ * @attr:              the attr to check
+ *             
+ * Checks whether the given attribute is a default "xml:" namespace
+ * with href="http://www.w3.org/XML/1998/namespace";
+ *
+ * Returns 1 if the node is default or 0 otherwise
+ */
+
+/* todo: make it a define? */
+static int
+xmlC14NIsXmlAttr(xmlAttrPtr attr)
+{
+    return ((attr->ns != NULL) && 
+           (xmlC14NIsXmlNs(attr->ns) != 0));
+}
+
+
+/**
  * xmlC14NAttrsCompare:
  * @attr1:             the pointer tls o first attr
  * @attr2:             the pointer to second attr
@@ -925,7 +947,7 @@ xmlC14NPrintAttrs(const xmlAttrPtr attr, xmlC14NCtxPtr ctx)
     xmlOutputBufferWriteString(ctx->buf, (const char *) attr->name);
     xmlOutputBufferWriteString(ctx->buf, "=\"");
 
-    value = xmlNodeListGetString(attr->doc, attr->children, 1);
+    value = xmlNodeListGetString(ctx->doc, attr->children, 1);
     /* todo: should we log an error if value==NULL ? */
     if (value != NULL) {
         buffer = xmlC11NNormalizeAttr(value);
@@ -942,11 +964,125 @@ xmlC14NPrintAttrs(const xmlAttrPtr attr, xmlC14NCtxPtr ctx)
     return (1);
 }
 
+
+/**
+ * xmlC14NAttrsCompare:
+ * @attr1:             the pointer tls o first attr
+ * @attr2:             the pointer to second attr
+ *
+ * Prints the given attribute to the output buffer from C14N context.
+ *
+ * Returns -1 if attr1 < attr2, 0 if attr1 == attr2 or 1 if attr1 > attr2.
+ */
+static xmlAttrPtr
+xmlC14NFindParentAttr(xmlNodePtr cur, const xmlChar * name, const xmlChar * ns)
+{
+    xmlAttrPtr res;
+    while(cur != NULL) {
+        res = xmlHasNsProp(cur, name, ns);
+        if(res != NULL) {
+            return res;
+        }
+
+        cur = cur->parent;
+    }
+
+    return NULL;
+}
+
+/**
+ * xmlC14NFixupBaseAttr:
+ *
+ * Fixes up the xml:base attribute
+ *
+ * Returns the newly created attribute or NULL
+ */
+static xmlAttrPtr
+xmlC14NFixupBaseAttr(xmlC14NCtxPtr ctx, xmlAttrPtr xml_base_attr)
+{    
+    xmlChar * res = NULL;
+    xmlNodePtr cur;
+    xmlAttrPtr attr;
+    xmlChar * tmp_str;
+    xmlChar * tmp_str2;
+
+    if ((ctx == NULL) || (xml_base_attr == NULL) || (xml_base_attr->parent == NULL)) {
+        xmlC14NErrParam("processing xml:base attribute");
+        return (NULL);
+    }
+
+    /* start from current value */
+    res = xmlNodeListGetString(ctx->doc, xml_base_attr->children, 1);
+    if(res == NULL) {
+        xmlC14NErrInternal("processing xml:base attribute - can't get attr value");
+        return (NULL);
+    }
+
+    /* go up the stack */
+    cur = xml_base_attr->parent->parent;
+    while(cur != NULL) {        
+        attr = xmlHasNsProp(cur, BAD_CAST "base", XML_XML_NAMESPACE);
+        if(attr != NULL){
+            /* check if we found a visible xml:base attribute and stop */
+            if(xmlC14NIsVisible(ctx, attr, cur)) {
+                break;
+            }
+
+            /* get attr value */
+            tmp_str = xmlNodeListGetString(ctx->doc, attr->children, 1);
+            if(tmp_str == NULL) {
+                xmlFree(res);
+
+                xmlC14NErrInternal("processing xml:base attribute - can't get attr value");
+                return (NULL);
+            } 
+
+            /* build uri */
+            tmp_str2 = xmlBuildURI(res, tmp_str); 
+            if(tmp_str2 == NULL) {
+                xmlFree(tmp_str);
+                xmlFree(res);
+
+                xmlC14NErrInternal("processing xml:base attribute - can't construct uri");
+                return (NULL);
+            }
+
+            /* cleanup and set the new res */
+            xmlFree(tmp_str);
+            xmlFree(res);
+            res = tmp_str2;
+        }
+
+        /* next */
+        cur = cur->parent;
+    }
+
+    /* check if result uri is empty or not */
+    if((res == NULL) || xmlStrEqual(res, BAD_CAST "")) {
+        xmlFree(res);
+        return (NULL);
+    }
+
+    /* create and return the new attribute node */
+    attr = xmlNewNsProp(NULL, xml_base_attr->ns, BAD_CAST "base", res);
+    if(attr == NULL) {
+        xmlFree(res);
+
+        xmlC14NErrInternal("processing xml:base attribute - can't construct attribute");
+        return (NULL);
+    }
+ 
+    /* done */
+    xmlFree(res);
+    return (attr);
+}
+
 /**
  * xmlC14NProcessAttrsAxis:
  * @ctx:               the C14N context
  * @cur:               the current node
  * @parent_visible:    the visibility of parent node
+ * @all_parents_visible: the visibility of all parent nodes
  *
  * Prints out canonical attribute axis of the current node to the
  * buffer from C14N context as follows 
@@ -975,10 +1111,16 @@ xmlC14NPrintAttrs(const xmlAttrPtr attr, xmlC14NCtxPtr ctx)
  * Returns 0 on success or -1 on fail.
  */
 static int
-xmlC14NProcessAttrsAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int parent_visible)
+xmlC14NProcessAttrsAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int parent_visible, int all_parents_visible)
 {
     xmlAttrPtr attr;
-    xmlListPtr list;
+    xmlListPtr list;    
+    xmlAttrPtr attrs_to_delete = NULL;
+    
+    /* special processing for 1.1 spec */
+    xmlAttrPtr xml_base_attr = NULL;
+    xmlAttrPtr xml_lang_attr = NULL;
+    xmlAttrPtr xml_space_attr = NULL;
 
     if ((ctx == NULL) || (cur == NULL) || (cur->type != XML_ELEMENT_NODE)) {
         xmlC14NErrParam("processing attributes axis");
@@ -994,42 +1136,183 @@ xmlC14NProcessAttrsAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int parent_visible)
         return (-1);
     }
 
-    /* 
-     * Add all visible attributes from current node. 
-     */
-    attr = cur->properties;
-    while (attr != NULL) {
-        /* check that attribute is visible */
-        if (xmlC14NIsVisible(ctx, attr, cur)) {
-            xmlListInsert(list, attr);
+    switch(ctx->mode) {
+    case XML_C14N_1_0:
+        /* The processing of an element node E MUST be modified slightly when an XPath node-set is 
+         * given as input and the element's parent is omitted from the node-set. The method for processing 
+         * the attribute axis of an element E in the node-set is enhanced. All element nodes along E's 
+         * ancestor axis are examined for nearest occurrences of attributes in the xml namespace, such 
+         * as xml:lang and xml:space (whether or not they are in the node-set). From this list of 
attributes, 
+         * remove any that are in E's attribute axis (whether or not they are in the node-set). Then, 
+         * lexicographically merge this attribute list with the nodes of E's attribute axis that are in 
+         * the node-set. The result of visiting the attribute axis is computed by processing the attribute 
+         * nodes in this merged attribute list. 
+         */
+    
+        /* 
+         * Add all visible attributes from current node. 
+         */
+        attr = cur->properties;
+        while (attr != NULL) {
+            /* check that attribute is visible */
+            if (xmlC14NIsVisible(ctx, attr, cur)) {
+                xmlListInsert(list, attr);
+            }
+            attr = attr->next;
         }
-        attr = attr->next;
-    }
 
-    /* 
-     * include attributes in "xml" namespace defined in ancestors
-     * (only for non-exclusive XML Canonicalization)
-     */
-    if (parent_visible && (!ctx->exclusive) && (cur->parent != NULL)
-        && (!xmlC14NIsVisible(ctx, cur->parent, cur->parent->parent))) {
-        /*
-         * If XPath node-set is not specified then the parent is always 
-         * visible!
+        /* 
+         * Handle xml attributes
          */
-        cur = cur->parent;
-        while (cur != NULL) {
-            attr = cur->properties;
-            while (attr != NULL) {
-                if ((attr->ns != NULL)
-                    && (xmlStrEqual(attr->ns->prefix, BAD_CAST "xml"))) {
-                    if (xmlListSearch(list, attr) == NULL) {
-                        xmlListInsert(list, attr);
+        if (parent_visible && (cur->parent != NULL) && 
+            (!xmlC14NIsVisible(ctx, cur->parent, cur->parent->parent))) 
+        {
+            xmlNodePtr tmp;
+
+            /*
+             * If XPath node-set is not specified then the parent is always 
+             * visible!
+             */
+            tmp = cur->parent;
+            while (tmp != NULL) {
+                attr = tmp->properties;
+                while (attr != NULL) {
+                    if (xmlC14NIsXmlAttr(attr) != 0) {
+                        if (xmlListSearch(list, attr) == NULL) {
+                            xmlListInsert(list, attr);
+                        }
                     }
+                    attr = attr->next;
                 }
-                attr = attr->next;
+                tmp = tmp->parent;
             }
-            cur = cur->parent;
         }
+
+        /* done */
+        break;
+    case XML_C14N_EXCLUSIVE_1_0:
+        /* attributes in the XML namespace, such as xml:lang and xml:space 
+         * are not imported into orphan nodes of the document subset 
+         */
+
+        /* 
+         * Add all visible attributes from current node. 
+         */
+        attr = cur->properties;
+        while (attr != NULL) {
+            /* check that attribute is visible */
+            if (xmlC14NIsVisible(ctx, attr, cur)) {
+                xmlListInsert(list, attr);
+            }
+            attr = attr->next;
+        }
+
+        /* do nothing special for xml attributes */
+        break;
+    case XML_C14N_1_1:
+        /* The processing of an element node E MUST be modified slightly when an XPath node-set is 
+         * given as input and some of the element's ancestors are omitted from the node-set. 
+         *
+         * Simple inheritable attributes are attributes that have a value that requires at most a simple 
+         * redeclaration. This redeclaration is done by supplying a new value in the child axis. The 
+         * redeclaration of a simple inheritable attribute A contained in one of E's ancestors is done 
+         * by supplying a value to an attribute Ae inside E with the same name. Simple inheritable 
attributes 
+         * are xml:lang and xml:space.
+         * 
+         * The method for processing the attribute axis of an element E in the node-set is hence enhanced. 
+         * All element nodes along E's ancestor axis are examined for the nearest occurrences of simple 
+         * inheritable attributes in the xml namespace, such as xml:lang and xml:space (whether or not they 
+         * are in the node-set). From this list of attributes, any simple inheritable attributes that are 
+         * already in E's attribute axis (whether or not they are in the node-set) are removed. Then, 
+         * lexicographically merge this attribute list with the nodes of E's attribute axis that are in 
+         * the node-set. The result of visiting the attribute axis is computed by processing the attribute 
+         * nodes in this merged attribute list.
+         * 
+         * The xml:id attribute is not a simple inheritable attribute and no processing of these attributes 
is 
+         * performed.
+         * 
+         * The xml:base attribute is not a simple inheritable attribute and requires special processing 
beyond 
+         * a simple redeclaration.
+         * 
+         * Attributes in the XML namespace other than xml:base, xml:id, xml:lang, and xml:space MUST be 
processed 
+         * as ordinary attributes.
+         */
+
+        /* 
+         * Add all visible attributes from current node. 
+         */
+        attr = cur->properties;
+        while (attr != NULL) {
+            /* special processing for XML attribute kiks in only when we have invisible parents */
+            if ((all_parents_visible) || (!parent_visible) || (xmlC14NIsXmlAttr(attr) == 0)) {
+                /* check that attribute is visible */
+                if (xmlC14NIsVisible(ctx, attr, cur)) {
+                    xmlListInsert(list, attr);
+                }
+            } else {
+                int matched = 0;
+
+                /* check for simple inheritance attributes */
+                if((!matched) && (xml_lang_attr == NULL) && xmlStrEqual(attr->name, BAD_CAST "lang")) {
+                    xml_lang_attr = attr;
+                    matched = 1;
+                } 
+                if((!matched) && (xml_space_attr == NULL) && xmlStrEqual(attr->name, BAD_CAST "space")) {
+                    xml_space_attr = attr;
+                    matched = 1;
+                }
+
+                /* check for base attr */
+                if((!matched) && (xml_base_attr == NULL) && xmlStrEqual(attr->name, BAD_CAST "base")) {
+                    xml_base_attr = attr;
+                    matched = 1;
+                }
+
+                /* otherwise, it is a normal attribute, so just check if it is visible */
+                if((!matched) && xmlC14NIsVisible(ctx, attr, cur)) {
+                    xmlListInsert(list, attr);
+                }
+            }
+         
+            /* move to the next one */
+            attr = attr->next;
+        }
+            
+        /* special processing for XML attribute kiks in only when we have invisible parents */
+        if ((!all_parents_visible) && (parent_visible)) {
+
+            /* simple inheritance attributes - copy */
+            if(xml_lang_attr == NULL) {
+                xml_lang_attr = xmlC14NFindParentAttr(cur->parent, BAD_CAST "lang", XML_XML_NAMESPACE);
+            }
+            if(xml_lang_attr != NULL) {
+                xmlListInsert(list, xml_lang_attr);
+            }
+            if(xml_space_attr == NULL) {
+                xml_space_attr = xmlC14NFindParentAttr(cur->parent, BAD_CAST "space", XML_XML_NAMESPACE);
+            }
+            if(xml_space_attr != NULL) {
+                xmlListInsert(list, xml_space_attr);
+            }
+
+            /* base uri attribute - fix up */
+            if(xml_base_attr == NULL) {
+                xml_base_attr = xmlC14NFindParentAttr(cur->parent, BAD_CAST "base", XML_XML_NAMESPACE);
+            }
+            if(xml_base_attr != NULL) {
+                xml_base_attr = xmlC14NFixupBaseAttr(ctx, xml_base_attr);
+                if(xml_base_attr != NULL) {                    
+                    xmlListInsert(list, xml_base_attr);
+
+                    /* note that we MUST delete returned attr node ourselves! */
+                    xml_base_attr->next = attrs_to_delete;
+                    attrs_to_delete = xml_base_attr;
+                }
+            }
+        }
+
+        /* done */
+        break;
     }
 
     /* 
@@ -1040,6 +1323,7 @@ xmlC14NProcessAttrsAxis(xmlC14NCtxPtr ctx, xmlNodePtr cur, int parent_visible)
     /* 
      * Cleanup
      */
+    xmlFreePropList(attrs_to_delete);
     xmlListDelete(list);
     return (0);
 }
@@ -1096,6 +1380,8 @@ xmlC14NCheckForRelativeNamespaces(xmlC14NCtxPtr ctx, xmlNodePtr cur)
  * xmlC14NProcessElementNode:
  * @ctx:               the pointer to C14N context object
  * @cur:               the node to process
+ * @visible:    this node is visible
+ * @all_parents_visible: whether all the parents of this node are visible
  *             
  * Canonical XML v 1.0 (http://www.w3.org/TR/xml-c14n)
  *
@@ -1114,7 +1400,7 @@ xmlC14NCheckForRelativeNamespaces(xmlC14NCtxPtr ctx, xmlNodePtr cur)
  * Returns non-negative value on success or negative value on fail
  */
 static int
-xmlC14NProcessElementNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
+xmlC14NProcessElementNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible, int all_parents_visible)
 {
     int ret;
     xmlC14NVisibleNsStack state;
@@ -1159,7 +1445,7 @@ xmlC14NProcessElementNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
         xmlOutputBufferWriteString(ctx->buf, (const char *) cur->name);
     }
 
-    if (!ctx->exclusive) {
+    if (!xmlC14NIsExclusive(ctx)) {
         ret = xmlC14NProcessNamespacesAxis(ctx, cur, visible);
     } else {
         ret = xmlExcC14NProcessNamespacesAxis(ctx, cur, visible);
@@ -1173,7 +1459,7 @@ xmlC14NProcessElementNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
        xmlC14NVisibleNsStackShift(ctx->ns_rendered);
     }
     
-    ret = xmlC14NProcessAttrsAxis(ctx, cur, visible);
+    ret = xmlC14NProcessAttrsAxis(ctx, cur, visible, (visible && all_parents_visible));
     if (ret < 0) {
        xmlC14NErrInternal("processing attributes axis");
        return (-1);
@@ -1183,7 +1469,7 @@ xmlC14NProcessElementNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
         xmlOutputBufferWriteString(ctx->buf, ">");
     }
     if (cur->children != NULL) {
-        ret = xmlC14NProcessNodeList(ctx, cur->children);
+        ret = xmlC14NProcessNodeList(ctx, cur->children, (visible && all_parents_visible));
         if (ret < 0) {
             xmlC14NErrInternal("processing childrens list");
             return (-1);
@@ -1222,7 +1508,7 @@ xmlC14NProcessElementNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int visible)
  * Returns non-negative value on success or negative value on fail
  */
 static int
-xmlC14NProcessNode(xmlC14NCtxPtr ctx, xmlNodePtr cur)
+xmlC14NProcessNode(xmlC14NCtxPtr ctx, xmlNodePtr cur, int all_parents_visible)
 {
     int ret = 0;
     int visible;
@@ -1235,7 +1521,7 @@ xmlC14NProcessNode(xmlC14NCtxPtr ctx, xmlNodePtr cur)
     visible = xmlC14NIsVisible(ctx, cur, cur->parent);
     switch (cur->type) {
         case XML_ELEMENT_NODE:
-            ret = xmlC14NProcessElementNode(ctx, cur, visible);
+            ret = xmlC14NProcessElementNode(ctx, cur, visible, all_parents_visible);
             break;
         case XML_CDATA_SECTION_NODE:
         case XML_TEXT_NODE:
@@ -1364,7 +1650,7 @@ xmlC14NProcessNode(xmlC14NCtxPtr ctx, xmlNodePtr cur)
             if (cur->children != NULL) {
                 ctx->pos = XMLC14N_BEFORE_DOCUMENT_ELEMENT;
                 ctx->parent_is_doc = 1;
-                ret = xmlC14NProcessNodeList(ctx, cur->children);
+                ret = xmlC14NProcessNodeList(ctx, cur->children, (visible && all_parents_visible));
             }
             break;
 
@@ -1413,7 +1699,7 @@ xmlC14NProcessNode(xmlC14NCtxPtr ctx, xmlNodePtr cur)
  * Returns non-negative value on success or negative value on fail
  */
 static int
-xmlC14NProcessNodeList(xmlC14NCtxPtr ctx, xmlNodePtr cur)
+xmlC14NProcessNodeList(xmlC14NCtxPtr ctx, xmlNodePtr cur, int all_parents_visible)
 {
     int ret;
 
@@ -1423,7 +1709,7 @@ xmlC14NProcessNodeList(xmlC14NCtxPtr ctx, xmlNodePtr cur)
     }
 
     for (ret = 0; cur != NULL && ret >= 0; cur = cur->next) {
-        ret = xmlC14NProcessNode(ctx, cur);
+        ret = xmlC14NProcessNode(ctx, cur, all_parents_visible);
     }
     return (ret);
 }
@@ -1457,9 +1743,10 @@ xmlC14NFreeCtx(xmlC14NCtxPtr ctx)
  *                     or not
  * @user_data:                 the first parameter for @is_visible_callback function
  *                     (in most cases, it is nodes set)
+ * @mode:   the c14n mode (see @xmlC14NMode)
  * @inclusive_ns_prefixe the list of inclusive namespace prefixes 
  *                     ended with a NULL or NULL if there is no
- *                     inclusive namespaces (only for exclusive 
+ *                     inclusive namespaces (only for ` 
  *                     canonicalization)
  * @with_comments:     include comments in the result (!=0) or not (==0)
  * @buf:               the output buffer to store canonical XML; this 
@@ -1473,7 +1760,7 @@ xmlC14NFreeCtx(xmlC14NCtxPtr ctx)
 static xmlC14NCtxPtr
 xmlC14NNewCtx(xmlDocPtr doc,  
              xmlC14NIsVisibleCallback is_visible_callback, void* user_data,
-              int exclusive, xmlChar ** inclusive_ns_prefixes,
+              xmlC14NMode mode, xmlChar ** inclusive_ns_prefixes,
               int with_comments, xmlOutputBufferPtr buf)
 {
     xmlC14NCtxPtr ctx = NULL;
@@ -1531,11 +1818,11 @@ xmlC14NNewCtx(xmlDocPtr doc,
     }
 
     /*
-     * Set "exclusive" flag, create a nodes set for namespaces
-     * stack and remember list of incluseve prefixes
+     * Set "mode" flag and remember list of incluseve prefixes
+     * for exclusive c14n
      */
-    if (exclusive) {
-        ctx->exclusive = 1;
+    ctx->mode = mode;
+    if(xmlC14NIsExclusive(ctx)) {
         ctx->inclusive_ns_prefixes = inclusive_ns_prefixes;
     }
     return (ctx);
@@ -1548,8 +1835,7 @@ xmlC14NNewCtx(xmlDocPtr doc,
  *                     or not
  * @user_data:                 the first parameter for @is_visible_callback function
  *                     (in most cases, it is nodes set)
- * @exclusive:         the exclusive flag (0 - non-exclusive canonicalization;
- *                     otherwise - exclusive canonicalization)
+ * @mode:      the c14n mode (see @xmlC14NMode)
  * @inclusive_ns_prefixes: the list of inclusive namespace prefixes 
  *                     ended with a NULL or NULL if there is no
  *                     inclusive namespaces (only for exclusive 
@@ -1567,7 +1853,7 @@ xmlC14NNewCtx(xmlDocPtr doc,
  */
 int            
 xmlC14NExecute(xmlDocPtr doc, xmlC14NIsVisibleCallback is_visible_callback,
-        void* user_data, int exclusive, xmlChar **inclusive_ns_prefixes,
+        void* user_data, xmlC14NMode mode, xmlChar **inclusive_ns_prefixes,
         int with_comments, xmlOutputBufferPtr buf) {
 
     xmlC14NCtxPtr ctx;
@@ -1588,7 +1874,7 @@ xmlC14NExecute(xmlDocPtr doc, xmlC14NIsVisibleCallback is_visible_callback,
     }
 
     ctx = xmlC14NNewCtx(doc, is_visible_callback, user_data, 
-                       exclusive, inclusive_ns_prefixes,
+                                   mode, inclusive_ns_prefixes,
                         with_comments, buf);
     if (ctx == NULL) {
         xmlC14NErr(NULL, (xmlNodePtr) doc, XML_C14N_CREATE_CTXT,
@@ -1607,7 +1893,7 @@ xmlC14NExecute(xmlDocPtr doc, xmlC14NIsVisibleCallback is_visible_callback,
      * declaration.
      */
     if (doc->children != NULL) {
-        ret = xmlC14NProcessNodeList(ctx, doc->children);
+        ret = xmlC14NProcessNodeList(ctx, doc->children, 1);
         if (ret < 0) {
             xmlC14NErrInternal("processing docs children list");
             xmlC14NFreeCtx(ctx);
@@ -1637,8 +1923,7 @@ xmlC14NExecute(xmlDocPtr doc, xmlC14NIsVisibleCallback is_visible_callback,
  * @doc:               the XML document for canonization
  * @nodes:             the nodes set to be included in the canonized image
  *                     or NULL if all document nodes should be included
- * @exclusive:         the exclusive flag (0 - non-exclusive canonicalization;
- *                     otherwise - exclusive canonicalization)
+ * @mode:              the c14n mode (see @xmlC14NMode)
  * @inclusive_ns_prefixes: the list of inclusive namespace prefixes 
  *                     ended with a NULL or NULL if there is no
  *                     inclusive namespaces (only for exclusive 
@@ -1656,12 +1941,12 @@ xmlC14NExecute(xmlDocPtr doc, xmlC14NIsVisibleCallback is_visible_callback,
  */
 int
 xmlC14NDocSaveTo(xmlDocPtr doc, xmlNodeSetPtr nodes,
-                 int exclusive, xmlChar ** inclusive_ns_prefixes,
+                 xmlC14NMode mode, xmlChar ** inclusive_ns_prefixes,
                  int with_comments, xmlOutputBufferPtr buf) {
     return(xmlC14NExecute(doc, 
                        (xmlC14NIsVisibleCallback)xmlC14NIsNodeInNodeset,
                        nodes,
-                       exclusive,
+                       mode,
                        inclusive_ns_prefixes,
                        with_comments,
                        buf));
@@ -1673,8 +1958,7 @@ xmlC14NDocSaveTo(xmlDocPtr doc, xmlNodeSetPtr nodes,
  * @doc:               the XML document for canonization
  * @nodes:             the nodes set to be included in the canonized image
  *                     or NULL if all document nodes should be included
- * @exclusive:         the exclusive flag (0 - non-exclusive canonicalization;
- *                     otherwise - exclusive canonicalization)
+ * @mode:              the c14n mode (see @xmlC14NMode)
  * @inclusive_ns_prefixes: the list of inclusive namespace prefixes 
  *                     ended with a NULL or NULL if there is no
  *                     inclusive namespaces (only for exclusive 
@@ -1692,7 +1976,7 @@ xmlC14NDocSaveTo(xmlDocPtr doc, xmlNodeSetPtr nodes,
  */
 int
 xmlC14NDocDumpMemory(xmlDocPtr doc, xmlNodeSetPtr nodes,
-                     int exclusive, xmlChar ** inclusive_ns_prefixes,
+                     xmlC14NMode mode, xmlChar ** inclusive_ns_prefixes,
                      int with_comments, xmlChar ** doc_txt_ptr)
 {
     int ret;
@@ -1717,7 +2001,7 @@ xmlC14NDocDumpMemory(xmlDocPtr doc, xmlNodeSetPtr nodes,
     /*
      * canonize document and write to buffer
      */
-    ret = xmlC14NDocSaveTo(doc, nodes, exclusive, inclusive_ns_prefixes,
+    ret = xmlC14NDocSaveTo(doc, nodes, mode, inclusive_ns_prefixes,
                            with_comments, buf);
     if (ret < 0) {
         xmlC14NErrInternal("saving doc to output buffer");
@@ -1743,8 +2027,7 @@ xmlC14NDocDumpMemory(xmlDocPtr doc, xmlNodeSetPtr nodes,
  * @doc:               the XML document for canonization
  * @nodes:             the nodes set to be included in the canonized image
  *                     or NULL if all document nodes should be included
- * @exclusive:         the exclusive flag (0 - non-exclusive canonicalization;
- *                     otherwise - exclusive canonicalization)
+ * @mode:              the c14n mode (see @xmlC14NMode)
  * @inclusive_ns_prefixes: the list of inclusive namespace prefixes 
  *                     ended with a NULL or NULL if there is no
  *                     inclusive namespaces (only for exclusive 
@@ -1764,7 +2047,7 @@ xmlC14NDocDumpMemory(xmlDocPtr doc, xmlNodeSetPtr nodes,
  */
 int
 xmlC14NDocSave(xmlDocPtr doc, xmlNodeSetPtr nodes,
-               int exclusive, xmlChar ** inclusive_ns_prefixes,
+               xmlC14NMode mode, xmlChar ** inclusive_ns_prefixes,
                int with_comments, const char *filename, int compression)
 {
     xmlOutputBufferPtr buf;
@@ -1791,7 +2074,7 @@ xmlC14NDocSave(xmlDocPtr doc, xmlNodeSetPtr nodes,
     /*
      * canonize document and write to buffer
      */
-    ret = xmlC14NDocSaveTo(doc, nodes, exclusive, inclusive_ns_prefixes,
+    ret = xmlC14NDocSaveTo(doc, nodes, mode, inclusive_ns_prefixes,
                            with_comments, buf);
     if (ret < 0) {
         xmlC14NErrInternal("cannicanize document to buffer");
diff --git a/include/libxml/c14n.h b/include/libxml/c14n.h
index a8aa737..0480a70 100644
--- a/include/libxml/c14n.h
+++ b/include/libxml/c14n.h
@@ -52,11 +52,22 @@ extern "C" {
  *    ...
  */
 
+/*
+ * xmlC14NMode:
+ * 
+ * Predefined values for C14N modes
+ *
+ */
+typedef enum {
+    XML_C14N_1_0            = 0,    /* Origianal C14N 1.0 spec */
+    XML_C14N_EXCLUSIVE_1_0  = 1,    /* Exclusive C14N 1.0 spec */
+    XML_C14N_1_1            = 2     /* C14N 1.1 spec */
+} xmlC14NMode;
 
 XMLPUBFUN int XMLCALL
                xmlC14NDocSaveTo        (xmlDocPtr doc,
                                         xmlNodeSetPtr nodes,
-                                        int exclusive,
+                                        xmlC14NMode mode,
                                         xmlChar **inclusive_ns_prefixes,
                                         int with_comments,
                                         xmlOutputBufferPtr buf);
@@ -64,7 +75,7 @@ XMLPUBFUN int XMLCALL
 XMLPUBFUN int XMLCALL
                xmlC14NDocDumpMemory    (xmlDocPtr doc,
                                         xmlNodeSetPtr nodes,
-                                        int exclusive,
+                                        xmlC14NMode mode,
                                         xmlChar **inclusive_ns_prefixes,
                                         int with_comments,
                                         xmlChar **doc_txt_ptr);
@@ -72,7 +83,7 @@ XMLPUBFUN int XMLCALL
 XMLPUBFUN int XMLCALL
                xmlC14NDocSave          (xmlDocPtr doc,
                                         xmlNodeSetPtr nodes,
-                                        int exclusive,
+                                        xmlC14NMode mode,
                                         xmlChar **inclusive_ns_prefixes,
                                         int with_comments,
                                         const char* filename,
@@ -100,7 +111,7 @@ XMLPUBFUN int XMLCALL
                xmlC14NExecute          (xmlDocPtr doc,
                                         xmlC14NIsVisibleCallback is_visible_callback,
                                         void* user_data,
-                                        int exclusive,
+                                        xmlC14NMode mode,
                                         xmlChar **inclusive_ns_prefixes,
                                         int with_comments,
                                         xmlOutputBufferPtr buf);
diff --git a/result/c14n/1-1-without-comments/example-1 b/result/c14n/1-1-without-comments/example-1
index e69de29..af9a977 100755
--- a/result/c14n/1-1-without-comments/example-1
+++ b/result/c14n/1-1-without-comments/example-1
@@ -0,0 +1,4 @@
+<?xml-stylesheet href="doc.xsl"
+   type="text/xsl"   ?>
+<doc>Hello, world!</doc>
+<?pi-without-data?>
\ No newline at end of file
diff --git a/result/c14n/1-1-without-comments/example-2 b/result/c14n/1-1-without-comments/example-2
index e69de29..2afa15c 100755
--- a/result/c14n/1-1-without-comments/example-2
+++ b/result/c14n/1-1-without-comments/example-2
@@ -0,0 +1,11 @@
+<doc>
+   <clean>   </clean>
+   <dirty>   A   B   </dirty>
+   <mixed>
+      A
+      <clean>   </clean>
+      B
+      <dirty>   A   B   </dirty>
+      C
+   </mixed>
+</doc>
\ No newline at end of file
diff --git a/result/c14n/1-1-without-comments/example-3 b/result/c14n/1-1-without-comments/example-3
index e69de29..4c287e6 100755
--- a/result/c14n/1-1-without-comments/example-3
+++ b/result/c14n/1-1-without-comments/example-3
@@ -0,0 +1,14 @@
+<doc>
+   <e1></e1>
+   <e2></e2>
+   <e3 id="elem3" name="elem3"></e3>
+   <e4 id="elem4" name="elem4"></e4>
+   <e5 xmlns="http://www.uvic.ca"; xmlns:a="http://www.w3.org"; xmlns:b="http://www.ietf.org"; attr="I'm" 
attr2="all" b:attr="sorted" a:attr="out"></e5>
+   <e6 xmlns:a="http://www.w3.org";>
+       <e7 xmlns="http://www.ietf.org";>
+           <e8 xmlns="">
+               <e9 xmlns:a="http://www.ietf.org"; attr="default"></e9>
+           </e8>
+       </e7>
+   </e6>
+</doc>
\ No newline at end of file
diff --git a/result/c14n/1-1-without-comments/example-4 b/result/c14n/1-1-without-comments/example-4
index e69de29..19a2559 100755
--- a/result/c14n/1-1-without-comments/example-4
+++ b/result/c14n/1-1-without-comments/example-4
@@ -0,0 +1,9 @@
+<doc>
+   <text>First line&#xD;
+Second line</text>
+   <value>2</value>
+   <compute>value&gt;"0" &amp;&amp; value&lt;"10" ?"valid":"error"</compute>
+   <compute expr="value>&quot;0&quot; &amp;&amp; value&lt;&quot;10&quot; 
?&quot;valid&quot;:&quot;error&quot;">valid</compute>
+   <norm attr=" '    &#xD;&#xA;&#x9;   ' "></norm>
+   <normId id="' &#xD;&#xA;&#x9; '"></normId>
+</doc>
\ No newline at end of file
diff --git a/result/c14n/1-1-without-comments/example-5 b/result/c14n/1-1-without-comments/example-5
index e69de29..c232e74 100755
--- a/result/c14n/1-1-without-comments/example-5
+++ b/result/c14n/1-1-without-comments/example-5
@@ -0,0 +1,3 @@
+<doc attrExtEnt="entExt">
+   Hello, world!
+</doc>
\ No newline at end of file
diff --git a/result/c14n/1-1-without-comments/example-6 b/result/c14n/1-1-without-comments/example-6
index e69de29..0be38f9 100755
--- a/result/c14n/1-1-without-comments/example-6
+++ b/result/c14n/1-1-without-comments/example-6
@@ -0,0 +1 @@
+<doc>©</doc>
\ No newline at end of file
diff --git a/result/c14n/1-1-without-comments/example-7 b/result/c14n/1-1-without-comments/example-7
index e69de29..0a96cc4 100755
--- a/result/c14n/1-1-without-comments/example-7
+++ b/result/c14n/1-1-without-comments/example-7
@@ -0,0 +1 @@
+<e1 xmlns="http://www.ietf.org"; xmlns:w3c="http://www.w3.org";><e3 xmlns="" id="E3" 
xml:space="preserve"></e3></e1>
\ No newline at end of file
diff --git a/result/c14n/1-1-without-comments/example-8 b/result/c14n/1-1-without-comments/example-8
index e69de29..4dcf5d5 100755
--- a/result/c14n/1-1-without-comments/example-8
+++ b/result/c14n/1-1-without-comments/example-8
@@ -0,0 +1 @@
+<e1 xmlns="http://www.ietf.org"; xmlns:w3c="http://www.w3.org"; 
xml:base="http://www.example.com/something/else";><e3 xmlns="" id="E3" 
xml:base="http://www.example.com/bar/foo"; xml:space="preserve"></e3></e1>
\ No newline at end of file
diff --git a/runtest.c b/runtest.c
index c7d11fa..5cf1320 100644
--- a/runtest.c
+++ b/runtest.c
@@ -3671,7 +3671,7 @@ parse_list(xmlChar *str) {
 }
 
 static int
-c14nRunTest(const char* xml_filename, int with_comments, int exclusive,
+c14nRunTest(const char* xml_filename, int with_comments, int mode,
            const char* xpath_filename, const char *ns_filename,
            const char* result_file) {
     xmlDocPtr doc;
@@ -3733,7 +3733,7 @@ c14nRunTest(const char* xml_filename, int with_comments, int exclusive,
     /* fprintf(stderr,"File \"%s\" loaded: start canonization\n", xml_filename); */
     ret = xmlC14NDocDumpMemory(doc,
            (xpath) ? xpath->nodesetval : NULL,
-           exclusive, inclusive_namespaces,
+           mode, inclusive_namespaces,
            with_comments, &result);
     if (ret >= 0) {
        if(result != NULL) {
@@ -3760,7 +3760,7 @@ c14nRunTest(const char* xml_filename, int with_comments, int exclusive,
 }
 
 static int
-c14nCommonTest(const char *filename, int with_comments, int exclusive,
+c14nCommonTest(const char *filename, int with_comments, int mode,
                const char *subdir) {
     char buf[500];
     char prefix[500];
@@ -3793,7 +3793,7 @@ c14nCommonTest(const char *filename, int with_comments, int exclusive,
     }
 
     nb_tests++;
-    if (c14nRunTest(filename, with_comments, exclusive,
+    if (c14nRunTest(filename, with_comments, mode,
                     xpath, ns, result) < 0)
         ret = 1;
 
@@ -3808,21 +3808,28 @@ c14nWithCommentTest(const char *filename,
                     const char *resul ATTRIBUTE_UNUSED,
                    const char *err ATTRIBUTE_UNUSED,
                    int options ATTRIBUTE_UNUSED) {
-    return(c14nCommonTest(filename, 1, 0, "with-comments"));
+    return(c14nCommonTest(filename, 1, XML_C14N_1_0, "with-comments"));
 }
 static int
 c14nWithoutCommentTest(const char *filename,
                     const char *resul ATTRIBUTE_UNUSED,
                    const char *err ATTRIBUTE_UNUSED,
                    int options ATTRIBUTE_UNUSED) {
-    return(c14nCommonTest(filename, 0, 0, "without-comments"));
+    return(c14nCommonTest(filename, 0, XML_C14N_1_0, "without-comments"));
 }
 static int
 c14nExcWithoutCommentTest(const char *filename,
                     const char *resul ATTRIBUTE_UNUSED,
                    const char *err ATTRIBUTE_UNUSED,
                    int options ATTRIBUTE_UNUSED) {
-    return(c14nCommonTest(filename, 0, 1, "exc-without-comments"));
+    return(c14nCommonTest(filename, 0, XML_C14N_EXCLUSIVE_1_0, "exc-without-comments"));
+}
+static int
+c14n11WithoutCommentTest(const char *filename,
+                    const char *resul ATTRIBUTE_UNUSED,
+                   const char *err ATTRIBUTE_UNUSED,
+                   int options ATTRIBUTE_UNUSED) {
+    return(c14nCommonTest(filename, 0, XML_C14N_1_1, "1-1-without-comments"));
 }
 #endif
 #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED) && defined (LIBXML_SAX1_ENABLED)
@@ -4257,6 +4264,9 @@ testDesc testDescriptions[] = {
     { "C14N exclusive without comments regression tests" ,
       c14nExcWithoutCommentTest, "./test/c14n/exc-without-comments/*.xml", NULL, NULL, NULL,
       0 },
+    { "C14N 1.1 without comments regression tests" ,
+      c14n11WithoutCommentTest, "./test/c14n/1-1-without-comments/*.xml", NULL, NULL, NULL,
+      0 },
 #endif
 #if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED) && defined(LIBXML_SAX1_ENABLED)
     { "Catalog and Threads regression tests" ,
diff --git a/test/.cvsignore b/test/.cvsignore
deleted file mode 100644
index c038ed7..0000000
--- a/test/.cvsignore
+++ /dev/null
@@ -1,2 +0,0 @@
-Makefile
-Makefile.in
\ No newline at end of file
diff --git a/test/c14n/1-1-without-comments/doc.dtd b/test/c14n/1-1-without-comments/doc.dtd
index e69de29..c460239 100755
--- a/test/c14n/1-1-without-comments/doc.dtd
+++ b/test/c14n/1-1-without-comments/doc.dtd
@@ -0,0 +1 @@
+<!-- Empty DTD -->
\ No newline at end of file
diff --git a/test/c14n/1-1-without-comments/example-1.xml b/test/c14n/1-1-without-comments/example-1.xml
index e69de29..ed450c7 100755
--- a/test/c14n/1-1-without-comments/example-1.xml
+++ b/test/c14n/1-1-without-comments/example-1.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+
+<?xml-stylesheet   href="doc.xsl"
+   type="text/xsl"   ?>
+
+<!DOCTYPE doc SYSTEM "doc.dtd">
+
+<doc>Hello, world!<!-- Comment 1 --></doc>
+
+<?pi-without-data     ?>
+
+<!-- Comment 2 -->
+
+<!-- Comment 3 -->
diff --git a/test/c14n/1-1-without-comments/example-2.xml b/test/c14n/1-1-without-comments/example-2.xml
index e69de29..74eeea1 100755
--- a/test/c14n/1-1-without-comments/example-2.xml
+++ b/test/c14n/1-1-without-comments/example-2.xml
@@ -0,0 +1,11 @@
+<doc>
+   <clean>   </clean>
+   <dirty>   A   B   </dirty>
+   <mixed>
+      A
+      <clean>   </clean>
+      B
+      <dirty>   A   B   </dirty>
+      C
+   </mixed>
+</doc>
diff --git a/test/c14n/1-1-without-comments/example-3.xml b/test/c14n/1-1-without-comments/example-3.xml
index e69de29..a7a1950 100755
--- a/test/c14n/1-1-without-comments/example-3.xml
+++ b/test/c14n/1-1-without-comments/example-3.xml
@@ -0,0 +1,18 @@
+<!DOCTYPE doc [<!ATTLIST e9 attr CDATA "default">]>
+<doc>
+   <e1   />
+   <e2   ></e2>
+   <e3    name = "elem3"   id="elem3"    />
+   <e4    name="elem4"   id="elem4"    ></e4>
+   <e5 a:attr="out" b:attr="sorted" attr2="all" attr="I'm"
+       xmlns:b="http://www.ietf.org"; 
+       xmlns:a="http://www.w3.org";
+       xmlns="http://www.uvic.ca"/>
+   <e6 xmlns="" xmlns:a="http://www.w3.org";>
+       <e7 xmlns="http://www.ietf.org";>
+           <e8 xmlns="" xmlns:a="http://www.w3.org";>
+               <e9 xmlns="" xmlns:a="http://www.ietf.org"/>
+           </e8>
+       </e7>
+   </e6>
+</doc>
diff --git a/test/c14n/1-1-without-comments/example-4.xml b/test/c14n/1-1-without-comments/example-4.xml
index e69de29..3fba138 100755
--- a/test/c14n/1-1-without-comments/example-4.xml
+++ b/test/c14n/1-1-without-comments/example-4.xml
@@ -0,0 +1,9 @@
+<!DOCTYPE doc [<!ATTLIST normId id ID #IMPLIED>]>
+<doc>
+   <text>First line&#x0d;&#10;Second line</text>
+   <value>&#x32;</value>
+   <compute><![CDATA[value>"0" && value<"10" ?"valid":"error"]]></compute>
+   <compute expr='value>"0" &amp;&amp; value&lt;"10" ?"valid":"error"'>valid</compute>
+   <norm attr=' &apos;   &#x20;&#13;&#xa;&#9;   &apos; '/>
+   <normId id=' &apos;   &#x20;&#13;&#xa;&#9;   &apos; '/>
+</doc>
diff --git a/test/c14n/1-1-without-comments/example-5.xml b/test/c14n/1-1-without-comments/example-5.xml
index e69de29..92c5322 100755
--- a/test/c14n/1-1-without-comments/example-5.xml
+++ b/test/c14n/1-1-without-comments/example-5.xml
@@ -0,0 +1,12 @@
+<!DOCTYPE doc [
+<!ATTLIST doc attrExtEnt ENTITY #IMPLIED>
+<!ENTITY ent1 "Hello">
+<!ENTITY ent2 SYSTEM "world.txt">
+<!ENTITY entExt SYSTEM "earth.gif" NDATA gif>
+<!NOTATION gif SYSTEM "viewgif.exe">
+]>
+<doc attrExtEnt="entExt">
+   &ent1;, &ent2;!
+</doc>
+
+<!-- Let world.txt contain "world" (excluding the quotes) -->
diff --git a/test/c14n/1-1-without-comments/example-6.xml b/test/c14n/1-1-without-comments/example-6.xml
index e69de29..31e2071 100755
--- a/test/c14n/1-1-without-comments/example-6.xml
+++ b/test/c14n/1-1-without-comments/example-6.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<doc>&#169;</doc>
diff --git a/test/c14n/1-1-without-comments/example-7.xml b/test/c14n/1-1-without-comments/example-7.xml
index e69de29..41171cb 100755
--- a/test/c14n/1-1-without-comments/example-7.xml
+++ b/test/c14n/1-1-without-comments/example-7.xml
@@ -0,0 +1,11 @@
+<!DOCTYPE doc [
+<!ATTLIST e2 xml:space (default|preserve) 'preserve'>
+<!ATTLIST e3 id ID #IMPLIED>
+]>
+<doc xmlns="http://www.ietf.org"; xmlns:w3c="http://www.w3.org";>
+   <e1>
+      <e2 xmlns="">
+         <e3 id="E3"/>
+      </e2>
+   </e1>
+</doc>
diff --git a/test/c14n/1-1-without-comments/example-7.xpath b/test/c14n/1-1-without-comments/example-7.xpath
index e69de29..84ddb08 100755
--- a/test/c14n/1-1-without-comments/example-7.xpath
+++ b/test/c14n/1-1-without-comments/example-7.xpath
@@ -0,0 +1,10 @@
+<XPath xmlns:ietf="http://www.ietf.org"; >
+    (//.|//@*|//namespace::*)
+    [
+       self::ietf:e1
+           or
+       (parent::ietf:e1 and not(self::text() or self::e2))
+           or
+       count(id("E3")|ancestor-or-self::node()) = count(ancestor-or-self::node())
+    ]
+</XPath>
\ No newline at end of file
diff --git a/test/c14n/1-1-without-comments/example-8.xml b/test/c14n/1-1-without-comments/example-8.xml
index e69de29..49568be 100755
--- a/test/c14n/1-1-without-comments/example-8.xml
+++ b/test/c14n/1-1-without-comments/example-8.xml
@@ -0,0 +1,11 @@
+<!DOCTYPE doc [
+<!ATTLIST e2 xml:space (default|preserve) 'preserve'>
+<!ATTLIST e3 id ID #IMPLIED>
+]>
+<doc xmlns="http://www.ietf.org"; xmlns:w3c="http://www.w3.org"; 
xml:base="http://www.example.com/something/else";>
+   <e1>
+      <e2 xmlns="" xml:id="abc" xml:base="../bar/">
+         <e3 id="E3" xml:base="foo"/>
+      </e2>
+   </e1>
+</doc>
diff --git a/test/c14n/1-1-without-comments/example-8.xpath b/test/c14n/1-1-without-comments/example-8.xpath
index e69de29..84ddb08 100755
--- a/test/c14n/1-1-without-comments/example-8.xpath
+++ b/test/c14n/1-1-without-comments/example-8.xpath
@@ -0,0 +1,10 @@
+<XPath xmlns:ietf="http://www.ietf.org"; >
+    (//.|//@*|//namespace::*)
+    [
+       self::ietf:e1
+           or
+       (parent::ietf:e1 and not(self::text() or self::e2))
+           or
+       count(id("E3")|ancestor-or-self::node()) = count(ancestor-or-self::node())
+    ]
+</XPath>
\ No newline at end of file
diff --git a/test/c14n/1-1-without-comments/world.txt b/test/c14n/1-1-without-comments/world.txt
index e69de29..04fea06 100755
--- a/test/c14n/1-1-without-comments/world.txt
+++ b/test/c14n/1-1-without-comments/world.txt
@@ -0,0 +1 @@
+world
\ No newline at end of file
diff --git a/test/c14n/with-comments/doc.dtd b/test/c14n/with-comments/doc.dtd
index e69de29..c460239 100644
--- a/test/c14n/with-comments/doc.dtd
+++ b/test/c14n/with-comments/doc.dtd
@@ -0,0 +1 @@
+<!-- Empty DTD -->
\ No newline at end of file
diff --git a/test/c14n/without-comments/doc.dtd b/test/c14n/without-comments/doc.dtd
index e69de29..c460239 100644
--- a/test/c14n/without-comments/doc.dtd
+++ b/test/c14n/without-comments/doc.dtd
@@ -0,0 +1 @@
+<!-- Empty DTD -->
\ No newline at end of file
diff --git a/testC14N.c b/testC14N.c
index 674fc71..ba70127 100644
--- a/testC14N.c
+++ b/testC14N.c
@@ -32,13 +32,17 @@ static void usage(const char *name) {
            name);
     fprintf(stderr, "where <mode> is one of following:\n");
     fprintf(stderr,
-       "--with-comments       \t XML file canonization w comments\n");
+       "--with-comments       \t XML file canonicalization v1.0 w comments \n");
     fprintf(stderr,
-       "--without-comments    \t XML file canonization w/o comments\n");
+       "--without-comments    \t XML file canonicalization v1.0 w/o comments\n");
     fprintf(stderr,
-    "--exc-with-comments   \t Exclusive XML file canonization w comments\n");
+       "--1-1-with-comments       \t XML file canonicalization v1.1 w comments\n");
     fprintf(stderr,
-    "--exc-without-comments\t Exclusive XML file canonization w/o comments\n");
+       "--1-1-without-comments    \t XML file canonicalization v1.1 w/o comments\n");
+    fprintf(stderr,
+    "--exc-with-comments   \t Exclusive XML file canonicalization v1.0 w comments\n");
+    fprintf(stderr,
+    "--exc-without-comments\t Exclusive XML file canonicalization v1.0 w/o comments\n");
 }
 
 static xmlXPathObjectPtr
@@ -49,7 +53,7 @@ static xmlChar **parse_list(xmlChar *str);
 /* static void print_xpath_nodes(xmlNodeSetPtr nodes); */
 
 static int 
-test_c14n(const char* xml_filename, int with_comments, int exclusive,
+test_c14n(const char* xml_filename, int with_comments, int mode,
        const char* xpath_filename, xmlChar **inclusive_namespaces) {
     xmlDocPtr doc;
     xmlXPathObjectPtr xpath = NULL; 
@@ -96,7 +100,7 @@ test_c14n(const char* xml_filename, int with_comments, int exclusive,
     /* fprintf(stderr,"File \"%s\" loaded: start canonization\n", xml_filename); */
     ret = xmlC14NDocDumpMemory(doc, 
            (xpath) ? xpath->nodesetval : NULL, 
-           exclusive, inclusive_namespaces,
+           mode, inclusive_namespaces,
            with_comments, &result);
     if(ret >= 0) {
        if(result != NULL) {
@@ -135,22 +139,26 @@ int main(int argc, char **argv) {
        fprintf(stderr, "Error: wrong number of arguments.\n");
        usage(argv[0]);
     } else if(strcmp(argv[1], "--with-comments") == 0) {
-       ret = test_c14n(argv[2], 1, 0, (argc > 3) ? argv[3] : NULL, NULL);
+       ret = test_c14n(argv[2], 1, XML_C14N_1_0, (argc > 3) ? argv[3] : NULL, NULL);
     } else if(strcmp(argv[1], "--without-comments") == 0) {
-       ret = test_c14n(argv[2], 0, 0, (argc > 3) ? argv[3] : NULL, NULL);
+       ret = test_c14n(argv[2], 0, XML_C14N_1_0, (argc > 3) ? argv[3] : NULL, NULL);
+    } else if(strcmp(argv[1], "--1-1-with-comments") == 0) {
+       ret = test_c14n(argv[2], 1, XML_C14N_1_1, (argc > 3) ? argv[3] : NULL, NULL);
+    } else if(strcmp(argv[1], "--1-1-without-comments") == 0) {
+       ret = test_c14n(argv[2], 0, XML_C14N_1_1, (argc > 3) ? argv[3] : NULL, NULL);
     } else if(strcmp(argv[1], "--exc-with-comments") == 0) {
        xmlChar **list;
        
        /* load exclusive namespace from command line */
        list = (argc > 4) ? parse_list((xmlChar *)argv[4]) : NULL;
-       ret = test_c14n(argv[2], 1, 1, (argc > 3) ? argv[3] : NULL, list);
+       ret = test_c14n(argv[2], 1, XML_C14N_EXCLUSIVE_1_0, (argc > 3) ? argv[3] : NULL, list);
        if(list != NULL) xmlFree(list);
     } else if(strcmp(argv[1], "--exc-without-comments") == 0) {
        xmlChar **list;
        
        /* load exclusive namespace from command line */
        list = (argc > 4) ? parse_list((xmlChar *)argv[4]) : NULL;
-       ret = test_c14n(argv[2], 0, 1, (argc > 3) ? argv[3] : NULL, list);
+       ret = test_c14n(argv[2], 0, XML_C14N_EXCLUSIVE_1_0, (argc > 3) ? argv[3] : NULL, list);
        if(list != NULL) xmlFree(list);
     } else {
        fprintf(stderr, "Error: bad option.\n");
diff --git a/xmllint.c b/xmllint.c
index 77c1e62..a668570 100644
--- a/xmllint.c
+++ b/xmllint.c
@@ -184,6 +184,7 @@ static int nocatalogs = 0;
 #endif
 #ifdef LIBXML_C14N_ENABLED
 static int canonical = 0;
+static int canonical_11 = 0;
 static int exc_canonical = 0;
 #endif
 #ifdef LIBXML_READER_ENABLED
@@ -2429,7 +2430,19 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) {
                xmlChar *result = NULL;
                int size;
 
-               size = xmlC14NDocDumpMemory(doc, NULL, 0, NULL, 1, &result);
+               size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_1_0, NULL, 1, &result);
+               if (size >= 0) {
+                   write(1, result, size);
+                   xmlFree(result);
+               } else {
+                   fprintf(stderr, "Failed to canonicalize\n");
+                   progresult = XMLLINT_ERR_OUT;
+               }
+           } else if (canonical) {
+               xmlChar *result = NULL;
+               int size;
+
+               size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_1_1, NULL, 1, &result);
                if (size >= 0) {
                    write(1, result, size);
                    xmlFree(result);
@@ -2442,7 +2455,7 @@ static void parseAndPrintFile(char *filename, xmlParserCtxtPtr rectxt) {
                xmlChar *result = NULL;
                int size;
 
-               size = xmlC14NDocDumpMemory(doc, NULL, 1, NULL, 1, &result);
+               size = xmlC14NDocDumpMemory(doc, NULL, XML_C14N_EXCLUSIVE_1_0, NULL, 1, &result);
                if (size >= 0) {
                    write(1, result, size);
                    xmlFree(result);
@@ -2878,7 +2891,8 @@ static void usage(const char *name) {
     printf("\t--encode encoding : output in the given encoding\n");
     printf("\t--dropdtd : remove the DOCTYPE of the input docs\n");
 #endif /* LIBXML_OUTPUT_ENABLED */
-    printf("\t--c14n : save in W3C canonical format (with comments)\n");
+    printf("\t--c14n : save in W3C canonical format v1.0 (with comments)\n");
+    printf("\t--c14n11 : save in W3C canonical format v1.1 (with comments)\n");
     printf("\t--exc-c14n : save in W3C exclusive canonical format (with comments)\n");
 #ifdef LIBXML_C14N_ENABLED
 #endif /* LIBXML_C14N_ENABLED */
@@ -3141,6 +3155,11 @@ main(int argc, char **argv) {
            canonical++;
            options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
        } 
+       else if ((!strcmp(argv[i], "-c14n11")) ||
+                (!strcmp(argv[i], "--c14n11"))) {
+           canonical_11++;
+           options |= XML_PARSE_NOENT | XML_PARSE_DTDATTR | XML_PARSE_DTDLOAD;
+       } 
        else if ((!strcmp(argv[i], "-exc-c14n")) ||
                 (!strcmp(argv[i], "--exc-c14n"))) {
            exc_canonical++;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]