/* Test case, xmlNewNs() does not update associated namespaces of nodes
 */

#include <stdio.h>
#include <libxml/parser.h>

static const xmlChar example_xml[] =
  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
  "<ns1:root xmlns:ns1=\"http://ns1.namespace/root\" xmlns:ns2=\"http://ns2.namespace/root\">\n"
  "  <ns1:child>\n"
  "    <ns1:grandchild1/>\n"
  "    <ns2:grandchild2/>\n"
  "    <ns1:grandchild3 xmlns:ns1=\"http://ns1.namespace/grandchild\"/>\n"
  "  </ns1:child>\n"
  "</ns1:root>\n";

/* Print the namespace URI of a node */
static void print_node_ns(const xmlNodePtr node)
{
  if (node->ns && node->ns->href)
    printf("Node %s, namespace %s\n", node->name, node->ns->href);
  else
    printf("Node %s, no namespace\n", node->name);
}    

/* Print the namespace URIs of a document */
static void print_doc_ns(xmlDocPtr doc)
{
  xmlNodePtr curnode;

  curnode = xmlDocGetRootElement(doc);
  if (curnode == NULL)
  {
    printf("Empty document\n");
  	return;
  }
  
  /* Show the namespaces of the nodes. */

  /* Root element */
  print_node_ns(curnode);

  /* Child element */
  curnode = curnode->children;
  while (curnode && curnode->type != XML_ELEMENT_NODE)
    curnode = curnode->next;

  if (curnode == NULL)
  {
    printf("No child node\n");
    return;
  }
  print_node_ns(curnode);

  /* Grandchildren */
  curnode = curnode->children;
  while (curnode)
  {
    if (curnode->type == XML_ELEMENT_NODE)
      print_node_ns(curnode);
    curnode = curnode->next;
  }
}

int main(int argc, char** argv)
{
  xmlDocPtr doc;
  xmlNodePtr curnode;
  xmlNsPtr ns;

  /* Parse the document before modification */
  doc = xmlParseDoc(example_xml);
  if (doc == NULL)
  {
	  printf("Error parsing example_xml\n");
	  return 1;
	}

  /* Write the document before modification */
  xmlSaveFile("example1.xml", doc);

  /* Print namespaces before modification */
  printf("Before modification.\n");
  print_doc_ns(doc);

  /* Find the child node */
  curnode = xmlDocGetRootElement(doc);
  if (curnode == NULL)
  {
    printf("Empty document\n");
  	return 1;
  }

  curnode = curnode->children;
  while (curnode && curnode->type != XML_ELEMENT_NODE)
    curnode = curnode->next;

  if (curnode == NULL)
  {
    printf("No child node\n");
    return 1;
  }

  /* Add namespace definitions to the child node, overriding the namespace
   * definitions in the root node. */
  ns = xmlNewNs(curnode, (const xmlChar*)"http://ns1.namespace/child", (const xmlChar*)"ns1");
  if (ns == NULL)
  {
    printf("Could not create new ns1 namespace\n");
    return 1;
  }
  ns = xmlNewNs(curnode, (const xmlChar*)"http://ns2.namespace/child", (const xmlChar*)"ns2");
  if (ns == NULL)
  {
    printf("Could not create new ns2 namespace\n");
    return 1;
  }

  /* Print namespaces after modification */
  printf("\nAfter modification.\n");
  print_doc_ns(doc);

  /* Write and reparse the document after modification */
  if (xmlSaveFile("example2.xml", doc) < 0)
  {
    printf("Could not save modified document\n");
    return 1;
  }

  doc = xmlParseFile("example2.xml");
  if (doc == NULL)
  {
	  printf("Error parsing file example2.xml\n");
	  return 1;
	}

  /* Print namespaces after modification and reparsing */
  printf("\nAfter modification and reparsing.\n");
  print_doc_ns(doc);

  return 0;
}
