/////////////////////////////////////////////////////////////////////////// // // 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. // /////////////////////////////////////////////////////////////////////////// #include "ixmlparser.h" /*================================================================ * ixmlNode_init * Intializes a node. * External function. * *=================================================================*/ void ixmlNode_init( IN IXML_Node * nodeptr ) { assert( nodeptr != NULL ); memset( nodeptr, 0, sizeof( IXML_Node ) ); } /*================================================================ * ixmlCDATASection_init * Initializes a CDATASection node. * External function. * *=================================================================*/ void ixmlCDATASection_init( IN IXML_CDATASection * nodeptr ) { memset( nodeptr, 0, sizeof( IXML_CDATASection ) ); } /*================================================================ * ixmlCDATASection_free * frees a CDATASection node. * External function. * *=================================================================*/ void ixmlCDATASection_free( IN IXML_CDATASection * nodeptr ) { if( nodeptr != NULL ) { ixmlNode_free( ( IXML_Node * ) nodeptr ); } } /*================================================================ * ixmlNode_freeSingleNode * frees a node content. * Internal to parser only. * *=================================================================*/ void ixmlNode_freeSingleNode( IN 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 ); } } /*================================================================ * ixmlNode_free * Frees all nodes under nodeptr subtree. * External function. * *=================================================================*/ void ixmlNode_free( IN IXML_Node * nodeptr ) { if( nodeptr != NULL ) { ixmlNode_free( nodeptr->firstChild ); ixmlNode_free( nodeptr->nextSibling ); ixmlNode_free( nodeptr->firstAttr ); ixmlNode_freeSingleNode( nodeptr ); } } /*================================================================ * ixmlNode_getNodeName * Returns the nodename(the qualified name) * External function. * *=================================================================*/ const DOMString ixmlNode_getNodeName( IN IXML_Node * nodeptr ) { if( nodeptr != NULL ) { return ( nodeptr->nodeName ); } return NULL; } /*================================================================ * ixmlNode_getLocalName * Returns the node local name * External function. * *=================================================================*/ const DOMString ixmlNode_getLocalName( IN IXML_Node * nodeptr ) { if( nodeptr != NULL ) { return ( nodeptr->localName ); } return NULL; } /*================================================================ * ixmlNode_setNamespaceURI * sets the namespace URI of the node. * Internal function. * Return: * IXML_SUCCESS or failure * *=================================================================*/ int ixmlNode_setNamespaceURI( IN IXML_Node * nodeptr, IN 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; } /*================================================================ * ixmlNode_setPrefix * set the prefix of the node. * Internal to parser only. * Returns: * IXML_SUCCESS or failure. * *=================================================================*/ int ixmlNode_setPrefix( IN IXML_Node * nodeptr, IN 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; } /*================================================================ * ixmlNode_setLocalName * set the localName of the node. * Internal to parser only. * Returns: * IXML_SUCCESS or failure. * *=================================================================*/ int ixmlNode_setLocalName( IN IXML_Node * nodeptr, IN 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; } /*================================================================ * ixmlNode_getNodeNamespaceURI * Returns the node namespaceURI * External function. * Returns: * the namespaceURI of the node * *=================================================================*/ const DOMString ixmlNode_getNamespaceURI( IN IXML_Node * nodeptr ) { DOMString retNamespaceURI = NULL; if( nodeptr != NULL ) { retNamespaceURI = nodeptr->namespaceURI; } return retNamespaceURI; } /*================================================================ * ixmlNode_getPrefix * Returns the node prefix * External function. * Returns: * the prefix of the node. * *=================================================================*/ DOMString ixmlNode_getPrefix( IN IXML_Node * nodeptr ) { DOMString prefix = NULL; if( nodeptr != NULL ) { prefix = nodeptr->prefix; } return prefix; } /*================================================================ * ixmlNode_getNodeValue * Returns the nodeValue of this node * External function. * Return: * the nodeValue of the node. * *=================================================================*/ DOMString ixmlNode_getNodeValue( IN IXML_Node * nodeptr ) { if( nodeptr != NULL ) { return ( nodeptr->nodeValue ); } return NULL; } /*================================================================ * ixmlNode_setNodeValue * Sets the nodeValue * Internal function. * Returns: * IXML_SUCCESS or failure * *=================================================================*/ int ixmlNode_setNodeValue( IN IXML_Node * nodeptr, IN 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; } /*================================================================ * ixmlNode_getNodeType * Gets the NodeType of this node * External function. * *=================================================================*/ unsigned short ixmlNode_getNodeType( IN IXML_Node * nodeptr ) { if( nodeptr != NULL ) { return ( nodeptr->nodeType ); } else { return ( eINVALID_NODE ); } } /*================================================================ * ixmlNode_getParentNode * Get the parent node * External function. * Return: * *=================================================================*/ IXML_Node * ixmlNode_getParentNode( IN IXML_Node * nodeptr ) { if( nodeptr != NULL ) { return nodeptr->parentNode; } else { return NULL; } } /*================================================================ * ixmlNode_getFirstChild * Returns the first child of nodeptr. * External function. * *=================================================================*/ IXML_Node * ixmlNode_getFirstChild( IN IXML_Node * nodeptr ) { if( nodeptr != NULL ) { return nodeptr->firstChild; } else { return NULL; } } /*================================================================ * ixmlNode_getLastChild * Returns the last child of nodeptr. * External function. * *=================================================================*/ IXML_Node * ixmlNode_getLastChild( IN IXML_Node * nodeptr ) { IXML_Node *prev, *next; if( nodeptr != NULL ) { prev = nodeptr; next = nodeptr->firstChild; while( next != NULL ) { prev = next; next = next->nextSibling; } return prev; } else { return NULL; } } /*================================================================ * ixmlNode_getPreviousSibling * returns the previous sibling node of nodeptr. * External function. * *=================================================================*/ IXML_Node * ixmlNode_getPreviousSibling( IN IXML_Node * nodeptr ) { if( nodeptr != NULL ) { return nodeptr->prevSibling; } else { return NULL; } } /*================================================================ * ixmlNode_getNextSibling * Returns the next sibling node. * External function. * *=================================================================*/ IXML_Node * ixmlNode_getNextSibling( IN IXML_Node * nodeptr ) { if( nodeptr != NULL ) { return nodeptr->nextSibling; } else { return NULL; } } /*================================================================ * ixmlNode_getOwnerDocument * Returns the owner document node. * External function. * *=================================================================*/ IXML_Document * ixmlNode_getOwnerDocument( IN IXML_Node * nodeptr ) { if( nodeptr != NULL ) { return ( IXML_Document * ) nodeptr->ownerDocument; } else { return NULL; } } /*================================================================ * ixmlNode_isAncestor * check if ancestorNode is ancestor of toFind * Internal to parser only. * Returns: * TRUE or FALSE * *=================================================================*/ BOOL ixmlNode_isAncestor( IXML_Node * ancestorNode, 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; } /*================================================================ * ixmlNode_isParent * Check whether toFind is a children of nodeptr. * Internal to parser only. * Return: * TRUE or FALSE * *=================================================================*/ BOOL ixmlNode_isParent( IXML_Node * nodeptr, IXML_Node * toFind ) { BOOL found = FALSE; assert( nodeptr != NULL && toFind != NULL ); if( toFind->parentNode == nodeptr ) { found = TRUE; } return found; } /*================================================================ * ixmlNode_allowChildren * Check to see whether nodeptr allows children of type newChild. * Internal to parser only. * Returns: * TRUE, if nodeptr can have newChild as children * FALSE,if nodeptr cannot have newChild as children * *=================================================================*/ BOOL ixmlNode_allowChildren( IXML_Node * nodeptr, 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; } /*================================================================ * ixmlNode_compare * Compare two nodes to see whether they are the same node. * Parent, sibling and children node are ignored. * Internal to parser only. * Returns: * TRUE, the two nodes are the same. * FALSE, the two nodes are not the same. * *=================================================================*/ BOOL ixmlNode_compare( IXML_Node * srcNode, IXML_Node * destNode ) { assert( srcNode != NULL && destNode != NULL ); if( ( 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 ) ) { return TRUE; } else { return FALSE; } } /*================================================================ * ixmlNode_insertBefore * Inserts the node newChild before the existing child node refChild. * If refChild is null, insert newChild at the end of the list of * children. If the newChild is already in the tree, it is first * removed. * External function. * Parameters: * newChild: the node to insert. * Returns: * *=================================================================*/ int ixmlNode_insertBefore( IN IXML_Node * nodeptr, IN IXML_Node * newChild, IN 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; } /*================================================================ * ixmlNode_replaceChild * Replaces the child node oldChild with newChild in the list of children, * and returns the oldChild node. * External function. * Parameters: * newChild: the new node to put in the child list. * oldChild: the node being replaced in the list. * returnNode: the node replaced. * Return Value: * IXML_SUCCESS * IXML_INVALID_PARAMETER: if anyone of nodeptr, newChild or oldChild is NULL. * IXML_HIERARCHY_REQUEST_ERR: if the newChild is ancestor of nodeptr or nodeptr * is of a type that does not allow children of the * type of the newChild node. * IXML_WRONG_DOCUMENT_ERR: if newChild was created from a different document than * the one that created this node. * IXML_NOT_FOUND_ERR: if oldChild is not a child of nodeptr. * *=================================================================*/ int ixmlNode_replaceChild( IN IXML_Node * nodeptr, IN IXML_Node * newChild, IN IXML_Node * oldChild, OUT 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; } /*================================================================ * ixmlNode_removeChild * Removes the child node indicated by oldChild from the list of * children, and returns it. * External function. * Parameters: * oldChild: the node being removed. * returnNode: the node removed. * Return Value: * IXML_SUCCESS * IXML_NOT_FOUND_ERR: if oldChild is not a child of this node. * IXML_INVALID_PARAMETER: if either oldChild or nodeptr is NULL * *=================================================================*/ int ixmlNode_removeChild( IN IXML_Node * nodeptr, IN IXML_Node * oldChild, OUT 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; } /*============================================================================= * ixmlNode_appendChild * Adds the node newChild to the end of the list of children of this node. * If the newChild is already in the tree, it is first removed. * External function. * Parameter: * newChild: the node to add. * Return Value: * IXML_SUCCESS * IXML_INVALID_PARAMETER: if either nodeptr or newChild is NULL * IXML_WRONG_DOCUMENT_ERR: if newChild was created from a different document than * the one that created nodeptr. * IXML_HIERARCHY_REQUEST_ERR: if newChild is ancestor of nodeptr or if nodeptr is of * a type that does not allow children of the type of the * newChild node. * *=================================================================*/ int ixmlNode_appendChild( IN IXML_Node * nodeptr, IN IXML_Node * newChild ) { IXML_Node *prev = NULL, *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; } /*================================================================ * ixmlNode_cloneTextNode * Returns a clone of nodeptr * Internal to parser only. * *=================================================================*/ IXML_Node * ixmlNode_cloneTextNode( IN 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; } /*================================================================ * ixmlNode_cloneCDATASect * Return a clone of CDATASection node. * Internal to parser only. * *=================================================================*/ IXML_CDATASection * ixmlNode_cloneCDATASect( IN 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; } /*================================================================ * ixmlNode_cloneElement * returns a clone of element node * Internal to parser only. * *=================================================================*/ IXML_Element * ixmlNode_cloneElement( IN 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; } /*================================================================ * ixmlNode_cloneDoc * Returns a clone of document node * Internal to parser only. * *=================================================================*/ IXML_Document * ixmlNode_cloneDoc( IN 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; } /*================================================================ * ixmlNode_cloneAttr * Returns a clone of attribute node * Internal to parser only * *=================================================================*/ IXML_Attr * ixmlNode_cloneAttr( IN 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; } /*================================================================ * ixmlNode_cloneAttrDirect * Return a clone of attribute node, with specified field set * to TRUE. * *=================================================================*/ IXML_Attr * ixmlNode_cloneAttrDirect( IN IXML_Attr * nodeptr ) { IXML_Attr *newAttr; assert( nodeptr != NULL ); newAttr = ixmlNode_cloneAttr( nodeptr ); if( newAttr != NULL ) { newAttr->specified = TRUE; } return newAttr; } void ixmlNode_setSiblingNodesParent( IXML_Node * nodeptr ) { IXML_Node *parentNode = nodeptr->parentNode; IXML_Node *nextptr = nodeptr->nextSibling; while( nextptr != NULL ) { nextptr->parentNode = parentNode; nextptr = nextptr->nextSibling; } } /*================================================================ * ixmlNode_cloneNodeTreeRecursive * recursive functions that clones node tree of nodeptr. * Internal to parser only. * *=================================================================*/ IXML_Node * ixmlNode_cloneNodeTreeRecursive( IN IXML_Node * nodeptr, IN BOOL deep ) { IXML_Node *newNode = NULL; IXML_Element *newElement; IXML_Attr *newAttr = NULL; IXML_CDATASection *newCDATA = NULL; IXML_Document *newDoc; IXML_Node *nextSib; 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; } /*================================================================ * ixmlNode_cloneNodeTree * clones a node tree. * Internal to parser only. * *=================================================================*/ IXML_Node * ixmlNode_cloneNodeTree( IN IXML_Node * nodeptr, IN 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: /* create a new node here? newNode = (IXML_Node *)malloc(sizeof(IXML_Node)); if( newNode == NULL ) { return NULL; }*/ break; } // by spec, the duplicate node has no parent newNode->parentNode = NULL; return newNode; } /*================================================================ * ixmlNode_cloneNode * Clones a node, if deep==TRUE, clones subtree under nodeptr. * External function. * Returns: * the cloned node or NULL if error occurs. * *=================================================================*/ IXML_Node * ixmlNode_cloneNode( IN IXML_Node * nodeptr, IN 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; } } /*================================================================ * ixmlNode_getChildNodes * Returns a IXML_NodeList of all the child nodes of nodeptr. * External function. * *=================================================================*/ IXML_NodeList * ixmlNode_getChildNodes( IN 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; } /*================================================================ * ixmlNode_getAttributes * returns a namedNodeMap of attributes of nodeptr * External function. * Returns: * *=================================================================*/ IXML_NamedNodeMap * ixmlNode_getAttributes( IN 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; } } /*================================================================ * ixmlNode_hasChildNodes * External function. * *=================================================================*/ BOOL ixmlNode_hasChildNodes( IXML_Node * nodeptr ) { if( nodeptr == NULL ) { return FALSE; } return ( nodeptr->firstChild != NULL ); } /*================================================================ * ixmlNode_hasAttributes * External function. * *=================================================================*/ BOOL ixmlNode_hasAttributes( IXML_Node * nodeptr ) { if( nodeptr != NULL ) { if( ( nodeptr->nodeType == eELEMENT_NODE ) && ( nodeptr->firstAttr != NULL ) ) { return TRUE; } } return FALSE; } /*================================================================ * ixmlNode_getElementsByTagNameRecursive * Recursively traverse the whole tree, search for element * with the given tagname. * Internal to parser. * *=================================================================*/ void ixmlNode_getElementsByTagNameRecursive( IN IXML_Node * n, IN char *tagname, OUT 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 ); } } /*================================================================ * ixmlNode_getElementsByTagName * Returns a nodeList of all descendant Elements with a given * tagName, in the order in which they are encountered in a * traversal of this element tree. * External function. * *=================================================================*/ void ixmlNode_getElementsByTagName( IN IXML_Node * n, IN char *tagname, OUT 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 ); } /*================================================================ * ixmlNode_getElementsByTagNameNSRecursive * Internal function to parser. * * *=================================================================*/ void ixmlNode_getElementsByTagNameNSRecursive( IN IXML_Node * n, IN char *namespaceURI, IN 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 ); } } /*================================================================ * ixmlNode_getElementsByTagNameNS * Returns a nodeList of all the descendant Elements with a given * local name and namespace URI in the order in which they are * encountered in a preorder traversal of this Elememt tree. * External function. * *=================================================================*/ void ixmlNode_getElementsByTagNameNS( IN IXML_Node * n, IN char *namespaceURI, IN char *localName, OUT 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 ); } /*================================================================ * ixmlNode_setNodeName * Internal to parser only. * *=================================================================*/ int ixmlNode_setNodeName( IN IXML_Node * node, IN 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; } /*================================================================ * ixmlNode_setNodeProperties * Internal to parser only. * *=================================================================*/ int ixmlNode_setNodeProperties( IN IXML_Node * destNode, IN 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; }