libupnp/ixml/src/node.c
Fabrice Fontaine c42216dad7 Check return code in ixml
Check return code of ixmlDocument_CreateElementEx in
ixmlDocument_CreateElement.
Check return code of ixmlNode_setNodeName and ixmlNode_setNodeValue in
ixmlNode_cloneCDATASect and ixmlNode_cloneTextNode.
(cherry picked from commit d3d17da6e5)
2012-03-19 11:48:03 -03:00

1380 lines
30 KiB
C

/*******************************************************************************
*
* Copyright (c) 2000-2003 Intel Corporation
* All rights reserved.
* Copyright (c) 2012 France Telecom 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));
}
void ixmlCDATASection_init(IXML_CDATASection *nodeptr)
{
memset(nodeptr, 0, sizeof (IXML_CDATASection));
}
void ixmlCDATASection_free(IXML_CDATASection *nodeptr)
{
if (nodeptr != NULL) {
ixmlNode_free((IXML_Node *)nodeptr);
}
}
/*!
* \brief Frees a node content.
*/
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);
}
switch (nodeptr->nodeType ) {
case eELEMENT_NODE:
element = (IXML_Element *)nodeptr;
free(element->tagName);
break;
default:
break;
}
free(nodeptr);
}
}
void ixmlNode_free(IXML_Node *nodeptr)
{
if (nodeptr != NULL) {
ixmlNode_free(nodeptr->firstChild);
ixmlNode_free(nodeptr->nextSibling);
ixmlNode_free(nodeptr->firstAttr);
ixmlNode_freeSingleNode(nodeptr);
}
}
const DOMString ixmlNode_getNodeName(IXML_Node *nodeptr)
{
if(nodeptr != NULL) {
return nodeptr->nodeName;
}
return NULL;
}
const DOMString ixmlNode_getLocalName(IXML_Node *nodeptr)
{
if (nodeptr != NULL) {
return nodeptr->localName;
}
return NULL;
}
/*!
* \brief Sets the namespace URI of the node.
*/
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.
*/
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.
*/
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;
}
const DOMString ixmlNode_getNamespaceURI(IXML_Node *nodeptr)
{
DOMString retNamespaceURI = NULL;
if (nodeptr != NULL) {
retNamespaceURI = nodeptr->namespaceURI;
}
return retNamespaceURI;
}
const DOMString ixmlNode_getPrefix(IXML_Node *nodeptr)
{
const DOMString prefix = NULL;
if (nodeptr != NULL) {
prefix = nodeptr->prefix;
}
return prefix;
}
const DOMString ixmlNode_getNodeValue(IXML_Node *nodeptr)
{
if ( nodeptr != NULL ) {
return nodeptr->nodeValue;
}
return NULL;
}
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;
}
unsigned short ixmlNode_getNodeType(IXML_Node *nodeptr)
{
if (nodeptr != NULL) {
return nodeptr->nodeType;
} else {
return (unsigned short)eINVALID_NODE;
}
}
IXML_Node *ixmlNode_getParentNode(IXML_Node *nodeptr)
{
if (nodeptr != NULL) {
return nodeptr->parentNode;
} else {
return NULL;
}
}
IXML_Node *ixmlNode_getFirstChild(IXML_Node *nodeptr)
{
if (nodeptr != NULL) {
return nodeptr->firstChild;
} else {
return NULL;
}
}
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;
}
}
IXML_Node *ixmlNode_getPreviousSibling(IXML_Node *nodeptr)
{
if (nodeptr != NULL) {
return nodeptr->prevSibling;
} else {
return NULL;
}
}
IXML_Node *ixmlNode_getNextSibling(IXML_Node *nodeptr)
{
if (nodeptr != NULL) {
return nodeptr->nextSibling;
} else {
return NULL;
}
}
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.
*/
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.
*/
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);
if (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.
*/
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;
case eELEMENT_NODE:
switch (newChild->nodeType) {
case eATTRIBUTE_NODE:
case eDOCUMENT_NODE:
return FALSE;
default:
break;
}
break;
case eDOCUMENT_NODE:
switch (newChild->nodeType) {
case eELEMENT_NODE:
break;
default:
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.
*/
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);
}
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, &newChild);
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;
}
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;
}
int ixmlNode_removeChild(
IXML_Node *nodeptr,
IXML_Node *oldChild,
IXML_Node **returnNode)
{
if (!nodeptr || !oldChild)
return IXML_INVALID_PARAMETER;
if (!ixmlNode_isParent(nodeptr, oldChild))
return IXML_NOT_FOUND_ERR;
if (oldChild->prevSibling)
oldChild->prevSibling->nextSibling = oldChild->nextSibling;
if (nodeptr->firstChild == oldChild)
nodeptr->firstChild = oldChild->nextSibling;
if (oldChild->nextSibling)
oldChild->nextSibling->prevSibling = oldChild->prevSibling;
oldChild->nextSibling = NULL;
oldChild->prevSibling = NULL;
oldChild->parentNode = NULL;
if (returnNode)
*returnNode = oldChild;
else
ixmlNode_free(oldChild);
return IXML_SUCCESS;
}
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, &newChild);
}
/* 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.
*/
static IXML_Node *ixmlNode_cloneTextNode(
/*! [in] The \b Node to clone. */
IXML_Node *nodeptr)
{
IXML_Node *newNode = NULL;
int rc;
assert(nodeptr != NULL);
newNode = (IXML_Node *)malloc(sizeof (IXML_Node));
if (newNode == NULL) {
return NULL;
} else {
ixmlNode_init(newNode);
rc = ixmlNode_setNodeName(newNode, nodeptr->nodeName);
if (rc != IXML_SUCCESS) {
ixmlNode_free(newNode);
return NULL;
}
rc = ixmlNode_setNodeValue(newNode, nodeptr->nodeValue);
if (rc != IXML_SUCCESS) {
ixmlNode_free(newNode);
return NULL;
}
newNode->nodeType = eTEXT_NODE;
}
return newNode;
}
/*!
* \brief Return a clone of CDATASection node.
*
* \return A clone of CDATASection node.
*/
static IXML_CDATASection *ixmlNode_cloneCDATASect(
/*! [in] The \b Node to clone. */
IXML_CDATASection *nodeptr)
{
IXML_CDATASection *newCDATA = NULL;
IXML_Node *newNode;
IXML_Node *srcNode;
int rc;
assert(nodeptr != NULL);
newCDATA = (IXML_CDATASection *)malloc(sizeof (IXML_CDATASection));
if (newCDATA != NULL) {
newNode = (IXML_Node *)newCDATA;
ixmlCDATASection_init(newCDATA);
srcNode = (IXML_Node *)nodeptr;
rc = ixmlNode_setNodeName(newNode, srcNode->nodeName);
if (rc != IXML_SUCCESS) {
ixmlCDATASection_free(newCDATA);
return NULL;
}
rc = ixmlNode_setNodeValue(newNode, srcNode->nodeValue);
if (rc != IXML_SUCCESS) {
ixmlCDATASection_free(newCDATA);
return NULL;
}
newNode->nodeType = eCDATA_SECTION_NODE;
}
return newCDATA;
}
/*!
* \brief Returns a clone of element node.
*
* \return A clone of element node.
*/
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 new document node.
*
* Currently, the IXML_Document struct is just a node, so this function
* just mallocs the IXML_Document, sets the node type and name.
*
* \return A new document node.
*/
static IXML_Document *ixmlNode_newDoc(void)
{
IXML_Document *newDoc;
IXML_Node *docNode;
int rc;
newDoc = (IXML_Document *)malloc(sizeof (IXML_Document));
if (!newDoc)
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.
*/
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.
*/
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.
*/
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.
*/
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);
if (newElement == NULL)
return NULL;
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);
if (newAttr == NULL)
return NULL;
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_newDoc();
if (newDoc == NULL)
return NULL;
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.
*/
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);
if (newElement == NULL)
return NULL;
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 */
if (newNode != NULL)
newNode->parentNode = NULL;
return newNode;
}
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;
}
}
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;
}
IXML_NamedNodeMap *ixmlNode_getAttributes(IXML_Node *nodeptr)
{
IXML_NamedNodeMap *returnNamedNodeMap = NULL;
IXML_Node *tempNode;
int rc;
if(nodeptr == NULL) {
return NULL;
}
switch(nodeptr->nodeType) {
case 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;
default:
/* if not an ELEMENT_NODE */
return NULL;
}
}
BOOL ixmlNode_hasChildNodes(IXML_Node *nodeptr)
{
if (nodeptr == NULL) {
return FALSE;
}
return nodeptr->firstChild != NULL;
}
BOOL ixmlNode_hasAttributes(IXML_Node *nodeptr)
{
if (nodeptr != NULL) {
switch (nodeptr->nodeType) {
case eELEMENT_NODE:
if (nodeptr->firstAttr != NULL)
return TRUE;
break;
default:
break;
}
}
return FALSE;
}
/*!
* \brief Recursively traverse the whole tree, search for element with the
* given tagname.
*/
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);
}
}
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
*/
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);
}
}
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);
}
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;
}
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;
}