NSXMLDocument objectByApplyingXSLTAtURL return value

Discussion in 'Mac Programming' started by wlh99, Nov 20, 2010.

  1. macrumors 6502

    Joined:
    Feb 7, 2008
    Messages:
    272
    #1
    From the API reference:
    Code:
    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
    
    ...
    Code:
    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.

    Code:
    // 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.

    Code:
    // 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;
    	}
    	
    
     
  2. macrumors 68000

    Sydde

    Joined:
    Aug 17, 2009
    Messages:
    1,896
    #2
    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.
     
  3. macrumors 603

    Joined:
    Aug 9, 2009
    Messages:
    6,404
    #3
    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.
     
  4. macrumors 6502

    Joined:
    Feb 7, 2008
    Messages:
    272
    #4
    Thank you. That is ultimately what I did. I'd still like to know what determines the outcome however.
     
  5. macrumors 6502

    Joined:
    Feb 7, 2008
    Messages:
    272
    #5
    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.
    Code:
    <?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>
    
    
     

Share This Page