mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-22 16:33:29 +00:00
* Source/NSXMLDocument.m: Correct memory management.
* Source/NSXMLElement.m, * Source/NSXMLNode.m: Add partial support for namespaces. Try to bracket more libxml2 functions with version checks. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@34967 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
8f42e7c2f8
commit
fa5df31b06
4 changed files with 383 additions and 100 deletions
|
@ -1,3 +1,10 @@
|
|||
2012-03-21 Fred Kiefer <FredKiefer@gmx.de>
|
||||
|
||||
* Source/NSXMLDocument.m: Correct memory management.
|
||||
* Source/NSXMLElement.m,
|
||||
* Source/NSXMLNode.m: Add partial support for namespaces.
|
||||
Try to bracket more libxml2 functions with version checks.
|
||||
|
||||
2012-03-21 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSXMLDocument.m:
|
||||
|
|
|
@ -220,6 +220,10 @@ GS_PRIVATE_INTERNAL(NSXMLDocument)
|
|||
|
||||
- (void) setCharacterEncoding: (NSString*)encoding
|
||||
{
|
||||
if (internal->node->encoding != NULL)
|
||||
{
|
||||
xmlFree((xmlChar *)internal->node->encoding);
|
||||
}
|
||||
internal->node->encoding = XMLStringCopy(encoding);
|
||||
}
|
||||
|
||||
|
@ -264,6 +268,7 @@ GS_PRIVATE_INTERNAL(NSXMLDocument)
|
|||
// remove all sub nodes
|
||||
[self setChildren: nil];
|
||||
|
||||
// FIXME: Should we use addChild: here?
|
||||
xmlDocSetRootElement(internal->node, [root _node]);
|
||||
|
||||
// Do our subNode housekeeping...
|
||||
|
@ -279,8 +284,12 @@ GS_PRIVATE_INTERNAL(NSXMLDocument)
|
|||
{
|
||||
if ([version isEqualToString: @"1.0"] || [version isEqualToString: @"1.1"])
|
||||
{
|
||||
if (internal->node->version != NULL)
|
||||
{
|
||||
xmlFree((xmlChar *)internal->node->version);
|
||||
}
|
||||
internal->node->version = XMLStringCopy(version);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
|
|
|
@ -37,15 +37,23 @@ GS_PRIVATE_INTERNAL(NSXMLElement)
|
|||
|
||||
- (void) dealloc
|
||||
{
|
||||
/*
|
||||
if (GS_EXISTS_INTERNAL && _internal != nil)
|
||||
{
|
||||
while ([self childCount] > 0)
|
||||
{
|
||||
[self removeChildAtIndex: [self childCount] - 1];
|
||||
}
|
||||
/*
|
||||
NSArray *subNodes = [internal->subNodes copy];
|
||||
NSEnumerator *enumerator = [subNodes objectEnumerator];
|
||||
NSXMLNode *subNode;
|
||||
|
||||
while ((subNode = [enumerator nextObject]) != nil)
|
||||
{
|
||||
if ([subNode kind] == NSXMLNamespaceKind)
|
||||
{
|
||||
[self removeNamespaceForPrefix: [subNode name]];
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
*/
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
@ -132,33 +140,81 @@ GS_PRIVATE_INTERNAL(NSXMLElement)
|
|||
|
||||
- (NSArray*) elementsForName: (NSString*)name
|
||||
{
|
||||
NSMutableArray *results = [NSMutableArray arrayWithCapacity: 10];
|
||||
xmlNodePtr cur = NULL;
|
||||
NSString *prefix = [[self class] prefixForName: name];
|
||||
|
||||
for (cur = internal->node->children; cur != NULL; cur = cur->next)
|
||||
if (nil != prefix)
|
||||
{
|
||||
NSString *n = StringFromXMLStringPtr(cur->name);
|
||||
if ([n isEqualToString: name])
|
||||
{
|
||||
NSXMLNode *node = [NSXMLNode _objectForNode: cur];
|
||||
[results addObject: node];
|
||||
}
|
||||
NSXMLNode *ns = [self namespaceForPrefix: prefix];
|
||||
|
||||
if (nil != ns)
|
||||
{
|
||||
NSString *localName = [[self class] localNameForName: name];
|
||||
|
||||
// Namespace nodes have the URI as their stringValue
|
||||
return [self elementsForLocalName: localName URI: [ns stringValue]];
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
NSMutableArray *results = [NSMutableArray arrayWithCapacity: 10];
|
||||
xmlNodePtr cur = NULL;
|
||||
|
||||
for (cur = internal->node->children; cur != NULL; cur = cur->next)
|
||||
{
|
||||
if (cur->type == XML_ELEMENT_NODE)
|
||||
{
|
||||
NSString *n = StringFromXMLStringPtr(cur->name);
|
||||
if ([n isEqualToString: name])
|
||||
{
|
||||
NSXMLNode *node = [NSXMLNode _objectForNode: cur];
|
||||
[results addObject: node];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray*) elementsForLocalName: (NSString*)localName URI: (NSString*)URI
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
return nil;
|
||||
NSMutableArray *results = [NSMutableArray arrayWithCapacity: 10];
|
||||
xmlNodePtr cur = NULL;
|
||||
const xmlChar *href = XMLSTRING(URI);
|
||||
xmlNsPtr parentNS = xmlSearchNsByHref(internal->node->doc, internal->node, href);
|
||||
|
||||
for (cur = internal->node->children; cur != NULL; cur = cur->next)
|
||||
{
|
||||
if (cur->type == XML_ELEMENT_NODE)
|
||||
{
|
||||
xmlNsPtr childNS = parentNS;
|
||||
|
||||
if (cur->nsDef != NULL)
|
||||
{
|
||||
childNS = xmlSearchNsByHref(internal->node->doc, cur, href);
|
||||
}
|
||||
|
||||
if (cur->ns == childNS)
|
||||
{
|
||||
NSString *n = StringFromXMLStringPtr(cur->name);
|
||||
|
||||
if ([n isEqualToString: localName])
|
||||
{
|
||||
NSXMLNode *node = [NSXMLNode _objectForNode: cur];
|
||||
[results addObject: node];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
- (void) addAttribute: (NSXMLNode*)attribute
|
||||
{
|
||||
xmlNodePtr node = internal->node;
|
||||
xmlAttrPtr attr = (xmlAttrPtr)[attribute _node];
|
||||
xmlAttrPtr oldAttr = xmlHasProp(node, attr->name);
|
||||
xmlAttrPtr oldAttr;
|
||||
|
||||
if (nil != [attribute parent])
|
||||
{
|
||||
|
@ -166,6 +222,27 @@ GS_PRIVATE_INTERNAL(NSXMLElement)
|
|||
format: @"Tried to add attribute to multiple parents."];
|
||||
}
|
||||
|
||||
if (attr->ns != NULL)
|
||||
{
|
||||
xmlNsPtr ns = attr->ns;
|
||||
|
||||
if (ns->href == NULL)
|
||||
{
|
||||
xmlNsPtr newNs = xmlSearchNs(node->doc, node, ns->prefix);
|
||||
|
||||
if (newNs != NULL)
|
||||
{
|
||||
ns = newNs;
|
||||
}
|
||||
}
|
||||
|
||||
oldAttr = xmlHasNsProp(node, attr->name, ns->href);
|
||||
}
|
||||
else
|
||||
{
|
||||
oldAttr = xmlHasProp(node, attr->name);
|
||||
}
|
||||
|
||||
if (NULL != oldAttr)
|
||||
{
|
||||
/*
|
||||
|
@ -252,36 +329,65 @@ GS_PRIVATE_INTERNAL(NSXMLElement)
|
|||
|
||||
- (NSXMLNode*) attributeForName: (NSString*)name
|
||||
{
|
||||
NSXMLNode *result = nil;
|
||||
xmlNodePtr node = internal->node;
|
||||
xmlAttrPtr attributeNode = xmlHasProp(node, XMLSTRING(name));
|
||||
NSString *prefix = [[self class] prefixForName: name];
|
||||
|
||||
if (NULL != attributeNode)
|
||||
if (nil != prefix)
|
||||
{
|
||||
result = [NSXMLNode _objectForNode: (xmlNodePtr)attributeNode];
|
||||
NSXMLNode *ns = [self namespaceForPrefix: prefix];
|
||||
|
||||
if (nil != ns)
|
||||
{
|
||||
NSString *localName = [[self class] localNameForName: name];
|
||||
|
||||
// Namespace nodes have the URI as their stringValue
|
||||
return [self attributeForLocalName: localName URI: [ns stringValue]];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
{
|
||||
NSXMLNode *result = nil;
|
||||
xmlNodePtr node = internal->node;
|
||||
xmlAttrPtr attributeNode = xmlHasProp(node, XMLSTRING(name));
|
||||
|
||||
if (NULL != attributeNode)
|
||||
{
|
||||
result = [NSXMLNode _objectForNode: (xmlNodePtr)attributeNode];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSXMLNode*) attributeForLocalName: (NSString*)localName
|
||||
URI: (NSString*)URI
|
||||
{
|
||||
[self notImplemented: _cmd];
|
||||
return nil;
|
||||
NSXMLNode *result = nil;
|
||||
xmlNodePtr node = internal->node;
|
||||
xmlAttrPtr attributeNode = xmlHasNsProp(node, XMLSTRING(localName),
|
||||
XMLSTRING(URI));
|
||||
|
||||
if (NULL != attributeNode)
|
||||
{
|
||||
result = [NSXMLNode _objectForNode: (xmlNodePtr)attributeNode];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (void) addNamespace: (NSXMLNode*)aNamespace
|
||||
{
|
||||
xmlNsPtr ns = (xmlNsPtr)[aNamespace _node];
|
||||
xmlNodePtr node = internal->node;
|
||||
|
||||
if (internal->node->nsDef == NULL)
|
||||
if (node->nsDef == NULL)
|
||||
{
|
||||
internal->node->nsDef = ns;
|
||||
node->nsDef = ns;
|
||||
[self _addSubNode: aNamespace];
|
||||
}
|
||||
else
|
||||
{
|
||||
xmlNsPtr cur = internal->node->nsDef;
|
||||
xmlNsPtr cur = node->nsDef;
|
||||
xmlNsPtr last = NULL;
|
||||
const xmlChar *prefix = ns->prefix;
|
||||
|
||||
while (xmlStrcmp(prefix, cur->prefix) != 0)
|
||||
|
@ -289,19 +395,43 @@ GS_PRIVATE_INTERNAL(NSXMLElement)
|
|||
if (cur->next == NULL)
|
||||
{
|
||||
cur->next = ns;
|
||||
[self _addSubNode: aNamespace];
|
||||
return;
|
||||
}
|
||||
last = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
// Found the same prefix
|
||||
if (cur->href == NULL)
|
||||
{
|
||||
// This was a fake namespace we added
|
||||
if (node->ns == cur)
|
||||
{
|
||||
node->ns = ns;
|
||||
}
|
||||
if (last == NULL)
|
||||
{
|
||||
node->nsDef = ns;
|
||||
}
|
||||
else
|
||||
{
|
||||
last->next = ns;
|
||||
}
|
||||
ns->next = cur->next;
|
||||
cur->next = NULL;
|
||||
}
|
||||
}
|
||||
[self _addSubNode: aNamespace];
|
||||
// FIXME: Need to replace fake namespaces in subnodes
|
||||
}
|
||||
|
||||
- (void) removeNamespaceForPrefix: (NSString*)name
|
||||
{
|
||||
if (internal->node->nsDef != NULL)
|
||||
xmlNodePtr node = internal->node;
|
||||
|
||||
if (node->nsDef != NULL)
|
||||
{
|
||||
xmlNsPtr cur = internal->node->nsDef;
|
||||
xmlNsPtr cur = node->nsDef;
|
||||
xmlNsPtr last = NULL;
|
||||
const xmlChar *prefix = XMLSTRING(name);
|
||||
|
||||
|
@ -318,6 +448,10 @@ GS_PRIVATE_INTERNAL(NSXMLElement)
|
|||
last->next = cur->next;
|
||||
}
|
||||
cur->next = NULL;
|
||||
if (node->ns == cur)
|
||||
{
|
||||
node->ns = NULL;
|
||||
}
|
||||
if (cur->_private != NULL)
|
||||
{
|
||||
[self _removeSubNode: (NSXMLNode *)cur->_private];
|
||||
|
@ -350,13 +484,14 @@ GS_PRIVATE_INTERNAL(NSXMLElement)
|
|||
|
||||
- (NSArray*) namespaces
|
||||
{
|
||||
// FIXME: Should use xmlGetNsList()
|
||||
// FIXME: Should we use xmlGetNsList()?
|
||||
NSMutableArray *result = nil;
|
||||
xmlNsPtr ns = internal->node->nsDef;
|
||||
|
||||
if (ns)
|
||||
{
|
||||
xmlNsPtr cur = NULL;
|
||||
|
||||
result = [NSMutableArray array];
|
||||
for (cur = ns; cur != NULL; cur = cur->next)
|
||||
{
|
||||
|
@ -369,20 +504,13 @@ GS_PRIVATE_INTERNAL(NSXMLElement)
|
|||
|
||||
- (NSXMLNode*) namespaceForPrefix: (NSString*)name
|
||||
{
|
||||
// FIXME: Should use xmlSearchNs()
|
||||
xmlNsPtr ns = internal->node->nsDef;
|
||||
const xmlChar *prefix = XMLSTRING(name);
|
||||
xmlNodePtr node = internal->node;
|
||||
xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
|
||||
|
||||
if (ns)
|
||||
{
|
||||
const xmlChar *prefix = XMLSTRING(name);
|
||||
xmlNsPtr cur = NULL;
|
||||
for (cur = ns; cur != NULL; cur = cur->next)
|
||||
{
|
||||
if (xmlStrcmp(prefix, cur->prefix) == 0)
|
||||
{
|
||||
return [NSXMLNode _objectForNode: (xmlNodePtr)cur];
|
||||
}
|
||||
}
|
||||
return [NSXMLNode _objectForNode: (xmlNodePtr)ns];
|
||||
}
|
||||
|
||||
return nil;
|
||||
|
@ -402,21 +530,12 @@ GS_PRIVATE_INTERNAL(NSXMLElement)
|
|||
|
||||
- (NSString*) resolvePrefixForNamespaceURI: (NSString*)namespaceURI
|
||||
{
|
||||
// FIXME Should use xmlSearchNsByHref()
|
||||
xmlNsPtr ns = internal->node->nsDef;
|
||||
const xmlChar *uri = XMLSTRING(namespaceURI);
|
||||
xmlNsPtr ns = xmlSearchNsByHref(internal->node->doc, internal->node, uri);
|
||||
|
||||
if (ns)
|
||||
{
|
||||
const xmlChar *uri = XMLSTRING(namespaceURI);
|
||||
xmlNsPtr cur;
|
||||
|
||||
for (cur = ns; cur != NULL; cur = cur->next)
|
||||
{
|
||||
if (xmlStrcmp(uri, cur->href) == 0)
|
||||
{
|
||||
return StringFromXMLStringPtr(cur->prefix);
|
||||
}
|
||||
}
|
||||
return StringFromXMLStringPtr(ns->prefix);
|
||||
}
|
||||
|
||||
return nil;
|
||||
|
|
|
@ -451,7 +451,28 @@ isEqualTree(xmlNodePtr nodeA, xmlNodePtr nodeB)
|
|||
xmlNodePtr curNode = [self _childNodeAtIndex: index];
|
||||
BOOL mergeTextNodes = NO; // is there a defined option for this?
|
||||
|
||||
if (mergeTextNodes || childNode->type == XML_ATTRIBUTE_NODE)
|
||||
if (childNode->type == XML_NAMESPACE_DECL)
|
||||
{
|
||||
// FIXME
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if LIBXML_VERSION >= 20620
|
||||
xmlDocPtr tmp = childNode->doc;
|
||||
|
||||
if (tmp)
|
||||
{
|
||||
xmlDOMWrapAdoptNode(NULL, childNode->doc, childNode,
|
||||
parentNode->doc, parentNode, 0);
|
||||
xmlFreeDoc(tmp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (mergeTextNodes ||
|
||||
((childNode->type != XML_TEXT_NODE) &&
|
||||
(parentNode->type != XML_TEXT_NODE)))
|
||||
{
|
||||
// this uses the built-in libxml functions which merge adjacent text nodes
|
||||
xmlNodePtr addedNode = NULL;
|
||||
|
@ -466,33 +487,23 @@ isEqualTree(xmlNodePtr nodeA, xmlNodePtr nodeB)
|
|||
}
|
||||
if (addedNode != childNode)
|
||||
{
|
||||
[child _setNode: NULL];
|
||||
child = [NSXMLNode _objectForNode: addedNode];
|
||||
if (addedNode != NULL)
|
||||
{
|
||||
// The node was freed while merging
|
||||
[child _invalidate];
|
||||
}
|
||||
// Don't add as subnode
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (childNode->type == XML_NAMESPACE_DECL)
|
||||
{
|
||||
// FIXME
|
||||
}
|
||||
else
|
||||
{
|
||||
/* here we avoid merging adjacent text nodes by linking
|
||||
* the new node in "by hand"
|
||||
*/
|
||||
xmlDocPtr tmp = childNode->doc;
|
||||
|
||||
if (tmp)
|
||||
{
|
||||
xmlDOMWrapAdoptNode(NULL, childNode->doc, childNode,
|
||||
parentNode->doc, parentNode, 0);
|
||||
xmlFreeDoc(tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
xmlSetTreeDoc(childNode, parentNode->doc);
|
||||
}
|
||||
|
||||
childNode->parent = parentNode;
|
||||
xmlSetTreeDoc(childNode, parentNode->doc);
|
||||
|
||||
if (curNode)
|
||||
{
|
||||
// insert childNode before an existing node curNode
|
||||
|
@ -532,6 +543,7 @@ isEqualTree(xmlNodePtr nodeA, xmlNodePtr nodeB)
|
|||
}
|
||||
|
||||
[self _addSubNode: child];
|
||||
// FIXME: Need to replace fake namespaces in subnodes
|
||||
}
|
||||
|
||||
- (void) _invalidate
|
||||
|
@ -833,12 +845,20 @@ execute_xpath(NSXMLNode *xmlNode, NSString *xpath_exp, NSString *nmspaces)
|
|||
const xmlChar *xmlName = XMLSTRING(name);
|
||||
xmlChar *prefix = NULL;
|
||||
xmlChar *localName;
|
||||
NSString *result = name;
|
||||
|
||||
if (NULL == xmlName)
|
||||
return nil;
|
||||
|
||||
localName = xmlSplitQName2(xmlName, &prefix);
|
||||
return StringFromXMLStringPtr(localName);
|
||||
if (NULL != localName)
|
||||
{
|
||||
result = StringFromXMLStringPtr(localName);
|
||||
xmlFree(localName);
|
||||
xmlFree(prefix);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
+ (id) namespaceWithName: (NSString*)name
|
||||
|
@ -887,21 +907,22 @@ execute_xpath(NSXMLNode *xmlNode, NSString *xpath_exp, NSString *nmspaces)
|
|||
+ (NSString*) prefixForName: (NSString*)name
|
||||
{
|
||||
const xmlChar *xmlName = XMLSTRING(name);
|
||||
xmlChar *localName;
|
||||
xmlChar *prefix = NULL;
|
||||
NSString *result = @"";
|
||||
|
||||
if (NULL == xmlName)
|
||||
return nil;
|
||||
|
||||
xmlSplitQName2(xmlName, &prefix);
|
||||
localName = xmlSplitQName2(xmlName, &prefix);
|
||||
if (NULL != prefix)
|
||||
{
|
||||
result = StringFromXMLStringPtr(prefix);
|
||||
xmlFree(localName);
|
||||
xmlFree(prefix);
|
||||
}
|
||||
|
||||
if (NULL == prefix)
|
||||
{
|
||||
return @"";
|
||||
}
|
||||
else
|
||||
{
|
||||
return StringFromXMLStringPtr(prefix);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+ (id) processingInstructionWithName: (NSString*)name
|
||||
|
@ -1049,7 +1070,10 @@ execute_xpath(NSXMLNode *xmlNode, NSString *xpath_exp, NSString *nmspaces)
|
|||
if (node->type == XML_NAMESPACE_DECL)
|
||||
{
|
||||
((xmlNsPtr)node)->_private = NULL;
|
||||
xmlFreeNode(node);
|
||||
// FIXME: Not sure when to free the node here,
|
||||
// the same namespace node might be referenced
|
||||
// from other places.
|
||||
//xmlFreeNode(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1099,6 +1123,7 @@ execute_xpath(NSXMLNode *xmlNode, NSString *xpath_exp, NSString *nmspaces)
|
|||
}
|
||||
else
|
||||
{
|
||||
#if LIBXML_VERSION >= 20620
|
||||
if (node->doc)
|
||||
{
|
||||
/* Create a private document and move the node over.
|
||||
|
@ -1112,6 +1137,7 @@ execute_xpath(NSXMLNode *xmlNode, NSString *xpath_exp, NSString *nmspaces)
|
|||
xmlDOMWrapAdoptNode(NULL, node->doc, node, tmp, NULL, 0);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// separate our node from its parent and siblings
|
||||
xmlUnlinkNode(node);
|
||||
|
@ -1253,12 +1279,22 @@ execute_xpath(NSXMLNode *xmlNode, NSString *xpath_exp, NSString *nmspaces)
|
|||
}
|
||||
|
||||
case NSXMLEntityDeclarationKind:
|
||||
// FIXME ... xmlNewEntity doesn't exist in common version of libxml2
|
||||
/*
|
||||
#if LIBXML_VERSION >= 20700
|
||||
node = xmlNewEntity(NULL, (xmlChar *)"", 0, (xmlChar *)"",
|
||||
(xmlChar *)"", (xmlChar *)"");
|
||||
*/
|
||||
node = xmlNewNode(NULL, (xmlChar *)"");
|
||||
#else
|
||||
{
|
||||
xmlEntityPtr ret;
|
||||
ret = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
|
||||
memset(ret, 0, sizeof(xmlEntity));
|
||||
ret->type = XML_ENTITY_DECL;
|
||||
ret->name = xmlStrdup((xmlChar *)"");
|
||||
ret->ExternalID = xmlStrdup((xmlChar *)"");
|
||||
ret->SystemID = xmlStrdup((xmlChar *)"");
|
||||
ret->content = xmlStrdup((xmlChar *)"");
|
||||
node = ret;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case NSXMLNotationDeclarationKind:
|
||||
|
@ -1333,11 +1369,6 @@ execute_xpath(NSXMLNode *xmlNode, NSString *xpath_exp, NSString *nmspaces)
|
|||
}
|
||||
|
||||
- (NSString*) localName
|
||||
{
|
||||
return [[self class] localNameForName: [self name]];
|
||||
}
|
||||
|
||||
- (NSString*) name
|
||||
{
|
||||
xmlNodePtr node = internal->node;
|
||||
|
||||
|
@ -1356,6 +1387,23 @@ execute_xpath(NSXMLNode *xmlNode, NSString *xpath_exp, NSString *nmspaces)
|
|||
}
|
||||
}
|
||||
|
||||
- (NSString*) name
|
||||
{
|
||||
NSString *localName = [self localName];
|
||||
|
||||
if (nil != localName)
|
||||
{
|
||||
NSString *prefix = [self prefix];
|
||||
|
||||
if ((nil != prefix) && [prefix length] > 0)
|
||||
{
|
||||
return [NSString stringWithFormat: @"%@:%@", prefix, localName];
|
||||
}
|
||||
}
|
||||
|
||||
return localName;
|
||||
}
|
||||
|
||||
- (NSXMLNode*) _nodeFollowingInNaturalDirection: (BOOL)forward
|
||||
{
|
||||
NSXMLNode *ancestor = self;
|
||||
|
@ -1440,7 +1488,26 @@ execute_xpath(NSXMLNode *xmlNode, NSString *xpath_exp, NSString *nmspaces)
|
|||
|
||||
- (NSString*) prefix
|
||||
{
|
||||
return [[self class] prefixForName: [self name]];
|
||||
xmlNodePtr node = internal->node;
|
||||
|
||||
if (NULL == node)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
if (XML_NAMESPACE_DECL == node->type)
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
if (XML_ELEMENT_NODE != node->type)
|
||||
{
|
||||
return @"";
|
||||
}
|
||||
if (node->ns == NULL)
|
||||
{
|
||||
return @"";
|
||||
}
|
||||
|
||||
return StringFromXMLStringPtr(node->ns->prefix);
|
||||
}
|
||||
|
||||
- (NSXMLNode*) previousNode
|
||||
|
@ -1510,7 +1577,76 @@ execute_xpath(NSXMLNode *xmlNode, NSString *xpath_exp, NSString *nmspaces)
|
|||
}
|
||||
else
|
||||
{
|
||||
xmlNodeSetName(node, XMLSTRING(name));
|
||||
const xmlChar *xmlName = XMLSTRING(name);
|
||||
xmlChar *prefix = NULL;
|
||||
xmlChar *localName;
|
||||
|
||||
if (NULL == xmlName)
|
||||
{
|
||||
xmlNodeSetName(node, (const xmlChar *)"");
|
||||
return;
|
||||
}
|
||||
|
||||
localName = xmlSplitQName2(xmlName, &prefix);
|
||||
if (localName != NULL)
|
||||
{
|
||||
// FIXME: Which other nodes get namespaces?
|
||||
if ((node->type == XML_ATTRIBUTE_NODE) ||
|
||||
(node->type == XML_ELEMENT_NODE))
|
||||
{
|
||||
xmlNsPtr ns;
|
||||
|
||||
// Set namespace
|
||||
if (node->doc == NULL)
|
||||
{
|
||||
#if LIBXML_VERSION >= 20620
|
||||
// Create a private document for this node
|
||||
xmlDocPtr tmp = xmlNewDoc((xmlChar *)"1.0");
|
||||
|
||||
xmlDOMWrapAdoptNode(NULL, NULL, node, tmp, NULL, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
ns = xmlSearchNs(node->doc, node, prefix);
|
||||
if (ns)
|
||||
{
|
||||
xmlSetNs(node, ns);
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME: Fake the name space and fix it later
|
||||
// xmlReconciliateNs or xmlDOMWrapReconcileNamespaces ?
|
||||
// This function is private, so re reimplemt it.
|
||||
//ns = xmlDOMWrapStoreNs(node->doc, NULL, prefix);
|
||||
xmlNsPtr oldNs = node->doc->oldNs;
|
||||
|
||||
while (oldNs)
|
||||
{
|
||||
if (xmlStrEqual(oldNs->prefix, prefix))
|
||||
{
|
||||
ns = oldNs;
|
||||
break;
|
||||
}
|
||||
if (oldNs->next == NULL)
|
||||
{
|
||||
ns = xmlNewNs(NULL, NULL, prefix);
|
||||
oldNs->next = ns;
|
||||
break;
|
||||
}
|
||||
oldNs = oldNs->next;
|
||||
}
|
||||
xmlSetNs(node, ns);
|
||||
}
|
||||
}
|
||||
|
||||
xmlNodeSetName(node, localName);
|
||||
xmlFree(localName);
|
||||
xmlFree(prefix);
|
||||
}
|
||||
else
|
||||
{
|
||||
xmlNodeSetName(node, xmlName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1610,9 +1746,21 @@ execute_xpath(NSXMLNode *xmlNode, NSString *xpath_exp, NSString *nmspaces)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if LIBXML_VERSION >= 20623
|
||||
ctxt = xmlSaveToBuffer(buffer, "utf-8", xmlOptions);
|
||||
xmlSaveTree(ctxt, internal->node);
|
||||
error = xmlSaveClose(ctxt);
|
||||
#else
|
||||
{
|
||||
xmlDocPtr doc = NULL;
|
||||
|
||||
if (internal->node->type != XML_NAMESPACE_DECL)
|
||||
{
|
||||
doc = internal->node->doc;
|
||||
}
|
||||
error = xmlNodeDump(buffer, doc, internal->node, 1, 1);
|
||||
}
|
||||
#endif
|
||||
if (-1 == error)
|
||||
{
|
||||
xmlBufferFree(buffer);
|
||||
|
|
Loading…
Reference in a new issue