2009-02-09 16:16:11 +00:00
/ * Implementation for NSXMLNode for GNUStep
Copyright ( C ) 2008 Free Software Foundation , Inc .
Written by : Richard Frith - Macdonald < rfm @ gnu . org >
Created : September 2008
This file is part of the GNUstep Base Library .
This library is free software ; you can redistribute it and / or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation ; either
version 3 of the License , or ( at your option ) any later version .
2011-10-01 18:43:29 +00:00
2009-02-09 16:16:11 +00:00
This library is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
Library General Public License for more details .
You should have received a copy of the GNU Lesser General Public
License along with this library ; if not , write to the Free
Software Foundation , Inc . , 51 Franklin Street , Fifth Floor ,
Boston , MA 02111 USA .
* /
2010-02-19 08:12:46 +00:00
# import "common.h"
2012-01-04 09:20:32 +00:00
# define GSInternal NSXMLNodeInternal
2012-01-05 20:40:12 +00:00
# import "NSXMLPrivate.h"
# import "GSInternal.h"
2012-01-04 09:20:32 +00:00
GS_PRIVATE _INTERNAL ( NSXMLNode )
2011-10-01 18:43:29 +00:00
2012-02-20 03:40:15 +00:00
# if defined ( HAVE_LIBXML )
int countAttributes ( xmlNodePtr node )
{
int count = 0 ;
xmlAttrPtr attr = node -> properties ;
while ( attr )
{
count + + ;
attr = attr -> next ;
}
return count ;
}
2012-02-21 08:21:12 +00:00
BOOL isEqualAttr ( const xmlAttrPtr attrA , const xmlAttrPtr attrB )
2012-02-20 03:40:15 +00:00
{
xmlChar * contentA ;
xmlChar * contentB ;
2012-02-21 08:21:12 +00:00
const xmlChar * nameA ;
const xmlChar * nameB ;
2012-02-20 03:40:15 +00:00
// what has to be the same for two attributes to be equal - - just their values ? ?
2012-02-21 08:21:12 +00:00
if ( attrB = = attrA )
2012-02-20 03:40:15 +00:00
{
return YES ;
}
2012-02-21 08:21:12 +00:00
if ( attrA = = NULL || attrB = = NULL )
2012-02-20 03:40:15 +00:00
{
return NO ;
}
2012-02-21 08:21:12 +00:00
nameA = attrA -> name ;
nameB = attrB -> name ;
2012-02-20 03:40:15 +00:00
2012-02-21 08:21:12 +00:00
if ( xmlStrcmp ( nameA , nameB ) = = 0 )
2012-02-20 03:40:15 +00:00
{
2012-02-21 08:21:12 +00:00
// get the content . . .
contentA = xmlNodeGetContent ( ( const xmlNodePtr ) attrA ) ;
contentB = xmlNodeGetContent ( ( const xmlNodePtr ) attrB ) ;
if ( xmlStrcmp ( contentA , contentB ) = = 0 )
2012-02-20 03:40:15 +00:00
{
2012-02-21 08:21:12 +00:00
xmlFree ( contentA ) ;
xmlFree ( contentB ) ;
2012-02-20 03:40:15 +00:00
return YES ;
}
2012-02-21 08:21:12 +00:00
xmlFree ( contentA ) ;
xmlFree ( contentB ) ;
2012-02-20 03:40:15 +00:00
return NO ;
}
return NO ;
}
2012-02-21 08:21:12 +00:00
xmlAttrPtr findAttrWithName ( xmlNodePtr node , const xmlChar * targetName )
2012-02-20 03:40:15 +00:00
{
xmlAttrPtr attr = node -> properties ;
// find an attr in node with the given name , and return it , else NULL
2012-02-21 08:21:12 +00:00
while ( ( attr ! = NULL ) && xmlStrcmp ( attr -> name , targetName ) ! = 0 )
2012-02-20 03:40:15 +00:00
{
attr = attr -> next ;
}
return attr ;
}
BOOL isEqualAttributes ( xmlNodePtr nodeA , xmlNodePtr nodeB )
{
xmlAttrPtr attrA = NULL ;
if ( countAttributes ( nodeA ) ! = countAttributes ( nodeB ) )
return NO ;
attrA = nodeA -> properties ;
2012-02-21 08:21:12 +00:00
while ( attrA )
2012-02-20 03:40:15 +00:00
{
2012-02-21 08:21:12 +00:00
xmlAttrPtr attrB = findAttrWithName ( nodeB , attrA -> name ) ;
2012-02-20 03:40:15 +00:00
if ( ! isEqualAttr ( attrA , attrB ) )
{
return NO ;
}
attrA = attrA -> next ;
}
return YES ;
}
BOOL isEqualNode ( xmlNodePtr nodeA , xmlNodePtr nodeB )
{
if ( nodeA = = nodeB )
return YES ;
if ( nodeA -> type ! = nodeB -> type )
return NO ;
2012-02-21 08:21:12 +00:00
if ( xmlStrcmp ( nodeA -> name , nodeB -> name ) ! = 0 )
2012-02-20 03:40:15 +00:00
return NO ;
if ( nodeA -> type = = XML_ELEMENT _NODE )
{
xmlChar * contentA = NULL ;
xmlChar * contentB = NULL ;
if ( ! isEqualAttributes ( nodeA , nodeB ) )
{
return NO ;
}
// Get the value of any text node underneath the current element .
contentA = xmlNodeGetContent ( ( const xmlNodePtr ) nodeA ) ;
contentB = xmlNodeGetContent ( ( const xmlNodePtr ) nodeB ) ;
2012-02-21 08:21:12 +00:00
if ( xmlStrcmp ( contentA , contentB ) ! = 0 )
2012-02-20 03:40:15 +00:00
{
2012-02-21 08:21:12 +00:00
xmlFree ( contentA ) ;
xmlFree ( contentB ) ;
2012-02-20 03:40:15 +00:00
return NO ;
}
2012-02-21 08:21:12 +00:00
xmlFree ( contentA ) ;
xmlFree ( contentB ) ;
2012-02-20 03:40:15 +00:00
}
return YES ;
}
BOOL isEqualTree ( xmlNodePtr nodeA , xmlNodePtr nodeB )
{
2012-02-21 08:21:12 +00:00
if ( nodeA = = nodeB )
2012-02-20 03:40:15 +00:00
{
return YES ;
}
if ( nodeA = = NULL || nodeB = = NULL )
{
return NO ;
}
if ( ! isEqualNode ( nodeA , nodeB ) )
{
return NO ;
}
if ( ! isEqualTree ( nodeA -> children , nodeB -> children ) )
{
return NO ;
}
if ( ! isEqualTree ( nodeA -> next , nodeB -> next ) )
{
return NO ;
}
return YES ;
}
// Private methods to manage libxml pointers . . .
@ interface NSXMLNode ( Private )
- ( void * ) _node ;
- ( void ) _setNode : ( void * ) _anode ;
+ ( NSXMLNode * ) _objectForNode : ( xmlNodePtr ) node ;
- ( void ) _addSubNode : ( NSXMLNode * ) subNode ;
- ( void ) _removeSubNode : ( NSXMLNode * ) subNode ;
- ( id ) _initWithNode : ( xmlNodePtr ) node kind : ( NSXMLNodeKind ) kind ;
- ( void ) _updateExternalRetains ;
- ( void ) _invalidate ;
@ end
@ implementation NSXMLNode ( Private )
- ( void * ) _node
{
return internal -> node ;
}
- ( void ) _setNode : ( void * ) _anode
{
if ( _anode )
( ( xmlNodePtr ) _anode ) -> _private = self ;
internal -> node = _anode ;
}
+ ( NSXMLNode * ) _objectForNode : ( xmlNodePtr ) node
{
NSXMLNode * result = nil ;
if ( node )
{
xmlElementType type = node -> type ;
// NSXMLNodeKind kind = 0 ;
result = node -> _private ;
if ( result = = nil )
{
switch ( type )
{
case ( XML_DOCUMENT _NODE ) :
result = [ [ NSXMLDocument alloc ] _initWithNode : node kind : NSXMLDocumentKind ] ;
break ;
case ( XML_ELEMENT _NODE ) :
result = [ [ NSXMLElement alloc ] _initWithNode : node kind : NSXMLElementKind ] ;
break ;
case ( XML_TEXT _NODE ) :
result = [ [ self alloc ] _initWithNode : node kind : NSXMLTextKind ] ;
break ;
case ( XML_PI _NODE ) :
result = [ [ self alloc ] _initWithNode : node kind : NSXMLProcessingInstructionKind ] ;
break ;
case ( XML_COMMENT _NODE ) :
result = [ [ self alloc ] _initWithNode : node kind : NSXMLCommentKind ] ;
break ;
case ( XML_ATTRIBUTE _NODE ) :
result = [ [ self alloc ] _initWithNode : node kind : NSXMLAttributeKind ] ;
break ;
default :
NSLog ( @ "ERROR: _objectForNode: called with a node of type %d" , type ) ;
break ;
}
// [ result _setNode : node ] ;
AUTORELEASE ( result ) ;
if ( node -> parent )
{
NSXMLNode * parent = [ NSXMLNode _objectForNode : node -> parent ] ;
[ parent _addSubNode : result ] ;
}
}
}
return result ;
}
- ( int ) _externalRetains
{
return internal -> externalRetains ;
}
- ( int ) verifyExternalRetains
{
int extraRetains = ( [ self retainCount ] > 1 ? 1 : 0 ) ; // start with 1 or 0 for ourself
int index ;
for ( index = 0 ; index < [ internal -> subNodes count ] ; index + + )
extraRetains + = [ [ internal -> subNodes objectAtIndex : index ] _externalRetains ] ;
return extraRetains ;
}
- ( void ) _updateExternalRetains
{
xmlNodePtr pnode = ( MY_NODE ? MY_NODE -> parent : NULL ) ;
NSXMLNode * parent = ( NSXMLNode * ) ( pnode ? pnode -> _private : nil ) ;
int oldCount = internal -> externalRetains ;
int extraRetains = ( [ self retainCount ] > 1 ? 1 : 0 ) ; // start with 1 or 0 for ourself
int index ;
for ( index = 0 ; index < [ internal -> subNodes count ] ; index + + )
extraRetains + = [ [ internal -> subNodes objectAtIndex : index ] _externalRetains ] ;
internal -> externalRetains = extraRetains ;
if ( extraRetains ! = oldCount )
{
if ( parent )
[ parent _updateExternalRetains ] ; // tell our parent ( if any ) since our count has changed
else
{ // we ' re the root node of this tree , so retain or release ourself as needed
if ( oldCount = = 0 && extraRetains > 0 )
{
[ super retain ] ;
internal -> retainedSelf + + ;
// NSLog ( @ "RETAINED SELF %@ (%d)" , self , internal -> retainedSelf ) ;
}
else if ( oldCount > 0 && extraRetains = = 0 && internal -> retainedSelf )
{
internal -> retainedSelf - - ;
// NSLog ( @ "RELEASED SELF %@ (%d)" , self , internal -> retainedSelf ) ;
[ super release ] ;
}
}
}
else
{
if ( ! parent )
{
if ( extraRetains > 0 && internal -> retainedSelf = = 0 )
{
[ super retain ] ;
internal -> retainedSelf + + ;
// NSLog ( @ "RETAINED SELF AFTER STATUS CHANGED %@ (%d)" , self , internal -> retainedSelf ) ;
}
else if ( extraRetains = = 0 && internal -> retainedSelf > 0 )
{
internal -> retainedSelf - - ;
// NSLog ( @ "RELEASED SELF AFTER STATUS CHANGED %@ (%d)" , self , internal -> retainedSelf ) ;
[ super release ] ;
}
}
}
}
- ( void ) _passExternalRetainsTo : ( NSXMLNode * ) parent
{
// this object just became a subNode , so pass knowledge of external retains up the line
if ( internal -> externalRetains > 0 )
{
// NSLog ( @ "_passExternalRetainsTo:%@ (%d,%d) from %@ Start:(%d,%d)" , parent , [ parent _externalRetains ] , [ parent verifyExternalRetains ] , self , internal -> externalRetains , [ self verifyExternalRetains ] ) ;
// if ( [ self retainCount ] = = 2 )
// {
// internal -> externalRetains - - ;
// NSLog ( @ "RELEASING TRICKY EXTRA RETAIN WHILE ADDING TO PARENT in %@ now: %d" , self , internal -> externalRetains ) ;
// }
// [ self _updateExternalRetains ] ;
if ( internal -> retainedSelf )
{
[ super release ] ; // we ' re no longer the root of our branch , so stop retaining ourself
internal -> retainedSelf - - ;
// NSLog ( @ "RELEASED SELF %@ (%d) in _passExternal..." , self , internal -> retainedSelf ) ;
}
[ parent _updateExternalRetains ] ;
// NSLog ( @ "DID _passExternalRetainsTo:%@ (%d,%d) from %@ End:(%d,%d)" , parent , [ parent _externalRetains ] , [ parent verifyExternalRetains ] , self , internal -> externalRetains , [ self verifyExternalRetains ] ) ;
}
}
- ( void ) _removeExternalRetainsFrom : ( NSXMLNode * ) parent
{
// this object is no longer a subNode , so pass removal of external retains up the line
if ( internal -> externalRetains > 0 )
{
// NSLog ( @ "_removeExternalRetainsTo:%@ from %@ Start: %d" , parent , self , internal -> externalRetains ) ;
// / [ parent releaseExternalRetain : internal -> externalRetains ] ;
if ( [ self retainCount ] = = 1 )
{
internal -> externalRetains + + ;
// NSLog ( @ "ADDED TRICKY EXTRA COUNT WHILE REMOVING FROM PARENT in %@ now: %d subNodes(low):%d" , self , internal -> externalRetains , [ self verifyExternalRetains ] ) ;
}
[ super retain ] ; // becoming detached , so retain ourself as the new root of our branch
internal -> retainedSelf + + ;
// NSLog ( @ "RETAINED SELF %@ (%d) in _removeExternal..." , self , internal -> retainedSelf ) ;
[ parent _updateExternalRetains ] ;
}
}
- ( void ) _addSubNode : ( NSXMLNode * ) subNode
{
if ( ! internal -> subNodes )
internal -> subNodes = [ [ NSMutableArray alloc ] init ] ;
if ( [ internal -> subNodes indexOfObjectIdenticalTo : subNode ] = = NSNotFound )
{
[ internal -> subNodes addObject : subNode ] ;
[ subNode _passExternalRetainsTo : self ] ;
}
}
- ( void ) _removeSubNode : ( NSXMLNode * ) subNode
{
[ subNode retain ] ; // retain temporarily so we can safely remove from our subNodes list first
[ internal -> subNodes removeObjectIdenticalTo : subNode ] ;
[ subNode _removeExternalRetainsFrom : self ] ;
[ subNode release ] ; // release temporary hold
}
- ( void ) _createInternal
{
GS_CREATE _INTERNAL ( NSXMLNode ) ;
}
- ( id ) _initWithNode : ( xmlNodePtr ) node kind : ( NSXMLNodeKind ) kind
{
if ( ( self = [ super init ] ) )
{
[ self _createInternal ] ;
[ self _setNode : node ] ;
internal -> kind = kind ;
}
return self ;
}
- ( void ) _invalidate
{
internal -> kind = NSXMLInvalidKind ;
[ self _setNode : NULL ] ;
}
@ end
void clearPrivatePointers ( xmlNodePtr aNode )
{
if ( ! aNode )
return ;
aNode -> _private = NULL ;
clearPrivatePointers ( aNode -> children ) ;
clearPrivatePointers ( aNode -> next ) ;
if ( aNode -> type = = XML_ELEMENT _NODE )
clearPrivatePointers ( ( xmlNodePtr ) ( aNode -> properties ) ) ;
}
int register_namespaces ( xmlXPathContextPtr xpathCtx ,
const xmlChar * nsList )
{
xmlChar * nsListDup ;
xmlChar * prefix ;
xmlChar * href ;
xmlChar * next ;
assert ( xpathCtx ) ;
assert ( nsList ) ;
nsListDup = xmlStrdup ( nsList ) ;
if ( nsListDup = = NULL ) {
NSLog ( @ "Error: unable to strdup namespaces list" ) ;
return ( -1 ) ;
}
next = nsListDup ;
while ( next ! = NULL ) {
/ * skip spaces * /
while ( ( * next ) = = ' ' ) next + + ;
if ( ( * next ) = = ' \ 0 ' ) break ;
/ * find prefix * /
prefix = next ;
next = ( xmlChar * ) xmlStrchr ( next , ' = ' ) ;
if ( next = = NULL ) {
NSLog ( @ "Error: invalid namespaces list format" ) ;
xmlFree ( nsListDup ) ;
return ( -1 ) ;
}
* ( next + + ) = ' \ 0 ' ;
/ * find href * /
href = next ;
next = ( xmlChar * ) xmlStrchr ( next , ' ' ) ;
if ( next ! = NULL ) {
* ( next + + ) = ' \ 0 ' ;
}
/ * do register namespace * /
if ( xmlXPathRegisterNs ( xpathCtx , prefix , href ) ! = 0 ) {
NSLog ( @ "Error: unable to register NS with prefix=\" % s \ " and href=\" % s \ "" , prefix , href ) ;
xmlFree ( nsListDup ) ;
return ( -1 ) ;
}
}
xmlFree ( nsListDup ) ;
return ( 0 ) ;
}
NSArray * execute_xpath ( NSXMLNode * node ,
NSString * xpath_exp ,
NSString * nmspaces )
{
xmlDocPtr doc = ( ( xmlNodePtr ) [ node _node ] ) -> doc ;
NSMutableArray * result = [ NSMutableArray arrayWithCapacity : 10 ] ;
xmlChar * xpathExpr = ( xmlChar * ) XMLSTRING ( xpath_exp ) ;
xmlChar * nsList = ( xmlChar * ) XMLSTRING ( nmspaces ) ;
xmlXPathContextPtr xpathCtx = NULL ;
xmlXPathObjectPtr xpathObj = NULL ;
xmlNodeSetPtr nodeset = NULL ;
xmlNodePtr cur = NULL ;
int i = 0 ;
assert ( xpathExpr ) ;
/ * Create xpath evaluation context * /
xpathCtx = xmlXPathNewContext ( doc ) ;
if ( ! xpathCtx )
{
NSLog ( @ "Error: unable to create new XPath context." ) ;
return nil ;
}
/ * Register namespaces from list ( if any ) * /
if ( ( nsList ! = NULL ) && ( register_namespaces ( xpathCtx , nsList ) < 0 ) )
{
NSLog ( @ "Error: failed to register namespaces list \" % s \ "" , nsList ) ;
xmlXPathFreeContext ( xpathCtx ) ;
return nil ;
}
if ( ! [ xpath_exp hasPrefix : @ "/" ] )
xpathCtx -> node = ( xmlNodePtr ) doc ; // provide a context for relative paths
/ * Evaluate xpath expression * /
xpathObj = xmlXPathEvalExpression ( xpathExpr , xpathCtx ) ;
if ( xpathObj = = NULL )
{
NSLog ( @ "Error: unable to evaluate xpath expression \" % s \ "" , xpathExpr ) ;
xmlXPathFreeContext ( xpathCtx ) ;
xmlFreeDoc ( doc ) ;
return nil ;
}
/ * results * /
nodeset = xpathObj -> nodesetval ;
/ *
if ( nodeset = = NULL || nodeset -> nodeNr = = 0 )
{
xpathObj = xmlXPathEval ( xpathExpr , xpathCtx ) ;
if ( xpathObj ! = NULL )
nodeset = xpathObj -> nodesetval ;
if ( nodeset )
NSLog ( @ "Succeeded in evaluating as a path, using xmlXPathEval" ) ;
}
* /
if ( nodeset )
{
/ * Collect results * /
for ( i = 0 ; i < nodeset -> nodeNr ; i + + )
{
id obj = nil ;
cur = nodeset -> nodeTab [ i ] ;
obj = [ NSXMLNode _objectForNode : cur ] ;
if ( obj )
{
[ result addObject : obj ] ;
}
}
}
/ * Cleanup * /
xmlXPathFreeObject ( xpathObj ) ;
xmlXPathFreeContext ( xpathCtx ) ;
return result ;
}
2011-10-17 10:24:07 +00:00
2009-02-09 16:16:11 +00:00
@ implementation NSXMLNode
+ ( id ) attributeWithName : ( NSString * ) name
stringValue : ( NSString * ) stringValue
{
NSXMLNode * n ;
2012-02-20 03:40:15 +00:00
xmlAttrPtr node = xmlNewProp ( NULL ,
XMLSTRING ( name ) ,
XMLSTRING ( stringValue ) ) ;
2009-02-09 16:16:11 +00:00
n = [ [ [ self alloc ] initWithKind : NSXMLAttributeKind ] autorelease ] ;
[ n setStringValue : stringValue ] ;
2011-12-30 21:40:12 +00:00
[ n setName : name ] ;
2012-02-20 03:40:15 +00:00
[ n _setNode : ( void * ) node ] ;
2009-02-09 16:16:11 +00:00
return n ;
}
+ ( id ) attributeWithName : ( NSString * ) name
URI : ( NSString * ) URI
stringValue : ( NSString * ) stringValue
{
NSXMLNode * n ;
2012-02-20 03:40:15 +00:00
xmlAttrPtr node = xmlNewProp ( NULL ,
XMLSTRING ( name ) ,
XMLSTRING ( stringValue ) ) ;
2009-02-09 16:16:11 +00:00
n = [ [ [ self alloc ] initWithKind : NSXMLAttributeKind ] autorelease ] ;
[ n setURI : URI ] ;
[ n setStringValue : stringValue ] ;
2011-12-30 21:40:12 +00:00
[ n setName : name ] ;
2012-02-20 03:40:15 +00:00
[ n _setNode : node ] ;
2009-02-09 16:16:11 +00:00
return n ;
}
+ ( id ) commentWithStringValue : ( NSString * ) stringValue
{
NSXMLNode * n ;
2012-02-20 03:40:15 +00:00
xmlNodePtr node = xmlNewComment ( XMLSTRING ( stringValue ) ) ;
2009-02-09 16:16:11 +00:00
n = [ [ [ self alloc ] initWithKind : NSXMLCommentKind ] autorelease ] ;
[ n setStringValue : stringValue ] ;
2012-02-20 03:40:15 +00:00
[ n _setNode : node ] ;
2009-02-09 16:16:11 +00:00
return n ;
}
+ ( id ) DTDNodeWithXMLString : ( NSString * ) string
{
NSXMLNode * n ;
n = [ [ [ self alloc ] initWithKind : NSXMLDTDKind ] autorelease ] ;
[ n setStringValue : string ] ;
2012-02-20 03:40:15 +00:00
// internal -> node = xmlNewDtd ( NULL , NULL , NULL ) ; // TODO : Parse the string and get the info to create this . . .
2009-02-09 16:16:11 +00:00
return n ;
}
+ ( id ) document
{
NSXMLNode * n ;
n = [ [ [ NSXMLDocument alloc ] initWithKind : NSXMLDocumentKind ] autorelease ] ;
return n ;
}
+ ( id ) documentWithRootElement : ( NSXMLElement * ) element
{
NSXMLDocument * d ;
d = [ NSXMLDocument alloc ] ;
d = [ [ d initWithRootElement : element ] autorelease ] ;
return d ;
}
+ ( id ) elementWithName : ( NSString * ) name
{
NSXMLNode * n ;
n = [ [ [ NSXMLElement alloc ] initWithName : name ] autorelease ] ;
return n ;
}
+ ( id ) elementWithName : ( NSString * ) name
children : ( NSArray * ) children
attributes : ( NSArray * ) attributes
{
NSXMLElement * e = [ self elementWithName : name ] ;
[ e insertChildren : children atIndex : 0 ] ;
[ e setAttributes : attributes ] ;
return e ;
}
+ ( id ) elementWithName : ( NSString * ) name
URI : ( NSString * ) URI
{
NSXMLNode * n ;
n = [ [ [ NSXMLElement alloc ] initWithName : name URI : URI ] autorelease ] ;
return n ;
}
+ ( id ) elementWithName : ( NSString * ) name
stringValue : ( NSString * ) string
{
NSXMLElement * e ;
NSXMLNode * t ;
2011-10-01 18:43:29 +00:00
e = [ self elementWithName : name ] ;
2009-02-09 16:16:11 +00:00
t = [ [ self alloc ] initWithKind : NSXMLTextKind ] ;
[ t setStringValue : string ] ;
[ e addChild : t ] ;
[ t release ] ;
return e ;
}
+ ( NSString * ) localNameForName : ( NSString * ) name
{
return [ self notImplemented : _cmd ] ;
}
+ ( id ) namespaceWithName : ( NSString * ) name
stringValue : ( NSString * ) stringValue
{
NSXMLNode * n ;
n = [ [ [ self alloc ] initWithKind : NSXMLNamespaceKind ] autorelease ] ;
[ n setStringValue : stringValue ] ;
return n ;
}
+ ( NSXMLNode * ) predefinedNamespaceForPrefix : ( NSString * ) name
{
return [ self notImplemented : _cmd ] ;
}
+ ( NSString * ) prefixForName : ( NSString * ) name
{
return [ self notImplemented : _cmd ] ;
}
+ ( id ) processingInstructionWithName : ( NSString * ) name
stringValue : ( NSString * ) stringValue
{
NSXMLNode * n ;
n = [ [ [ self alloc ] initWithKind : NSXMLProcessingInstructionKind ] autorelease ] ;
[ n setStringValue : stringValue ] ;
return n ;
}
+ ( id ) textWithStringValue : ( NSString * ) stringValue
{
NSXMLNode * n ;
n = [ [ [ self alloc ] initWithKind : NSXMLTextKind ] autorelease ] ;
[ n setStringValue : stringValue ] ;
return n ;
}
- ( NSString * ) canonicalXMLStringPreservingComments : ( BOOL ) comments
{
return [ self notImplemented : _cmd ] ; // FIXME . . . generate from libxml
}
2012-02-20 03:40:15 +00:00
- ( xmlNodePtr ) _childNodeAtIndex : ( NSUInteger ) index
{
NSUInteger count = 0 ;
xmlNodePtr node = ( xmlNodePtr ) ( internal -> node ) ;
xmlNodePtr children = node -> children ;
if ( ! children )
return NULL ; // the Cocoa docs say it returns nil if there are no children
for ( children = node -> children ; children ! = NULL && count ! = index ; children = children -> next )
{
count + + ;
}
if ( count ! = index )
[ NSException raise : NSRangeException format : @ "child index too large" ] ;
return children ;
}
2009-02-09 16:16:11 +00:00
- ( NSXMLNode * ) childAtIndex : ( NSUInteger ) index
{
2012-02-20 03:40:15 +00:00
xmlNodePtr childNode = [ self _childNodeAtIndex : index ] ;
return ( NSXMLNode * ) [ NSXMLNode _objectForNode : childNode ] ;
2009-02-09 16:16:11 +00:00
}
- ( NSUInteger ) childCount
{
2012-02-20 03:40:15 +00:00
NSUInteger count = 0 ;
xmlNodePtr children = NULL ;
xmlNodePtr node = MY_NODE ;
for ( children = node -> children ; children ; children = children -> next )
{
count + + ;
}
return count ;
2009-02-09 16:16:11 +00:00
}
2012-01-06 12:22:30 +00:00
- ( NSArray * ) children
2009-02-09 16:16:11 +00:00
{
2012-02-20 03:40:15 +00:00
NSMutableArray * childrenArray = nil ;
if ( NSXMLInvalidKind = = internal -> kind )
{
return nil ;
}
else
{
xmlNodePtr children = NULL ;
xmlNodePtr node = ( xmlNodePtr ) ( internal -> node ) ;
if ( node -> children = = NULL )
{
return nil ;
}
childrenArray = [ NSMutableArray array ] ;
for ( children = node -> children ; children ; children = children -> next )
{
NSXMLNode * n = [ NSXMLNode _objectForNode : children ] ;
[ childrenArray addObject : n ] ;
}
}
return childrenArray ;
}
- ( void ) _insertChild : ( NSXMLNode * ) child atIndex : ( NSUInteger ) index
{
// this private method provides the common insertion implementation used by NSXMLElement and NSXMLDocument
// Get all of the nodes . . .
xmlNodePtr parentNode = MY_NODE ; // we are the parent
xmlNodePtr childNode = ( ( xmlNodePtr ) [ child _node ] ) ;
xmlNodePtr curNode = [ self _childNodeAtIndex : index ] ;
BOOL mergeTextNodes = NO ; // is there a defined option for this ?
if ( mergeTextNodes || childNode -> type = = XML_ATTRIBUTE _NODE )
{
// this uses the built - in libxml functions which merge adjacent text nodes
xmlNodePtr addedNode = NULL ;
// curNode = ( ( xmlNodePtr ) [ cur _node ] ) ;
if ( curNode = = NULL ) // ( 0 = = childCount || index = = childCount )
{
addedNode = xmlAddChild ( parentNode , childNode ) ;
}
else // if ( index < childCount )
{
addedNode = xmlAddPrevSibling ( curNode , childNode ) ;
}
if ( addedNode ! = childNode )
{
[ child _setNode : NULL ] ;
child = [ NSXMLNode _objectForNode : addedNode ] ;
}
}
else
{
// here we avoid merging adjacent text nodes by linking the new node in "by hand"
childNode -> parent = parentNode ;
if ( curNode )
{
// insert childNode before an existing node curNode
xmlNodePtr prevNode = curNode -> prev ;
curNode -> prev = childNode ;
childNode -> next = curNode ;
if ( prevNode )
{
childNode -> prev = prevNode ;
prevNode -> next = childNode ;
}
else
{
// in this case , this is the new "first child" , so update our parent to point to it
parentNode -> children = childNode ;
}
}
else
{
// not inserting before an existing node . . . add as new "last child"
xmlNodePtr formerLastChild = parentNode -> last ;
if ( formerLastChild )
{
formerLastChild -> next = childNode ;
childNode -> prev = formerLastChild ;
parentNode -> last = childNode ;
}
else
{
// no former children - - this is the first
parentNode -> children = childNode ;
parentNode -> last = childNode ;
}
}
}
[ self _addSubNode : child ] ;
2009-02-09 16:16:11 +00:00
}
- ( id ) copyWithZone : ( NSZone * ) zone
{
2012-01-06 02:43:26 +00:00
id c = [ [ self class ] allocWithZone : zone ] ;
2012-02-20 03:40:15 +00:00
xmlNodePtr newNode = xmlCopyNode ( [ self _node ] , 1 ) ; // make a deep copy
clearPrivatePointers ( newNode ) ;
// c = [ c initWithKind : internal -> kind options : internal -> options ] ;
// [ c _setNode : newNode ] ;
c = [ c _initWithNode : newNode kind : internal -> kind ] ;
2012-01-04 12:41:45 +00:00
2012-02-20 03:40:15 +00:00
// [ c setName : [ self name ] ] ;
// [ c setURI : [ self URI ] ] ;
// [ c setObjectValue : [ self objectValue ] ] ;
// [ c setStringValue : [ self stringValue ] ] ;
2012-01-06 02:43:26 +00:00
2012-01-04 12:41:45 +00:00
return c ;
2012-01-06 12:48:49 +00:00
}
2009-02-09 16:16:11 +00:00
2012-02-20 03:40:15 +00:00
/ * * these methods should go away now
- ( void ) recordExternalRetain : ( int ) count
{
id parent = [ self parent ] ;
if ( parent )
[ parent recordExternalRetain : count ] ;
else
{
if ( count > 0 && internal -> externalRetains = = 0 )
{
[ super retain ] ; // the top of the tree retains itself whenever there are external retains anywhere
if ( [ self retainCount ] = = 2 )
{
internal -> externalRetains + + ;
NSLog ( @ "ADDED TRICKY EXTRA COUNT in %@ now: %d subNodes(OFF):%d" , self , internal -> externalRetains , [ self verifyExternalRetains ] ) ;
}
}
}
internal -> externalRetains + = count ;
NSLog ( @ "recordExternalRetain in %@ now: %d subNodes:%d" , self , internal -> externalRetains , [ self verifyExternalRetains ] ) ;
}
- ( void ) releaseExternalRetain : ( int ) count
{
id parent = [ self parent ] ;
internal -> externalRetains - = count ;
if ( internal -> externalRetains < 0 )
NSLog ( @ "ExternalRetains going NEGATIVE: %d in %@" , internal -> externalRetains - count , self ) ;
NSLog ( @ "releaseExternalRetain in %@ now: %d" , self , internal -> externalRetains ) ;
if ( parent )
[ parent releaseExternalRetain : count ] ;
else
{
// check for tricky condition where our only "external" retain is from ourself and is about to go away
if ( count > 0 && internal -> externalRetains = = 1 && [ self retainCount ] = = 2 )
{
internal -> externalRetains - - ;
NSLog ( @ "RELEASING TRICKY EXTRA RETAIN in %@ now: %d" , self , internal -> externalRetains ) ;
}
if ( count > 0 && internal -> externalRetains = = 0 )
[ super release ] ; // the top of the tree retains itself whenever there are external retains anywhere
}
}
* * /
- ( id ) retain
{
[ super retain ] ; // do this first
if ( [ self retainCount ] = = 2 )
{
[ self _updateExternalRetains ] ; // [ self recordExternalRetain : 1 ] ;
}
return self ;
}
- ( void ) release
{
if ( [ self retainCount ] = = 2 )
{
[ super release ] ;
[ self _updateExternalRetains ] ; // [ self releaseExternalRetain : 1 ] ;
}
else
[ super release ] ;
}
2009-02-09 16:16:11 +00:00
- ( void ) dealloc
{
2012-01-04 12:41:45 +00:00
if ( GS_EXISTS _INTERNAL )
{
2012-02-20 03:40:15 +00:00
xmlNodePtr node = ( xmlNodePtr ) ( internal -> node ) ;
2012-01-04 12:41:45 +00:00
[ internal -> URI release ] ;
[ internal -> objectValue release ] ;
2012-02-20 03:40:15 +00:00
[ internal -> subNodes release ] ;
if ( node )
node -> _private = NULL ;
if ( node && node -> parent = = NULL )
{
if ( node -> type = = XML_DOCUMENT _NODE )
xmlFreeDoc ( ( xmlDocPtr ) node ) ;
else
xmlFreeNode ( node ) ; // the top level node frees the entire tree
}
2012-01-04 12:41:45 +00:00
GS_DESTROY _INTERNAL ( NSXMLNode ) ;
}
2009-02-09 16:16:11 +00:00
[ super dealloc ] ;
}
- ( void ) detach
{
2012-02-20 03:40:15 +00:00
xmlNodePtr node = ( xmlNodePtr ) ( internal -> node ) ;
if ( node )
{
int extraRetains = 0 ;
xmlNodePtr parentNode = node -> parent ;
NSXMLNode * parent = ( parentNode ? parentNode -> _private : nil ) ; // get our parent object if it exists
xmlUnlinkNode ( node ) ; // separate our node from its parent and siblings
if ( parent )
{
// transfer extra retains of this branch from our parent to ourself
extraRetains = internal -> externalRetains ; // [ self verifyExternalRetains ] ;
if ( extraRetains )
{
// / [ parent releaseExternalRetain : extraRetains ] ;
if ( [ self retainCount ] = = 1 )
{
internal -> externalRetains + + ;
// NSLog ( @ "ADDED TRICKY EXTRA COUNT WHILE DETACHING in %@ now: %d subNodes(low):%d" , self , internal -> externalRetains , [ self verifyExternalRetains ] ) ;
}
[ super retain ] ; // [ self recordExternalRetain : extraRetains ] ;
internal -> retainedSelf + + ;
// NSLog ( @ "RETAINED SELF %@ (%d) in detach" , self , internal -> retainedSelf ) ;
}
[ parent _removeSubNode : self ] ;
}
// NSLog ( @ "DETACHED %@ from %@ and transferred extra retains: %d" , self , parent , extraRetains ) ;
}
2009-02-09 16:16:11 +00:00
}
2012-01-06 12:22:30 +00:00
- ( NSUInteger ) hash
{
2012-02-20 03:40:15 +00:00
return [ StringFromXMLStringPtr ( MY_NODE -> name ) hash ] ;
2012-01-06 12:22:30 +00:00
}
2009-02-09 16:16:11 +00:00
- ( NSUInteger ) index
{
2012-02-20 03:40:15 +00:00
int count = 0 ;
xmlNodePtr node = ( xmlNodePtr ) ( internal -> node ) ;
while ( ( node = node -> prev ) )
2012-01-07 13:08:03 +00:00
{
2012-02-20 03:40:15 +00:00
count + + ; // count our earlier sibling nodes
2012-01-07 13:08:03 +00:00
}
2012-02-20 03:40:15 +00:00
return count ;
2009-02-09 16:16:11 +00:00
}
2011-10-01 18:43:29 +00:00
- ( id ) init
{
return [ self initWithKind : NSXMLInvalidKind ] ;
}
2009-02-09 16:16:11 +00:00
- ( id ) initWithKind : ( NSXMLNodeKind ) kind
{
self = [ self initWithKind : kind options : 0 ] ;
return self ;
}
2011-10-01 18:43:29 +00:00
- ( id ) initWithKind : ( NSXMLNodeKind ) kind options : ( NSUInteger ) theOptions
2009-02-09 16:16:11 +00:00
{
2011-10-01 18:43:29 +00:00
Class theSubclass = [ NSXMLNode class ] ;
2012-02-20 03:40:15 +00:00
void * node = NULL ;
2012-01-04 12:41:45 +00:00
2011-10-01 18:43:29 +00:00
if ( nil = = ( self = [ super init ] ) )
2012-01-01 07:38:53 +00:00
{
return nil ;
}
2011-10-01 18:43:29 +00:00
/ *
* We find the correct subclass for specific node kinds :
* /
switch ( kind )
{
2012-02-20 03:40:15 +00:00
case NSXMLDocumentKind :
theSubclass = [ NSXMLDocument class ] ;
break ;
case NSXMLInvalidKind :
theSubclass = [ NSXMLNode class ] ;
break ;
case NSXMLElementKind :
theSubclass = [ NSXMLElement class ] ;
break ;
case NSXMLDTDKind :
theSubclass = [ NSXMLDTD class ] ;
break ;
case NSXMLEntityDeclarationKind :
case NSXMLElementDeclarationKind :
case NSXMLNotationDeclarationKind :
theSubclass = [ NSXMLDTDNode class ] ;
break ;
case NSXMLAttributeDeclarationKind :
[ self release ] ;
return nil ;
break ;
case NSXMLProcessingInstructionKind :
case NSXMLCommentKind :
case NSXMLTextKind :
case NSXMLNamespaceKind :
case NSXMLAttributeKind :
break ;
default :
kind = NSXMLInvalidKind ;
theSubclass = [ NSXMLNode class ] ;
break ;
2011-10-01 18:43:29 +00:00
}
/ *
* Check whether we are already initializing an instance of the given
* subclass . If we are not , release ourselves and allocate a subclass instance
* instead .
* /
if ( NO = = [ self isKindOfClass : theSubclass ] )
2012-01-01 07:38:53 +00:00
{
[ self release ] ;
return [ [ theSubclass alloc ] initWithKind : kind
options : theOptions ] ;
}
2011-10-01 18:43:29 +00:00
2012-02-20 03:40:15 +00:00
switch ( kind )
{
case NSXMLDocumentKind :
node = xmlNewDoc ( ( xmlChar * ) "1.0" ) ;
break ;
case NSXMLInvalidKind :
case NSXMLElementKind :
node = xmlNewNode ( NULL , ( xmlChar * ) "" ) ;
break ;
case NSXMLDTDKind :
node = xmlNewDtd ( NULL , ( xmlChar * ) "" , ( xmlChar * ) "" , ( xmlChar * ) "" ) ;
break ;
case NSXMLEntityDeclarationKind :
case NSXMLElementDeclarationKind :
case NSXMLNotationDeclarationKind :
node = xmlNewNode ( NULL , ( xmlChar * ) "" ) ;
break ;
case NSXMLProcessingInstructionKind :
node = xmlNewPI ( ( xmlChar * ) "" , ( xmlChar * ) "" ) ;
break ;
case NSXMLCommentKind :
node = xmlNewComment ( ( xmlChar * ) "" ) ;
break ;
case NSXMLTextKind :
node = xmlNewText ( ( xmlChar * ) "" ) ;
break ;
case NSXMLNamespaceKind :
node = xmlNewNs ( NULL , ( xmlChar * ) "" , ( xmlChar * ) "" ) ;
break ;
case NSXMLAttributeKind :
node = xmlNewProp ( NULL , ( xmlChar * ) "" , ( xmlChar * ) "" ) ;
break ;
default :
break ;
}
2012-01-04 12:41:45 +00:00
/ * Create holder for internal instance variables if needed .
2011-10-01 18:43:29 +00:00
* /
2012-02-20 03:40:15 +00:00
[ self _createInternal ] ;
/ * Create libxml object to go with it . . .
* /
[ self _setNode : node ] ;
2011-10-01 18:43:29 +00:00
2012-01-04 12:41:45 +00:00
/ * If we are initializing for the correct class , we can actually perform
* initializations :
* /
internal -> kind = kind ;
2012-01-04 09:20:32 +00:00
internal -> options = theOptions ;
2009-02-09 16:16:11 +00:00
return self ;
}
2012-01-06 12:22:30 +00:00
- ( BOOL ) isEqual : ( id ) other
{
2012-02-20 03:40:15 +00:00
if ( [ self kind ] ! = [ other kind ] )
2012-01-06 12:22:30 +00:00
{
return NO ;
}
2012-02-20 03:40:15 +00:00
return isEqualTree ( MY_NODE , ( xmlNodePtr ) [ other _node ] ) ;
2012-01-06 12:22:30 +00:00
}
2009-02-09 16:16:11 +00:00
- ( NSXMLNodeKind ) kind
{
2012-01-04 12:41:45 +00:00
return internal -> kind ;
2009-02-09 16:16:11 +00:00
}
- ( NSUInteger ) level
{
NSUInteger level = 0 ;
2012-02-20 03:40:15 +00:00
xmlNodePtr tmp = MY_NODE -> parent ;
2009-02-09 16:16:11 +00:00
2012-02-20 03:40:15 +00:00
while ( tmp ! = NULL )
2009-02-09 16:16:11 +00:00
{
level + + ;
2012-02-20 03:40:15 +00:00
tmp = tmp -> parent ;
2009-02-09 16:16:11 +00:00
}
return level ;
}
- ( NSString * ) localName
{
return [ self notImplemented : _cmd ] ; // FIXME . . . fetch from libxml
}
- ( NSString * ) name
{
2012-02-20 03:40:15 +00:00
if ( NSXMLInvalidKind = = internal -> kind )
{
return nil ;
}
return StringFromXMLStringPtr ( MY_NODE -> name ) ;
2009-02-09 16:16:11 +00:00
}
2011-10-01 18:43:29 +00:00
- ( NSXMLNode * ) _nodeFollowingInNaturalDirection : ( BOOL ) forward
{
2012-01-04 12:41:45 +00:00
NSXMLNode * ancestor = internal -> parent ;
2011-10-01 18:43:29 +00:00
NSXMLNode * candidate = nil ;
/ * Node walking is a depth - first thingy . Hence , we consider children first : * /
2012-02-20 03:40:15 +00:00
if ( 0 ! = [ self childCount ] )
2011-10-01 18:43:29 +00:00
{
2012-01-01 07:38:53 +00:00
NSUInteger theIndex = 0 ;
if ( NO = = forward )
{
2012-02-20 03:40:15 +00:00
theIndex = ( [ self childCount ] ) - 1 ;
2012-01-01 07:38:53 +00:00
}
2012-02-20 03:40:15 +00:00
candidate = [ [ self children ] objectAtIndex : theIndex ] ;
2011-10-01 18:43:29 +00:00
}
/ * If there are no children , we move on to siblings : * /
if ( nil = = candidate )
{
2012-01-01 07:38:53 +00:00
if ( forward )
{
2012-01-04 09:20:32 +00:00
candidate = internal -> nextSibling ;
2012-01-01 07:38:53 +00:00
}
else
{
2012-01-04 09:20:32 +00:00
candidate = internal -> previousSibling ;
2012-01-01 07:38:53 +00:00
}
2011-10-01 18:43:29 +00:00
}
/ * If there are no siblings left for the receiver , we recurse down to the root
* of the tree until we find an ancestor with further siblings : * /
while ( ( nil = = candidate ) && ( nil ! = ancestor ) )
{
2012-01-01 07:38:53 +00:00
if ( forward )
{
candidate = [ ancestor nextSibling ] ;
}
else
{
candidate = [ ancestor previousSibling ] ;
}
2012-01-04 12:41:45 +00:00
ancestor = GSIVar ( ancestor , parent ) ;
2011-10-01 18:43:29 +00:00
}
/ * No children , no next siblings , no next siblings for any ancestor : We are
* the last node * /
if ( nil = = candidate )
2012-01-01 07:38:53 +00:00
{
return nil ;
}
2011-10-01 18:43:29 +00:00
/ * Sanity check : Namespace and attribute nodes are skipped : * /
2012-01-04 12:41:45 +00:00
if ( ( NSXMLAttributeKind = = GSIVar ( candidate , kind ) )
|| ( NSXMLNamespaceKind = = GSIVar ( candidate , kind ) ) )
2012-01-01 07:38:53 +00:00
{
return [ candidate _nodeFollowingInNaturalDirection : forward ] ;
}
2011-10-01 18:43:29 +00:00
return candidate ;
}
2009-02-09 16:16:11 +00:00
- ( NSXMLNode * ) nextNode
{
2011-10-01 18:43:29 +00:00
return [ self _nodeFollowingInNaturalDirection : YES ] ;
2009-02-09 16:16:11 +00:00
}
- ( NSXMLNode * ) nextSibling
{
2012-02-20 03:40:15 +00:00
xmlNodePtr next = MY_NODE -> next ;
if ( next ! = NULL )
{
return [ NSXMLNode _objectForNode : next ] ;
}
return nil ;
2009-02-09 16:16:11 +00:00
}
- ( id ) objectValue
{
2012-01-04 12:41:45 +00:00
return internal -> objectValue ;
2009-02-09 16:16:11 +00:00
}
- ( NSXMLNode * ) parent
{
2012-02-20 03:40:15 +00:00
return [ NSXMLNode _objectForNode : MY_NODE -> parent ] ;
2009-02-09 16:16:11 +00:00
}
- ( NSString * ) prefix
{
return [ self notImplemented : _cmd ] ; // FIXME . . . fetch from libxml
}
- ( NSXMLNode * ) previousNode
{
2011-10-01 18:43:29 +00:00
return [ self _nodeFollowingInNaturalDirection : NO ] ;
2009-02-09 16:16:11 +00:00
}
- ( NSXMLNode * ) previousSibling
{
2012-02-20 03:40:15 +00:00
xmlNodePtr prev = MY_NODE -> prev ;
2011-10-01 18:43:29 +00:00
2012-02-20 03:40:15 +00:00
if ( prev ! = NULL )
{
return [ NSXMLNode _objectForNode : prev ] ;
}
return nil ;
2009-02-09 16:16:11 +00:00
}
- ( NSXMLDocument * ) rootDocument
{
2012-02-20 03:40:15 +00:00
xmlNodePtr node = MY_NODE ;
NSXMLDocument * ancestor = ( NSXMLDocument * ) [ NSXMLNode _objectForNode : ( xmlNodePtr ) ( node -> doc ) ] ;
return ancestor ;
2009-02-09 16:16:11 +00:00
}
- ( NSString * ) stringValue
{
2012-02-20 03:40:15 +00:00
xmlNodePtr node = MY_NODE ;
xmlChar * content = xmlNodeGetContent ( node ) ;
NSString * result = nil ;
/ *
if ( node -> type = = XML_ATTRIBUTE _NODE ||
node -> type = = XML_ELEMENT _NODE )
{
node = node -> children ;
}
* /
result = StringFromXMLStringPtr ( content ) ;
return result ;
2009-02-09 16:16:11 +00:00
}
- ( NSString * ) URI
{
2012-02-20 03:40:15 +00:00
if ( NSXMLInvalidKind = = internal -> kind )
{
return nil ;
}
2012-01-04 12:41:45 +00:00
return internal -> URI ; // FIXME . . . fetch from libxml
2009-02-09 16:16:11 +00:00
}
- ( NSString * ) XMLString
{
return [ self XMLStringWithOptions : 0 ] ;
}
- ( NSString * ) XMLStringWithOptions : ( NSUInteger ) options
{
2012-02-20 03:40:15 +00:00
NSString * string = nil ;
xmlNodePtr node = ( xmlNodePtr ) [ self _node ] ;
xmlChar * buf = NULL ;
xmlDocPtr doc = node -> doc ;
xmlBufferPtr buffer = xmlBufferCreate ( ) ; // NULL ;
int error = 0 ;
int len = 0 ;
error = xmlNodeDump ( buffer , doc , node , 1 , 1 ) ;
buf = buffer -> content ;
len = buffer -> use ;
string = StringFromXMLString ( buf , len ) ;
xmlBufferFree ( buffer ) ;
return string ;
2009-02-09 16:16:11 +00:00
}
- ( void ) setObjectValue : ( id ) value
{
2012-02-20 03:40:15 +00:00
if ( nil = = value )
{
ASSIGN ( internal -> objectValue , [ NSString stringWithString : @ "" ] ) ;
return ;
}
2012-01-04 12:41:45 +00:00
ASSIGN ( internal -> objectValue , value ) ;
2009-02-09 16:16:11 +00:00
}
2012-01-02 07:27:56 +00:00
- ( void ) setName : ( NSString * ) name
2009-02-09 16:16:11 +00:00
{
2012-01-06 12:22:30 +00:00
if ( NSXMLInvalidKind ! = internal -> kind )
{
2012-02-20 03:40:15 +00:00
xmlNodePtr node = MY_NODE ;
xmlNodeSetName ( node , XMLSTRING ( name ) ) ;
2012-01-06 12:22:30 +00:00
}
2009-02-09 16:16:11 +00:00
}
- ( void ) setStringValue : ( NSString * ) string
{
[ self setStringValue : string resolvingEntities : NO ] ;
}
- ( void ) setURI : ( NSString * ) URI
{
2012-01-06 12:22:30 +00:00
if ( NSXMLInvalidKind ! = internal -> kind )
{
ASSIGNCOPY ( internal -> URI , URI ) ;
}
2009-02-09 16:16:11 +00:00
}
- ( void ) setStringValue : ( NSString * ) string resolvingEntities : ( BOOL ) resolve
{
2012-02-20 03:40:15 +00:00
xmlNodePtr node = MY_NODE ;
2012-01-04 12:41:45 +00:00
if ( resolve = = NO )
2012-01-03 17:15:29 +00:00
{
2012-02-20 03:40:15 +00:00
xmlNodeSetContent ( node , XMLSTRING ( string ) ) ;
2012-01-03 17:15:29 +00:00
}
else
{
2012-01-04 12:41:45 +00:00
// need to actually resolve entities . . .
2012-02-20 03:40:15 +00:00
xmlChar * newstr = xmlEncodeSpecialChars ( node -> doc , XMLSTRING ( string ) ) ; // is this the right functionality ? ?
xmlNodeSetContent ( node , newstr ) ;
xmlMemFree ( newstr ) ;
2012-01-06 12:22:30 +00:00
}
2012-02-20 03:40:15 +00:00
if ( nil = = string )
2012-01-06 12:22:30 +00:00
{
2012-02-20 03:40:15 +00:00
xmlNodeSetContent ( node , XMLSTRING ( @ "" ) ) ; // string value may not be nil
2012-01-03 17:15:29 +00:00
}
2009-02-09 16:16:11 +00:00
}
- ( NSString * ) XPath
{
2012-02-20 03:40:15 +00:00
xmlNodePtr node = MY_NODE ;
return StringFromXMLStringPtr ( xmlGetNodePath ( node ) ) ;
2009-02-09 16:16:11 +00:00
}
2012-02-20 03:40:15 +00:00
- ( NSArray * ) nodesForXPath : ( NSString * ) anxpath error : ( NSError * * ) error
2009-02-09 16:16:11 +00:00
{
2012-02-20 03:40:15 +00:00
if ( error ! = NULL )
{
* error = NULL ;
}
return execute_xpath ( self , anxpath , NULL ) ;
2009-02-09 16:16:11 +00:00
}
- ( NSArray * ) objectsForXQuery : ( NSString * ) xquery
constants : ( NSDictionary * ) constants
error : ( NSError * * ) error
{
return [ self notImplemented : _cmd ] ;
}
- ( NSArray * ) objectsForXQuery : ( NSString * ) xquery error : ( NSError * * ) error
{
return [ self notImplemented : _cmd ] ;
}
@ end
2012-02-20 03:40:15 +00:00
# endif