Logo Search packages:      
Sourcecode: libupnp4 version File versions  Download package

node.c

Go to the documentation of this file.
/*******************************************************************************
 *
 * Copyright (c) 2000-2003 Intel Corporation 
 * All rights reserved. 
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met: 
 *
 * - Redistributions of source code must retain the above copyright notice, 
 * this list of conditions and the following disclaimer. 
 * - Redistributions in binary form must reproduce the above copyright notice, 
 * this list of conditions and the following disclaimer in the documentation 
 * and/or other materials provided with the distribution. 
 * - Neither name of Intel Corporation nor the names of its contributors 
 * may be used to endorse or promote products derived from this software 
 * without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR 
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 ******************************************************************************/


/*!
 * \file
 */


#include "ixmlparser.h"


#include <assert.h>
#include <stdlib.h> /* for free(), malloc() */
#include <string.h>


void ixmlNode_init(IXML_Node *nodeptr)
{
      assert(nodeptr != NULL);

      memset(nodeptr, 0, sizeof (IXML_Node));
}


00054 void ixmlCDATASection_init(IXML_CDATASection *nodeptr)
{
      memset(nodeptr, 0, sizeof (IXML_CDATASection));
}


00060 void ixmlCDATASection_free(IXML_CDATASection *nodeptr)
{
      if (nodeptr != NULL) {
            ixmlNode_free((IXML_Node *)nodeptr);
      }
}


/*!
 * \brief Frees a node content.
 */
00071 static void ixmlNode_freeSingleNode(
      /*! [in] The node to free. */
      IXML_Node *nodeptr)
{
      IXML_Element *element = NULL;

      if (nodeptr != NULL) {
            if (nodeptr->nodeName != NULL) {
                  free(nodeptr->nodeName);
            }
            if (nodeptr->nodeValue != NULL) {
                  free(nodeptr->nodeValue);
            }
            if (nodeptr->namespaceURI != NULL) {
                  free(nodeptr->namespaceURI);
            }
            if (nodeptr->prefix != NULL) {
                  free(nodeptr->prefix);
            }
            if (nodeptr->localName != NULL) {
                  free(nodeptr->localName);
            }
            if (nodeptr->nodeType == eELEMENT_NODE) {
                  element = (IXML_Element *)nodeptr;
                  free(element->tagName);
            }
            free(nodeptr);
      }
}


00102 void ixmlNode_free(IXML_Node *nodeptr)
{
      if (nodeptr != NULL) {
            ixmlNode_free(nodeptr->firstChild);
            ixmlNode_free(nodeptr->nextSibling);
            ixmlNode_free(nodeptr->firstAttr);
            ixmlNode_freeSingleNode(nodeptr);
      }
}


00113 const DOMString ixmlNode_getNodeName(IXML_Node *nodeptr)
{
      if(nodeptr != NULL) {
            return nodeptr->nodeName;
      }

      return NULL;
}


00123 const DOMString ixmlNode_getLocalName(IXML_Node *nodeptr)
{
      if (nodeptr != NULL) {
            return nodeptr->localName;
      }

      return NULL;
}


/*!
 * \brief Sets the namespace URI of the node.
 */
00136 static int ixmlNode_setNamespaceURI(
      /*! [in] The \b Node on which to operate. */
      IXML_Node *nodeptr,
      /*! [in] The name space string to set. */
      const char *namespaceURI)
{
      if (nodeptr == NULL) {
            return IXML_INVALID_PARAMETER;
      }

      if (nodeptr->namespaceURI != NULL) {
            free(nodeptr->namespaceURI);
            nodeptr->namespaceURI = NULL;
      }

      if (namespaceURI != NULL) {
            nodeptr->namespaceURI = strdup(namespaceURI);
            if (nodeptr->namespaceURI == NULL) {
                  return IXML_INSUFFICIENT_MEMORY;
            }
      }

      return IXML_SUCCESS;
}


/*
 * \brief Set the prefix of the node.
 */
00165 static int ixmlNode_setPrefix(
      /*! [in] The \b Node on which to operate. */
      IXML_Node *nodeptr,
      /*! [in] The prefix string to set. */
      const char *prefix)
{
      if (nodeptr == NULL) {
            return IXML_INVALID_PARAMETER;
      }

      if (nodeptr->prefix != NULL) {
            free(nodeptr->prefix);
            nodeptr->prefix = NULL;
      }

      if (prefix != NULL) {
            nodeptr->prefix = strdup(prefix);
            if(nodeptr->prefix == NULL) {
                  return IXML_INSUFFICIENT_MEMORY;
            }
      }

      return IXML_SUCCESS;
}


/*!
 * \brief Set the localName of the node.
 *
 * \return IXML_SUCCESS or failure.
 */
00196 static int ixmlNode_setLocalName(
      /*! [in] The pointer to the node. */
      IXML_Node *nodeptr,
      /*! [in] The local name to set. */
      const char *localName)
{
      assert(nodeptr != NULL);

      if (nodeptr->localName != NULL) {
            free(nodeptr->localName);
            nodeptr->localName = NULL;
      }

      if (localName != NULL) {
            nodeptr->localName = strdup(localName);
            if (nodeptr->localName == NULL) {
                  return IXML_INSUFFICIENT_MEMORY;
            }
      }

      return IXML_SUCCESS;
}


00220 const DOMString ixmlNode_getNamespaceURI(IXML_Node *nodeptr)
{
      DOMString retNamespaceURI = NULL;

      if (nodeptr != NULL) {
            retNamespaceURI = nodeptr->namespaceURI;
      }

      return retNamespaceURI;
}


00232 const DOMString ixmlNode_getPrefix(IXML_Node *nodeptr)
{
      const DOMString prefix = NULL;

      if (nodeptr != NULL) {
            prefix = nodeptr->prefix;
      }

      return prefix;
}


00244 const DOMString ixmlNode_getNodeValue(IXML_Node *nodeptr)
{
      if ( nodeptr != NULL ) {
            return nodeptr->nodeValue;
      }

      return NULL;
}


00254 int ixmlNode_setNodeValue(IXML_Node *nodeptr, const char *newNodeValue)
{
      int rc = IXML_SUCCESS;

      if (nodeptr == NULL) {
            return IXML_INVALID_PARAMETER;
      }

      if (nodeptr->nodeValue != NULL) {
            free(nodeptr->nodeValue);
            nodeptr->nodeValue = NULL;
      }

      if (newNodeValue != NULL) {
            nodeptr->nodeValue = strdup(newNodeValue);
            if (nodeptr->nodeValue == NULL) {
                  return IXML_INSUFFICIENT_MEMORY;
            }
      }

      return rc;
}


00278 unsigned short ixmlNode_getNodeType(IXML_Node *nodeptr)
{
      if (nodeptr != NULL) {
            return nodeptr->nodeType;
      } else {
            return eINVALID_NODE;
      }
}


00288 IXML_Node *ixmlNode_getParentNode(IXML_Node *nodeptr)
{
      if (nodeptr != NULL) {
            return nodeptr->parentNode;
      } else {
            return NULL;
      }
}


00298 IXML_Node *ixmlNode_getFirstChild(IXML_Node *nodeptr)
{
      if (nodeptr != NULL) {
            return nodeptr->firstChild;
      } else {
            return NULL;
      }
}


00308 IXML_Node *ixmlNode_getLastChild(IXML_Node *nodeptr)
{
      IXML_Node *prev;
      IXML_Node *next;

      if (nodeptr != NULL) {
            prev = nodeptr;
            next = nodeptr->firstChild;
            while (next != NULL) {
                  prev = next;
                  next = next->nextSibling;
            }
            return prev;
      } else {
            return NULL;
      }
}


00327 IXML_Node *ixmlNode_getPreviousSibling(IXML_Node *nodeptr)
{
      if (nodeptr != NULL) {
            return nodeptr->prevSibling;
      } else {
            return NULL;
      }
}


00337 IXML_Node *ixmlNode_getNextSibling(IXML_Node *nodeptr)
{
      if (nodeptr != NULL) {
            return nodeptr->nextSibling;
      } else {
            return NULL;
      }
}


00347 IXML_Document *ixmlNode_getOwnerDocument(IXML_Node *nodeptr)
{
      if (nodeptr != NULL) {
            return (IXML_Document *)nodeptr->ownerDocument;
      } else {
            return NULL;
      }
}

/*!
 * \brief Check if ancestorNode is ancestor of toFind.
 *
 * \return TRUE or FALSE.
 */
00361 static BOOL ixmlNode_isAncestor(
      /*! [in] The candidate to ancestor \b Node. */
      IXML_Node *ancestorNode,
      /*! [in] The \b Node to check for an ancestor. */
      IXML_Node *toFind)
{
      BOOL found = FALSE;

      if (ancestorNode != NULL && toFind != NULL) {
            if (toFind->parentNode == ancestorNode) {
                  return TRUE;
            } else {
                  found = ixmlNode_isAncestor(
                        ancestorNode->firstChild, toFind);
                  if (found == FALSE) {
                        found = ixmlNode_isAncestor(
                              ancestorNode->nextSibling, toFind);
                  }
            }
      }

      return found;
}

/*!
 * \brief Check whether toFind is a children of nodeptr.
 *
 * \return TRUE or FALSE.
 */
00390 static BOOL ixmlNode_isParent(
      /*! [in] The candidate to parent \b Node. */
      IXML_Node *nodeptr,
      /*! [in] The \b Node to check for his parent. */
      IXML_Node *toFind)
{
      BOOL found = FALSE;

      assert(nodeptr != NULL && toFind != NULL);

      found = toFind->parentNode == nodeptr;

      return found;
}

/*!
 * \brief Check to see whether nodeptr allows children of type newChild.    
 *
 * \return
 *    \li TRUE, if nodeptr can have newChild as children.
 *    \li FALSE, if nodeptr cannot have newChild as children.
 */
00412 static BOOL ixmlNode_allowChildren(
      /*! [in] The \b Node to check. */
      IXML_Node *nodeptr,
      /*! [in] The child \b Node to check. */
      IXML_Node *newChild)
{
      assert(nodeptr != NULL && newChild != NULL);

      switch (nodeptr->nodeType) {
      case eATTRIBUTE_NODE:
      case eTEXT_NODE:
      case eCDATA_SECTION_NODE:
            return FALSE;
            break;

      case eELEMENT_NODE:
            if (newChild->nodeType == eATTRIBUTE_NODE ||
                newChild->nodeType == eDOCUMENT_NODE) {
                  return FALSE;
            }
      break;

      case eDOCUMENT_NODE:
            if (newChild->nodeType != eELEMENT_NODE) {
                  return FALSE;
            }

      default:
            break;
      }

      return TRUE;
}


/*!
 * \brief Compare two nodes to see whether they are the same node.
 * Parent, sibling and children node are ignored.
 *
 * \return
 *    \li TRUE, the two nodes are the same.
 *    \li FALSE, the two nodes are not the same.
 */
00455 BOOL ixmlNode_compare(
      /*! [in] The first \b Node. */
      IXML_Node *srcNode,
      /*! [in] The second \b Node. */
      IXML_Node *destNode)
{
      assert(srcNode != NULL && destNode != NULL);

      return 
            srcNode == destNode ||
      (strcmp(srcNode->nodeName, destNode->nodeName) == 0 &&
       strcmp(srcNode->nodeValue, destNode->nodeValue) == 0 &&
       srcNode->nodeType == destNode->nodeType &&
       strcmp(srcNode->namespaceURI, destNode->namespaceURI) == 0 &&
       strcmp(srcNode->prefix, destNode->prefix) == 0 &&
       strcmp(srcNode->localName, destNode->localName) == 0);
}


00474 int ixmlNode_insertBefore(
      IXML_Node *nodeptr,
      IXML_Node *newChild,
      IXML_Node *refChild)
{
      int ret = IXML_SUCCESS;

      if (nodeptr == NULL || newChild == NULL) {
            return IXML_INVALID_PARAMETER;
      }
      /* whether nodeptr allow children of the type of newChild */
      if (ixmlNode_allowChildren(nodeptr, newChild) == FALSE) {
            return IXML_HIERARCHY_REQUEST_ERR;
      }
      /* or if newChild is one of nodeptr's ancestors */
      if (ixmlNode_isAncestor(newChild, nodeptr) == TRUE) {
            return IXML_HIERARCHY_REQUEST_ERR;
      }
      /* if newChild was created from a different document */
      if (nodeptr->ownerDocument != newChild->ownerDocument) {
            return IXML_WRONG_DOCUMENT_ERR;
      }
      /* if refChild is not a child of nodeptr */
      if (ixmlNode_isParent(nodeptr, refChild) == FALSE) {
            return IXML_NOT_FOUND_ERR;
      }

      if (refChild != NULL) {
            if (ixmlNode_isParent(nodeptr, newChild) == TRUE) {
                  ixmlNode_removeChild(nodeptr, newChild, NULL);
                  newChild->nextSibling = NULL;
                  newChild->prevSibling = NULL;
            }
            newChild->nextSibling = refChild;
            if (refChild->prevSibling != NULL) {
                  refChild->prevSibling->nextSibling = newChild;
                  newChild->prevSibling = refChild->prevSibling;
            }
            refChild->prevSibling = newChild;
            if (newChild->prevSibling == NULL) {
                  nodeptr->firstChild = newChild;
            }
            newChild->parentNode = nodeptr;
      } else {
            ret = ixmlNode_appendChild( nodeptr, newChild );
      }

      return ret;
}


00525 int ixmlNode_replaceChild(
      IXML_Node *nodeptr,
      IXML_Node *newChild,
      IXML_Node *oldChild,
      IXML_Node **returnNode)
{
      int ret = IXML_SUCCESS;

      if (nodeptr == NULL || newChild == NULL || oldChild == NULL) {
            return IXML_INVALID_PARAMETER;
      }
      /* if nodetype of nodeptr does not allow children of the type of newChild
       * needs to add later or if newChild is one of nodeptr's ancestors */
      if (ixmlNode_isAncestor(newChild, nodeptr) == TRUE) {
            return IXML_HIERARCHY_REQUEST_ERR;
      }

      if (ixmlNode_allowChildren(nodeptr, newChild) == FALSE) {
            return IXML_HIERARCHY_REQUEST_ERR;
      }
      // if newChild was created from a different document 
      if (nodeptr->ownerDocument != newChild->ownerDocument) {
            return IXML_WRONG_DOCUMENT_ERR;
      }
      // if refChild is not a child of nodeptr
      if (ixmlNode_isParent(nodeptr, oldChild) != TRUE) {
            return IXML_NOT_FOUND_ERR;
      }

      ret = ixmlNode_insertBefore(nodeptr, newChild, oldChild);
      if (ret != IXML_SUCCESS) {
            return ret;
      }

      ret = ixmlNode_removeChild(nodeptr, oldChild, returnNode);
      return ret;
}


00564 int ixmlNode_removeChild(
      IXML_Node *nodeptr,
      IXML_Node *oldChild,
      IXML_Node **returnNode)
{
      if (nodeptr == NULL || oldChild == NULL) {
            return IXML_INVALID_PARAMETER;
      }

      if (ixmlNode_isParent(nodeptr, oldChild) == FALSE ) {
            return IXML_NOT_FOUND_ERR;
      }

      if (oldChild->prevSibling != NULL) {
            oldChild->prevSibling->nextSibling = oldChild->nextSibling;
      }
      if (nodeptr->firstChild == oldChild) {
            nodeptr->firstChild = oldChild->nextSibling;
      }
      if (oldChild->nextSibling != NULL) {
            oldChild->nextSibling->prevSibling = oldChild->prevSibling;
      }
      oldChild->nextSibling = NULL;
      oldChild->prevSibling = NULL;
      oldChild->parentNode = NULL;
      if (returnNode != NULL) {
            *returnNode = oldChild;
      }

      return IXML_SUCCESS;
}


00597 int ixmlNode_appendChild(IXML_Node *nodeptr, IXML_Node *newChild)
{
      IXML_Node *prev = NULL;
      IXML_Node *next = NULL;

      if (nodeptr == NULL || newChild == NULL) {
            return IXML_INVALID_PARAMETER;
      }
      /* if newChild was created from a different document */
      if (newChild->ownerDocument != NULL &&
          nodeptr->ownerDocument != newChild->ownerDocument) {
            return IXML_WRONG_DOCUMENT_ERR;
      }
      /* if newChild is an ancestor of nodeptr */
      if (ixmlNode_isAncestor(newChild, nodeptr) == TRUE) {
            return IXML_HIERARCHY_REQUEST_ERR;
      }
      /* if nodeptr does not allow to have newChild as children */
      if (ixmlNode_allowChildren(nodeptr, newChild) == FALSE) {
            return IXML_HIERARCHY_REQUEST_ERR;
      }

      if (ixmlNode_isParent(nodeptr, newChild) == TRUE ) {
            ixmlNode_removeChild(nodeptr, newChild, NULL);
      }
      /* set the parent node pointer */
      newChild->parentNode = nodeptr;
      newChild->ownerDocument = nodeptr->ownerDocument;

      /* if the first child */
      if (nodeptr->firstChild == NULL) {
            nodeptr->firstChild = newChild;
      } else {
            prev = nodeptr->firstChild;
            next = prev->nextSibling;
            while (next != NULL) {
                  prev = next;
                  next = prev->nextSibling;
            }
            prev->nextSibling = newChild;
            newChild->prevSibling = prev;
      }

      return IXML_SUCCESS;
}

/*!
 * \brief Returns a clone of nodeptr.
 *
 * \return A cloned node of nodeptr.
 */
00648 static IXML_Node *ixmlNode_cloneTextNode(
      /*! [in] The \b Node to clone. */
      IXML_Node *nodeptr)
{
      IXML_Node *newNode = NULL;

      assert(nodeptr != NULL);

      newNode = (IXML_Node *)malloc(sizeof (IXML_Node));
      if (newNode == NULL) {
            return NULL;
      } else {
            ixmlNode_init(newNode);
            ixmlNode_setNodeName(newNode, nodeptr->nodeName);
            ixmlNode_setNodeValue(newNode, nodeptr->nodeValue);
            newNode->nodeType = eTEXT_NODE;
      }

      return newNode;
}

/*!
 * \brief Return a clone of CDATASection node.
 *
 * \return A clone of CDATASection node.
 */
00674 static IXML_CDATASection *ixmlNode_cloneCDATASect(
      /*! [in] The \b Node to clone. */
      IXML_CDATASection *nodeptr)
{
      IXML_CDATASection *newCDATA = NULL;
      IXML_Node *newNode;
      IXML_Node *srcNode;

      assert(nodeptr != NULL);
      newCDATA = (IXML_CDATASection *)malloc(sizeof (IXML_CDATASection));
      if (newCDATA != NULL) {
            newNode = (IXML_Node *)newCDATA;
            ixmlNode_init(newNode);
            srcNode = (IXML_Node *)nodeptr;
            ixmlNode_setNodeName(newNode, srcNode->nodeName);
            ixmlNode_setNodeValue(newNode, srcNode->nodeValue);
            newNode->nodeType = eCDATA_SECTION_NODE;
      }

      return newCDATA;
}


/*!
 * \brief Returns a clone of element node.
 *
 * \return A clone of element node.
 */
00702 static IXML_Element *ixmlNode_cloneElement(
      /*! [in] The \b Node to clone. */
      IXML_Element *nodeptr)
{
      IXML_Element *newElement;
      IXML_Node *elementNode;
      IXML_Node *srcNode;
      int rc;

      assert(nodeptr != NULL);

      newElement = (IXML_Element *)malloc(sizeof (IXML_Element));
      if (newElement == NULL) {
            return NULL;
      }

      ixmlElement_init(newElement);
      rc = ixmlElement_setTagName(newElement, nodeptr->tagName);
      if (rc != IXML_SUCCESS) {
            ixmlElement_free(newElement);
            return NULL;
      }

      elementNode = (IXML_Node *)newElement;
      srcNode = (IXML_Node *)nodeptr;
      rc = ixmlNode_setNodeName(elementNode, srcNode->nodeName);
      if (rc != IXML_SUCCESS) {
            ixmlElement_free(newElement);
            return NULL;
      }

      rc = ixmlNode_setNodeValue(elementNode, srcNode->nodeValue);
      if (rc != IXML_SUCCESS) {
            ixmlElement_free(newElement);
            return NULL;
      }

      rc = ixmlNode_setNamespaceURI(elementNode, srcNode->namespaceURI);
      if (rc != IXML_SUCCESS) {
            ixmlElement_free(newElement);
            return NULL;
      }

      rc = ixmlNode_setPrefix(elementNode, srcNode->prefix);
      if (rc != IXML_SUCCESS) {
            ixmlElement_free(newElement);
            return NULL;
      }

      rc = ixmlNode_setLocalName(elementNode, srcNode->localName);
      if (rc != IXML_SUCCESS) {
            ixmlElement_free(newElement);
            return NULL;
      }

      elementNode->nodeType = eELEMENT_NODE;

      return newElement;
}


/*!
 * \brief Returns a clone of a document node.
 *
 * \return A clone of a document node.
 */
00768 static IXML_Document *ixmlNode_cloneDoc(
      /*! [in] The \b Node to clone. */
      IXML_Document *nodeptr)
{
      IXML_Document *newDoc;
      IXML_Node *docNode;
      int rc;

      assert(nodeptr != NULL);

      newDoc = (IXML_Document *)malloc(sizeof (IXML_Document));
      if (newDoc == NULL) {
            return NULL;
      }

      ixmlDocument_init(newDoc);
      docNode = (IXML_Node *) newDoc;

      rc = ixmlNode_setNodeName(docNode, DOCUMENTNODENAME);
      if (rc != IXML_SUCCESS) {
            ixmlDocument_free(newDoc);
            return NULL;
      }

      newDoc->n.nodeType = eDOCUMENT_NODE;

      return newDoc;
}

/*!
 * \brief Returns a clone of an attribute node.
 *
 * \return A clone of an attribute node.
 */
00802 static IXML_Attr *ixmlNode_cloneAttr(
      /*! [in] The \b Node to clone. */
      IXML_Attr *nodeptr)
{
      IXML_Attr *newAttr;
      IXML_Node *attrNode;
      IXML_Node *srcNode;
      int rc;

      assert(nodeptr != NULL);

      newAttr = (IXML_Attr *)malloc(sizeof (IXML_Attr));
      if (newAttr == NULL) {
            return NULL;
      }

      ixmlAttr_init(newAttr);
      attrNode = (IXML_Node *)newAttr;
      srcNode = (IXML_Node *)nodeptr;

      rc = ixmlNode_setNodeName(attrNode, srcNode->nodeName);
      if (rc != IXML_SUCCESS) {
            ixmlAttr_free(newAttr);
            return NULL;
      }

      rc = ixmlNode_setNodeValue(attrNode, srcNode->nodeValue);
      if (rc != IXML_SUCCESS) {
            ixmlAttr_free(newAttr);
            return NULL;
      }

      /* Check to see whether we need to split prefix and localname for attribute */
      rc = ixmlNode_setNamespaceURI(attrNode, srcNode->namespaceURI);
      if (rc != IXML_SUCCESS) {
            ixmlAttr_free(newAttr);
            return NULL;
      }

      rc = ixmlNode_setPrefix(attrNode, srcNode->prefix);
      if (rc != IXML_SUCCESS) {
            ixmlAttr_free(newAttr);
            return NULL;
      }

      rc = ixmlNode_setLocalName(attrNode, srcNode->localName);
      if (rc != IXML_SUCCESS) {
            ixmlAttr_free(newAttr);
            return NULL;
      }

      attrNode->nodeType = eATTRIBUTE_NODE;

      return newAttr;
}

/*!
 * \brief Return a clone of attribute node, with specified field set to TRUE.
 *
 * \return A clone of attribute node, with specified field set to TRUE.
 */
00863 static IXML_Attr *ixmlNode_cloneAttrDirect(
      /*! [in] The \b Node to clone. */
      IXML_Attr *nodeptr)
{
      IXML_Attr *newAttr;

      assert(nodeptr != NULL);

      newAttr = ixmlNode_cloneAttr(nodeptr);
      if (newAttr != NULL) {
            newAttr->specified = TRUE;
      }

      return newAttr;
}


/*!
 * \brief Sets siblings nodes parent to be the same as this node's.
 */
00883 static void ixmlNode_setSiblingNodesParent(
      /*! [in] The node to operate on. */
      IXML_Node *nodeptr)
{
      IXML_Node *parentNode = nodeptr->parentNode;
      IXML_Node *nextptr = nodeptr->nextSibling;

      while (nextptr != NULL) {
            nextptr->parentNode = parentNode;
            nextptr = nextptr->nextSibling;
      }
}


/*!
 * \brief Recursive function that clones a node tree of nodeptr.
 *
 * \returns The cloned node/tree.
 */
00902 static IXML_Node *ixmlNode_cloneNodeTreeRecursive(
      /*! [in] Node tree to clone. */
      IXML_Node *nodeptr,
      /*! [in] TRUE if you want to clone the tree. */
      BOOL deep)
{
      IXML_Node *newNode = NULL;
      IXML_Element *newElement = NULL;
      IXML_Attr *newAttr = NULL;
      IXML_CDATASection *newCDATA = NULL;
      IXML_Document *newDoc = NULL;
      IXML_Node *nextSib = NULL;

      if (nodeptr != NULL) {
            switch (nodeptr->nodeType) {
            case eELEMENT_NODE:
                  newElement = ixmlNode_cloneElement((IXML_Element *)nodeptr);
                  newElement->n.firstAttr = ixmlNode_cloneNodeTreeRecursive(
                        nodeptr->firstAttr, deep);
                  if (deep) {
                        newElement->n.firstChild =
                              ixmlNode_cloneNodeTreeRecursive(nodeptr->firstChild, deep);
                        if (newElement->n.firstChild != NULL) {
                              newElement->n.firstChild->parentNode = (IXML_Node *)newElement;
                              ixmlNode_setSiblingNodesParent(newElement->n.firstChild);
                        }
                        nextSib = ixmlNode_cloneNodeTreeRecursive(nodeptr->nextSibling, deep);
                        newElement->n.nextSibling = nextSib;
                        if (nextSib != NULL) {
                              nextSib->prevSibling = (IXML_Node *)newElement;
                        }
                  }
                  newNode = (IXML_Node *)newElement;
                  break;

            case eATTRIBUTE_NODE:
                  newAttr = ixmlNode_cloneAttr((IXML_Attr *)nodeptr);
                  nextSib = ixmlNode_cloneNodeTreeRecursive(nodeptr->nextSibling, deep);
                  newAttr->n.nextSibling = nextSib;
                  if (nextSib != NULL) {
                        nextSib->prevSibling = (IXML_Node *)newAttr;
                  }
                  newNode = (IXML_Node *)newAttr;
                  break;

            case eTEXT_NODE:
                  newNode = ixmlNode_cloneTextNode(nodeptr);
                  break;

            case eCDATA_SECTION_NODE:
                  newCDATA = ixmlNode_cloneCDATASect((IXML_CDATASection *)nodeptr);
                  newNode = (IXML_Node *)newCDATA;
                  break;

            case eDOCUMENT_NODE:
                  newDoc = ixmlNode_cloneDoc((IXML_Document *)nodeptr);
                  newNode = (IXML_Node *)newDoc;
                  if (deep) {
                        newNode->firstChild = ixmlNode_cloneNodeTreeRecursive(
                              nodeptr->firstChild, deep);
                        if (newNode->firstChild != NULL) {
                              newNode->firstChild->parentNode = newNode;
                        }
                  }
                  break;

            case eINVALID_NODE:
            case eENTITY_REFERENCE_NODE:
            case eENTITY_NODE:
            case ePROCESSING_INSTRUCTION_NODE:
            case eCOMMENT_NODE:
            case eDOCUMENT_TYPE_NODE:
            case eDOCUMENT_FRAGMENT_NODE:
            case eNOTATION_NODE:
                  break;
            }
      }

      return newNode;
}


/*!
 * \brief Function that clones a node tree of nodeptr.
 *
 * \returns The cloned node/tree.
 */
00989 static IXML_Node *ixmlNode_cloneNodeTree(
      /*! [in] Node tree to clone. */
      IXML_Node *nodeptr,
      /*! [in] TRUE if you want to clone the tree. */
      BOOL deep)
{
      IXML_Node *newNode = NULL;
      IXML_Element *newElement;
      IXML_Node *childNode;

      assert(nodeptr != NULL);

      switch (nodeptr->nodeType) {
      case eELEMENT_NODE:
            newElement = ixmlNode_cloneElement((IXML_Element *)nodeptr);
            newElement->n.firstAttr = ixmlNode_cloneNodeTreeRecursive(nodeptr->firstAttr, deep);
            if (deep) {
                  newElement->n.firstChild = ixmlNode_cloneNodeTreeRecursive(
                        nodeptr->firstChild, deep);
                  childNode = newElement->n.firstChild;
                  while (childNode != NULL) {
                        childNode->parentNode = (IXML_Node *)newElement;
                        childNode = childNode->nextSibling;
                  }
                  newElement->n.nextSibling = NULL;
            }
            newNode = ( IXML_Node * ) newElement;
            break;

      case eATTRIBUTE_NODE:
      case eTEXT_NODE:
      case eCDATA_SECTION_NODE:
      case eDOCUMENT_NODE:
            newNode = ixmlNode_cloneNodeTreeRecursive(nodeptr, deep);
            break;

      case eINVALID_NODE:
      case eENTITY_REFERENCE_NODE:
      case eENTITY_NODE:
      case ePROCESSING_INSTRUCTION_NODE:
      case eCOMMENT_NODE:
      case eDOCUMENT_TYPE_NODE:
      case eDOCUMENT_FRAGMENT_NODE:
      case eNOTATION_NODE:
#if 0
            /* create a new node here? */
            newNode = (IXML_Node *)malloc(sizeof(IXML_Node));
            if (newNode == NULL) {
                  return NULL;
            }
#endif
            break;
      }

      /* by spec, the duplicate node has no parent */
      newNode->parentNode = NULL;

      return newNode;
}



01051 IXML_Node *ixmlNode_cloneNode(IXML_Node *nodeptr, BOOL deep)
{
      IXML_Node *newNode;
      IXML_Attr *newAttrNode;

      if (nodeptr == NULL) {
            return NULL;
      }

      switch (nodeptr->nodeType) {
      case eATTRIBUTE_NODE:
            newAttrNode = ixmlNode_cloneAttrDirect((IXML_Attr *)nodeptr);
            return (IXML_Node *)newAttrNode;
            break;

      default:
            newNode = ixmlNode_cloneNodeTree(nodeptr, deep);
            return newNode;
            break;
      }
}


01074 IXML_NodeList *ixmlNode_getChildNodes(IXML_Node *nodeptr)
{
      IXML_Node *tempNode;
      IXML_NodeList *newNodeList;
      int rc;

      if (nodeptr == NULL) {
            return NULL;
      }

      newNodeList = (IXML_NodeList *)malloc(sizeof(IXML_NodeList));
      if (newNodeList == NULL) {
            return NULL;
      }

      ixmlNodeList_init(newNodeList);
      tempNode = nodeptr->firstChild;
      while (tempNode != NULL) {
            rc = ixmlNodeList_addToNodeList(&newNodeList, tempNode);
            if (rc != IXML_SUCCESS) {
                  ixmlNodeList_free(newNodeList);
                  return NULL;
            }

            tempNode = tempNode->nextSibling;
      }

      return newNodeList;
}


01105 IXML_NamedNodeMap *ixmlNode_getAttributes(IXML_Node *nodeptr)
{
      IXML_NamedNodeMap *returnNamedNodeMap = NULL;
      IXML_Node *tempNode;
      int rc;

      if(nodeptr == NULL) {
            return NULL;
      }

      if(nodeptr->nodeType == eELEMENT_NODE) {
            returnNamedNodeMap = (IXML_NamedNodeMap *)malloc(sizeof(IXML_NamedNodeMap));
            if(returnNamedNodeMap == NULL) {
                  return NULL;
            }

            ixmlNamedNodeMap_init(returnNamedNodeMap);
            tempNode = nodeptr->firstAttr;
            while( tempNode != NULL ) {
                  rc = ixmlNamedNodeMap_addToNamedNodeMap(&returnNamedNodeMap, tempNode);
                  if(rc != IXML_SUCCESS) {
                        ixmlNamedNodeMap_free(returnNamedNodeMap);
                        return NULL;
                  }

                  tempNode = tempNode->nextSibling;
            }
            return returnNamedNodeMap;
      } else {
            /* if not an ELEMENT_NODE */
            return NULL;
      }
}


01140 BOOL ixmlNode_hasChildNodes(IXML_Node *nodeptr)
{
      if (nodeptr == NULL) {
            return FALSE;
      }

      return nodeptr->firstChild != NULL;
}


01150 BOOL ixmlNode_hasAttributes(IXML_Node *nodeptr)
{
      if (nodeptr != NULL) {
            if (nodeptr->nodeType == eELEMENT_NODE && nodeptr->firstAttr != NULL) {
                  return TRUE;
            }
      }

      return FALSE;
}


/*!
 * \brief Recursively traverse the whole tree, search for element with the
 * given tagname.
 */
01166 static void ixmlNode_getElementsByTagNameRecursive(
      /*! [in] The \b Node tree. */
      IXML_Node *n,
      /*! [in] The tag name to match. */
      const char *tagname,
      /*! [out] The output \b NodeList. */
      IXML_NodeList **list)
{
      const char *name;

      if (n != NULL) {
            if (ixmlNode_getNodeType(n) == eELEMENT_NODE) {
                  name = ixmlNode_getNodeName(n);
                  if (strcmp(tagname, name) == 0 || strcmp(tagname, "*") == 0) {
                        ixmlNodeList_addToNodeList(list, n);
                  }
            }
            ixmlNode_getElementsByTagNameRecursive(ixmlNode_getFirstChild(n), tagname, list);
            ixmlNode_getElementsByTagNameRecursive(ixmlNode_getNextSibling(n), tagname, list);
      }
}


01189 void ixmlNode_getElementsByTagName(
      IXML_Node *n,
      const char *tagname,
      IXML_NodeList **list)
{
      const char *name;

      assert(n != NULL && tagname != NULL);

      if (ixmlNode_getNodeType(n) == eELEMENT_NODE) {
            name = ixmlNode_getNodeName(n);
            if (strcmp(tagname, name) == 0 || strcmp(tagname, "*") == 0) {
                  ixmlNodeList_addToNodeList(list, n);
            }
      }
      ixmlNode_getElementsByTagNameRecursive(ixmlNode_getFirstChild(n), tagname, list);
}


/*!
 * \brief 
 */
01211 static void ixmlNode_getElementsByTagNameNSRecursive(
      /*! [in] . */
      IXML_Node *n,
      /*! [in] . */
      const char *namespaceURI,
      /*! [in] . */
      const char *localName,
      /*! [out] . */
      IXML_NodeList **list)
{
      const DOMString nsURI;
      const DOMString name;

      if (n != NULL) {
            if (ixmlNode_getNodeType(n) == eELEMENT_NODE) {
                  name = ixmlNode_getLocalName(n);
                  nsURI = ixmlNode_getNamespaceURI(n);

                  if (name != NULL && nsURI != NULL &&
                      (strcmp(namespaceURI, nsURI) == 0 ||
                       strcmp(namespaceURI, "*") == 0 ) &&
                      (strcmp(name, localName) == 0 ||
                       strcmp(localName, "*") == 0)) {
                        ixmlNodeList_addToNodeList(list, n);
                  }
            }
            ixmlNode_getElementsByTagNameNSRecursive(
                  ixmlNode_getFirstChild(n), namespaceURI, localName, list);
            ixmlNode_getElementsByTagNameNSRecursive(
                  ixmlNode_getNextSibling(n), namespaceURI, localName, list);
      }
}


01245 void ixmlNode_getElementsByTagNameNS(
      IXML_Node *n,
      const char *namespaceURI,
      const char *localName,
      IXML_NodeList **list)
{
      const DOMString nsURI;
      const DOMString name;

      assert(n != NULL && namespaceURI != NULL && localName != NULL);

      if (ixmlNode_getNodeType(n) == eELEMENT_NODE) {
            name = ixmlNode_getLocalName(n);
            nsURI = ixmlNode_getNamespaceURI(n);
            if (name != NULL && nsURI != NULL &&
                (strcmp(namespaceURI, nsURI) == 0 ||
                 strcmp(namespaceURI, "*") == 0) &&
                (strcmp(name, localName) == 0 ||
                 strcmp(localName, "*") == 0)) {
                  ixmlNodeList_addToNodeList(list, n);
            }
      }

      ixmlNode_getElementsByTagNameNSRecursive(
            ixmlNode_getFirstChild(n), namespaceURI, localName, list);
}


01273 int ixmlNode_setNodeName(
      IXML_Node *node,
      const DOMString qualifiedName)
{
      int rc = IXML_SUCCESS;

      assert( node != NULL );

      if (node->nodeName != NULL) {
            free(node->nodeName);
            node->nodeName = NULL;
      }

      if (qualifiedName != NULL) {
            /* set the name part */
            node->nodeName = strdup(qualifiedName);
            if (node->nodeName == NULL) {
                  return IXML_INSUFFICIENT_MEMORY;
            }

            rc = Parser_setNodePrefixAndLocalName(node);
            if (rc != IXML_SUCCESS) {
                  free(node->nodeName);
            }
      }

      return rc;
}


01303 int ixmlNode_setNodeProperties(
      IXML_Node *destNode,
      IXML_Node *src)
{
      int rc;

      assert(destNode != NULL || src != NULL);

      rc = ixmlNode_setNodeValue(destNode, src->nodeValue);
      if(rc != IXML_SUCCESS) {
            goto ErrorHandler;
      }

      rc = ixmlNode_setLocalName(destNode, src->localName);
      if(rc != IXML_SUCCESS) {
            goto ErrorHandler;
      }

      rc = ixmlNode_setPrefix(destNode, src->prefix);
      if(rc != IXML_SUCCESS) {
            goto ErrorHandler;
      }
      /* set nodetype */
      destNode->nodeType = src->nodeType;

      return IXML_SUCCESS;

ErrorHandler:
      if(destNode->nodeName != NULL) {
            free(destNode->nodeName);
            destNode->nodeName = NULL;
      }
      if(destNode->nodeValue != NULL) {
            free(destNode->nodeValue);
            destNode->nodeValue = NULL;
      }
      if(destNode->localName != NULL) {
            free(destNode->localName);
            destNode->localName = NULL;
      }

      return IXML_INSUFFICIENT_MEMORY;
}


Generated by  Doxygen 1.6.0   Back to index