Use xmlSave for XML String creation.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@34929 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Fred Kiefer 2012-03-14 21:12:19 +00:00
parent 043b774291
commit 3318835025
4 changed files with 49 additions and 38 deletions

View file

@ -1,4 +1,11 @@
2012-03-14 Richard Frith-Macdonald & Fred Kiefer
2012-03-12 Fred Kiefer <FredKiefer@gmx.de>
* Source/NSXMLPrivate.h: Add comments on owner policy.
* Source/NSXMLNode.m (-XMLStringWithOptions:): Reimplement to
allow closer control over output.
* Source/NSXMLDocument.m (-XMLStringWithOptions:): Remove this method.
2012-03-14 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSXMLPrivate.h:
* Source/NSXMLNode.m:

View file

@ -365,23 +365,6 @@ GS_PRIVATE_INTERNAL(NSXMLDocument)
return data;
}
- (NSString *) XMLStringWithOptions: (NSUInteger)options
{
NSString *string = nil;
xmlChar *buf = NULL;
int length;
xmlDocDumpFormatMemoryEnc(internal->node, &buf, &length, "utf-8",
((options & NSXMLNodePrettyPrint) ? 1 : 0));
if (buf != 0 && length > 0)
{
string = StringFromXMLString(buf, length);
free(buf);
}
return string;
}
- (id) objectByApplyingXSLT: (NSData*)xslt
arguments: (NSDictionary*)arguments
error: (NSError**)error

View file

@ -904,7 +904,7 @@ execute_xpath(NSXMLNode *xmlNode, NSString *xpath_exp, NSString *nmspaces)
- (NSString*) canonicalXMLStringPreservingComments: (BOOL)comments
{
// FIXME ... generate from libxml
return [self notImplemented: _cmd];
return [self XMLStringWithOptions: NSXMLNodePreserveWhitespace];
}
- (NSXMLNode*) childAtIndex: (NSUInteger)index
@ -1016,6 +1016,7 @@ execute_xpath(NSXMLNode *xmlNode, NSString *xpath_exp, NSString *nmspaces)
}
[subNodes release];
[internal->URI release];
[internal->objectValue release];
[internal->subNodes release];
if (node)
@ -1504,20 +1505,32 @@ execute_xpath(NSXMLNode *xmlNode, NSString *xpath_exp, NSString *nmspaces)
{
NSString *string = nil;
xmlChar *buf = NULL;
xmlDocPtr doc;
xmlBufferPtr buffer;
int error = 0;
int len = 0;
xmlSaveCtxtPtr ctxt;
int xmlOptions = 0;
if (internal->node->type == XML_NAMESPACE_DECL)
{
xmlNsPtr ns = (xmlNsPtr)internal->node;
return StringFromXMLStringPtr(ns->href);
}
buffer = xmlBufferCreate();
doc = internal->node->doc;
error = xmlNodeDump(buffer, doc, internal->node, 1, 1);
// XML_SAVE_XHTML XML_SAVE_AS_HTML XML_SAVE_NO_DECL XML_SAVE_NO_XHTML
xmlOptions |= XML_SAVE_AS_XML;
if (options & NSXMLNodePreserveWhitespace)
{
xmlOptions |= XML_SAVE_WSNONSIG;
}
if (options & NSXMLNodeCompactEmptyElement)
{
xmlOptions |= XML_SAVE_NO_EMPTY;
}
if (options & NSXMLNodePrettyPrint)
{
xmlOptions |= XML_SAVE_FORMAT;
}
ctxt = xmlSaveToBuffer(buffer, "utf-8", xmlOptions);
xmlSaveTree(ctxt, internal->node);
error = xmlSaveClose(ctxt);
if (-1 == error)
{
xmlBufferFree(buffer);

View file

@ -86,25 +86,32 @@ StringFromXMLString(const unsigned char *bytes, unsigned length)
*
* The 'kind' tells us what sort of node this is.
* The 'node' points to the underlying libxml2 node structure.
* The 'nsParent' points to the parent node of a namspace structure, needed
* because older (but still used on at least one major linux distribution)
* versions of libxml2 don't have a link to the parent of a namespace.
* The 'options' field is a bitmask of options for this node.
* The 'objectValue' is the object value set for the node.
* The 'subNodes' array is used to retain the objects pointed to by subnodes.
*
* The 'subNodes' array is confusing ... what *is* the ownership policy for
* NSXMLNode with respect to the libxml2 tree? The simple/obvious one would
* be that each NSXMLNode owns any NSXMLNode pointed to by children of the
* corresponding libxml2 structure ... in which case there would be no need
* for this array because the references to the owned NSXMLNode instances
* would be the'_private' fields of the libxml2 structures.
* When we create an Objective-C object for a node we also create objects
* for all parents up to the root object. (Reusing existing once as we find
* them in the _private points of parent nodes)
* This adds the object to the subnode array of the parent object, retaining
* the object in this process.
* This means a document object will retain all the objects we have created
* for its node tree, but we don't have to create all these objects at once.
* When we remove an object from its parent we always call the detach method.
* Here we unlink the libxml2 node and remove the object from its parent's
* subnode array, This will release the object.
* When an object gets deallocated it detaches all the subnodes, releasing
* them in the process and then it frees the node. That way each object takes
* care of freeing its own node, but nodes that don't have objects attached
* to them will get freed when their parent object (e.g. the NSXMLDocument)
* gets deallocated.
* For namespace nodes special rules apply as they don't have a parent pointer.
*
* URI is probably not needed at all ... I'm not sure
*/
#define GS_NSXMLNode_IVARS \
NSUInteger kind; \
GS_XMLNODETYPE *node; \
xmlNodePtr nsParent; \
NSUInteger options; \
id objectValue; \
NSString *URI; \
@ -193,6 +200,7 @@ StringFromXMLString(const unsigned char *bytes, unsigned length)
#include <libxml/parserInternals.h>
#include <libxml/HTMLparser.h>
#include <libxml/xmlmemory.h>
#include <libxml/xmlsave.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>