PDA

View Full Version : NSXMLDocument objectByApplyingXSLTAtURL return value




wlh99
Nov 20, 2010, 01:36 PM
From the API reference:
objectByApplyingXSLTAtURL:arguments:error:
Applies the XSLT pattern rules and templates located at a specified URL to the receiver and returns a document object containing transformed XML markup or an NSData object containing plain text, RTF text, and so on.

- (id)objectByApplyingXSLTAtURL:(NSURL *)xsltURL arguments:(NSDictionary *)arguments error:(NSError **)error

...
Return Value
Depending on intended output, the returns an NSXMLDocument object or an NSData data containing transformed XML or HTML markup. If the message is supposed to create plain text or RTF, then an NSData object is returned, otherwise an XML document object. The method returns nil if XSLT processing did not succeed.


How do I know or control if the return type is NSXMLDocument or NSData? I used this code from the NSXML_Concepts document, only changing the xsltPath to point to my XSLT code, but I was returned an NSData object. I don't have a problem with that, but I'm curious why.


// find XSLT code
NSString *xsltPath = [[NSBundle mainBundle]
pathForResource:@"addresses_transform" ofType:@"xml"];
if (!xsltPath)
return;

// transform through XSLT
NSXMLDocument *printDoc = (NSXMLDocument *)[xmlDoc
objectByApplyingXSLTAtURL:[NSURL fileURLWithPath:xsltPath]
arguments:nil error:&err];




Here is my code. It works fine, and newXMLDoc is NSData. That's fine because I want to write it to a file, but I expected another step to get an NSData from the NSXMLDocument first.


// Create NSURL with arg 3
NSURL *xsltUrl = [NSURL fileURLWithPath:[args objectAtIndex:3]];
if (!xsltUrl)
{
NSLog(@"Can't create an URL from XSLT file %@.", [args objectAtIndex:3]);
return 1;
}
// Apply xslt to NSXML Document
newXMLDoc = [xmlDoc objectByApplyingXSLTAtURL:xsltUrl arguments:nil error:&err];
[newXMLDoc retain];
if (newXMLDoc == nil) {
if (err) {
NSLog(@"UNABLE TO OPEN XSLT FILE: %@",[args objectAtIndex:3]);
}
return 1;
}



Sydde
Nov 21, 2010, 11:15 AM
Obviously you realise that you cannot expect a specific result type just by coercing the method's return type - that coercion is actually pointless because id is typeless. You should probably follow the link in the documentation that goes to xml.com, where they describe XSLT. A cursory look seems to tell me that the default transformation (such as you would get with arguments:nil) is to html, which would be text in NSData.

chown33
Nov 21, 2010, 12:07 PM
How do I know or control if the return type is NSXMLDocument or NSData?

You test the returned object's class.

One way to do this is the isKindOfClass: method. Do not use isMemberOfClass: which is similar but tests for a specific class. To understand the difference, read the docs for isKindOfClass:.

Another way to do this is to infer an object's class based on whether it responds to a specific selector or not. Use a selector that is unique to NSData or to NSXMLDocument.

Personally, I'd use the first way, or the second followed by the first.

wlh99
Nov 21, 2010, 11:40 PM
You test the returned object's class.

One way to do this is the isKindOfClass: method. Do not use isMemberOfClass: which is similar but tests for a specific class. To understand the difference, read the docs for isKindOfClass:.

Another way to do this is to infer an object's class based on whether it responds to a specific selector or not. Use a selector that is unique to NSData or to NSXMLDocument.

Personally, I'd use the first way, or the second followed by the first.

Thank you. That is ultimately what I did. I'd still like to know what determines the outcome however.

wlh99
Nov 21, 2010, 11:51 PM
Obviously you realise that you cannot expect a specific result type just by coercing the method's return type - that coercion is actually pointless because id is typeless. You should probably follow the link in the documentation that goes to xml.com, where they describe XSLT. A cursory look seems to tell me that the default transformation (such as you would get with arguments:nil) is to html, which would be text in NSData.

I do realize that. The cast to NSXMLDocument is in the apple code, not my own. Arguments as far as I can tell don't affect the type of returned object. Arguments are passed to the processor and can then by used in the XSLT stylesheet. The stylesheet I wrote myself, but it is something I am just learning so I don't know if something in it can or does affect this behavior.

That stylesheet is below, though this might not be the correct forum for that.

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:media="http://search.yahoo.com/mrss/">

<xsl:template match="/">
<xsl:text>
</xsl:text><feed><xsl:text>
</xsl:text><resultLength>3</resultLength><endIndex>3</endIndex><xsl:text>
</xsl:text>
<xsl:for-each select="rss/channel/item">
<item> <xsl:attribute name="SDImg">
<xsl:value-of select="media:thumbnail/@url"/>
</xsl:attribute>
<xsl:text>
</xsl:text>
<xsl:text> </xsl:text><title><xsl:value-of select="title"/></title><xsl:text>
</xsl:text>
<xsl:text> </xsl:text><contentId><xsl:value-of select="guid"/></contentId><xsl:text>
</xsl:text>
<xsl:text> </xsl:text><contentType>Movie</contentType><xsl:text>
</xsl:text>
<xsl:text> </xsl:text><contentQuality>SD</contentQuality><xsl:text>
</xsl:text>


<xsl:text> </xsl:text><xsl:for-each select="media:group/media:content"><xsl:text>
</xsl:text>
<xsl:text> </xsl:text><media><xsl:text>
</xsl:text>
<xsl:text> </xsl:text><streamFormat>mp4</streamFormat><xsl:text>
</xsl:text>
<xsl:text> </xsl:text><streamQuality><xsl:value-of select="@quality"/></streamQuality><xsl:text>
</xsl:text>
<xsl:text> </xsl:text><streamBitrate><xsl:value-of select="@bitrate"/></streamBitrate><xsl:text>
</xsl:text>
<xsl:text> </xsl:text><streamUrl><xsl:value-of select="@url"/></streamUrl><xsl:text>
</xsl:text>



<xsl:text> </xsl:text></media><xsl:text>
</xsl:text>
</xsl:for-each>


<xsl:text> </xsl:text><synopsis><xsl:value-of select="description"/></synopsis><xsl:text>
</xsl:text>
<xsl:text> </xsl:text><runtime><xsl:value-of select="pubDate"/></runtime><xsl:text>
</xsl:text>
<xsl:text> </xsl:text><genres></genres><xsl:text>
</xsl:text>
</item> <xsl:text>
</xsl:text><xsl:text>
</xsl:text>
</xsl:for-each>

</feed>
</xsl:template>
</xsl:stylesheet>