diff --git a/GDataXML-HTML/lib/GDataXMLNode.h b/GDataXML-HTML/lib/GDataXMLNode.h
index e757630..4ea554d 100644
--- a/GDataXML-HTML/lib/GDataXMLNode.h
+++ b/GDataXML-HTML/lib/GDataXMLNode.h
@@ -139,6 +139,10 @@ typedef NSUInteger GDataXMLNodeKind;
- (NSArray *)children;
- (GDataXMLNode *)childAtIndex:(unsigned)index;
+- (GDataXMLNode *)parent;
+
+- (NSUInteger)index;
+
- (NSString *)localName;
- (NSString *)name;
- (NSString *)prefix;
@@ -185,6 +189,7 @@ typedef NSUInteger GDataXMLNodeKind;
// addChild adds a copy of the child node to the element
- (void)addChild:(GDataXMLNode *)child;
- (void)removeChild:(GDataXMLNode *)child;
+- (void)removeChildAtIndex:(NSUInteger)index;
- (NSArray *)elementsForName:(NSString *)name;
- (NSArray *)elementsForLocalName:(NSString *)localName URI:(NSString *)URI;
@@ -193,6 +198,7 @@ typedef NSUInteger GDataXMLNodeKind;
- (GDataXMLNode *)attributeForName:(NSString *)name;
- (GDataXMLNode *)attributeForLocalName:(NSString *)name URI:(NSString *)attributeURI;
- (void)addAttribute:(GDataXMLNode *)attribute;
+- (void)removeAttributeForName:(NSString *)name;
- (NSString *)resolvePrefixForNamespaceURI:(NSString *)namespaceURI;
diff --git a/GDataXML-HTML/lib/GDataXMLNode.m b/GDataXML-HTML/lib/GDataXMLNode.m
index 737a8da..3939f7c 100644
--- a/GDataXML-HTML/lib/GDataXMLNode.m
+++ b/GDataXML-HTML/lib/GDataXMLNode.m
@@ -375,6 +375,68 @@ - (NSString *)stringFromXMLString:(const xmlChar *)chars {
return result;
}
+/**
+ * Removes and free's the given attribute from its parent node.
+ * The attribute's surrounding prev/next pointers are properly updated to remove the attribute from the attr list.
+ **/
++ (void)removeAttribute:(xmlAttrPtr)attr
+{
+ // We perform a bit of optimization here.
+ // No need to bother nullifying pointers since we're about to free the node anyway.
+ [self detachAttribute:attr andClean:NO];
+
+ xmlFreeProp(attr);
+}
+
+/**
+ * Detaches the given attribute from its parent node.
+ * The attribute's surrounding prev/next pointers are properly updated to remove the attribute from the attr list.
+ * Then, if the clean flag is YES, the attribute's parent, prev, next and doc pointers are set to null.
+ **/
++ (void)detachAttribute:(xmlAttrPtr)attr andClean:(BOOL)clean
+{
+ xmlNodePtr parent = attr->parent;
+
+ // Update the surrounding prev/next pointers
+ if (attr->prev == NULL)
+ {
+ parent->properties = attr->next;
+ if (attr->next != NULL) {
+ attr->next->prev = NULL;
+ }
+ }
+ else
+ {
+ attr->prev->next = attr->next;
+ if (attr->next != NULL) {
+ attr->next->prev = attr->prev;
+ }
+ }
+
+ if (clean)
+ {
+ // Nullify pointers
+ attr->parent = NULL;
+ attr->prev = NULL;
+ attr->next = NULL;
+ attr->ns = NULL;
+ if (attr->doc != NULL) [self stripDocPointersFromAttr:attr];
+ }
+}
+
++ (void)stripDocPointersFromAttr:(xmlAttrPtr)attr
+{
+ xmlNodePtr child = attr->children;
+ while (child != NULL)
+ {
+ child->doc = NULL;
+ child = child->next;
+ }
+
+ attr->doc = NULL;
+}
+
+
- (void)dealloc {
if (xmlNode_ && shouldFreeXMLNode_) {
@@ -652,6 +714,27 @@ - (GDataXMLNode *)childAtIndex:(unsigned)index {
return nil;
}
+- (GDataXMLNode *)parent {
+ xmlNodePtr node = xmlNode_;
+
+ if (node->parent == NULL)
+ return nil;
+ else
+ return [GDataXMLNode nodeBorrowingXMLNode:node->parent];
+}
+
+- (NSUInteger)index {
+ NSUInteger result = 0;
+ xmlNodePtr node = xmlNode_->prev;
+ while (node != NULL)
+ {
+ result++;
+ node = node->prev;
+ }
+
+ return result;
+}
+
- (GDataXMLNodeKind)kind {
if (xmlNode_ != NULL) {
xmlElementType nodeType = xmlNode_->type;
@@ -1115,6 +1198,11 @@ - (void)removeChild:(GDataXMLNode *)child {
}
}
+- (void)removeChildAtIndex:(NSUInteger)index
+{
+ [self removeChild:[self childAtIndex:index]];
+}
+
- (NSArray *)elementsForName:(NSString *)name {
NSString *desiredName = name;
@@ -1326,6 +1414,26 @@ - (void)addAttribute:(GDataXMLNode *)attribute {
}
}
+- (void)removeAttributeForName:(NSString *)name {
+ // This is a private/internal method
+
+ xmlAttrPtr attr = (xmlNode_)->properties;
+ if (attr)
+ {
+ const xmlChar *xmlName = (const xmlChar *)[name UTF8String];;
+ do
+ {
+ if (xmlStrEqual(attr->name, xmlName))
+ {
+ [GDataXMLNode removeAttribute:attr];
+ return;
+ }
+ attr = attr->next;
+
+ } while(attr);
+ }
+}
+
- (GDataXMLNode *)attributeForXMLNode:(xmlAttrPtr)theXMLNode {
// search the cached attributes list for the GDataXMLNode with
// the underlying xmlAttrPtr
@@ -1981,4 +2089,3 @@ static CFHashCode StringCacheKeyHashCallBack(const void *str) {
}
return hash;
}
-