14

I plan to use XML/XSLT in my iPhone application.

What version of XSLT is currently supported on the iPhone? Can I use XSLT 2.0 or just 1.0 ?

tillda
  • 18,150
  • 16
  • 51
  • 70

5 Answers5

15

Using libxslt on the iPhone OS is actually quite easy:

  1. Download the source-code of libxslt and extract it.
  2. Add the "libxslt" dir to Header search paths in your build settings. Also, add the path to the libxml-headers there (usually /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk/usr/include/libxml2).
  3. Add libxml2.2.dylib and libxslt.dylib to the linked frameworks (Xcode "Groups & Files" panel: right click on "Frameworks" --> "Add" --> "Existing Frameworks...").
  4. Create a simple XML file and its XSL tranformation.

And finally you can use a code similar to the sample above to get the tranformation result into an NSString (e.g. to display in in a UIWebView):

#import <libxml/xmlmemory.h>
#import <libxml/debugXML.h>
#import <libxml/HTMLtree.h>
#import <libxml/xmlIO.h>
#import <libxml/xinclude.h>
#import <libxml/catalog.h>
#import <libxslt/xslt.h>
#import <libxslt/xsltInternals.h>
#import <libxslt/transform.h>
#import <libxslt/xsltutils.h>

...

NSString* filePath = [[NSBundle mainBundle] pathForResource: @"article" ofType: @"xml"];
NSString* styleSheetPath = [[NSBundle mainBundle] pathForResource: @"article_transform" ofType:@"xml"];

xmlDocPtr doc, res;

// tells the libxml2 parser to substitute entities as it parses your file
xmlSubstituteEntitiesDefault(1);
// This tells libxml to load external entity subsets
xmlLoadExtDtdDefaultValue = 1;

sty = xsltParseStylesheetFile((const xmlChar *)[styleSheetPath cStringUsingEncoding: NSUTF8StringEncoding]);
doc = xmlParseFile([filePath cStringUsingEncoding: NSUTF8StringEncoding]);
res = xsltApplyStylesheet(sty, doc, NULL);

char* xmlResultBuffer = nil;
int length = 0;

xsltSaveResultToString(&xmlResultBuffer, &length, res, sty);

NSString* result = [NSString stringWithCString: xmlResultBuffer encoding: NSUTF8StringEncoding];

NSLog(@"Result: %@", result);

free(xmlResultBuffer);

xsltFreeStylesheet(sty);
xmlFreeDoc(res);
xmlFreeDoc(doc);

xsltCleanupGlobals();
xmlCleanupParser();
rpitting
  • 3,329
  • 1
  • 19
  • 10
  • 2
    dylibs are not allowed on iPhone. You need to make a static lib – Lou Franco Jul 22 '10 at 00:20
  • 1
    Apple will reject this, unfortunately. See comments by Chris Gilbert, below. Since they are not providing the headers for this dylib, they consider it to be a private framework despite being a public library. – Jason Nov 25 '10 at 16:06
  • Getting an EXC_BAD_ACCESS error on "xsltSaveResultToString(&xmlResultBuffer, &length, res, sty);" Any ideas? – docchang Jan 21 '15 at 19:45
7

As Lou Franco points out, you're not allowed dylibs on the iPhone.

It'll work fine in development both in the simulator and the phone but it'll be rejected as soon as you submit it to Apple for approval. My app was rejected within about 20 minutes, presumably by their automated static analysis tool.

Instead, download the source, add it to your project, link the LibXML2.2.dylib (don't ask me why this dylib is allowed but the XSLT isn't!) and build the project. That's pretty much all you have to do. Credit to Lou for this as it was he who pointed me in the right direction.

Chris Gilbert
  • 348
  • 5
  • 12
  • 2
    Is using libxslt a headache? - Yes to a certain extent but it's not insurmountable. The best thing you can do is download the source code for LIBXSLT and include the 40 or so files (20 .m and 20 .h files) in a folder in your Xcode project. Once you've added the libxml2.2.dylib (bizarrely this dylib is acceptable!) framework, the source code of LIBXSLT will be compiled as part of the main project and you'll have no issues with regards to your app being rejected for using unsupported APIs. – Chris Gilbert Nov 26 '10 at 11:44
  • Can't compile this way. `'config.h' file not found` – surfrider Mar 16 '16 at 14:06
5

I'm afraid the xslt situation is rather grim. The NSXMLDocument class would be the way to do this but Apple pulled it from the iPhone.

TouchXML plans xslt support but doesn't have it yet.

The only option I know of is to directly use libxslt, which supports xslt 1.0 and some of the exslt extensions.

Gordon Wilson
  • 26,244
  • 11
  • 57
  • 60
2

For everyone updating to XCode 5 + iOS7 baseSDK, you will notice that if you included libxslt-1.1.26 in your project and compiled from source, it was using the prior version of libxml. In the latest base SDK libxml has been updated and as such you will need to update to libxslt-1.1.28.

When you download the latest .tar.gz file all you need to include into your project for the first time are:

  • config.h
  • libxslt/*.h
  • libxslt/*.c

But config.h and libxslt/xsltconfig.h don't exist just yet. They have the .in suffix. You will need to either run the ./configure script or if that isn't working straight out of the box for you then cheat like I did.

Step 1 - 0 differences

Simply create a new copy of config.h.in named config.h.

Step 2 - 12 differences

Simply create a new copy of libxslt/xsltconfig.h.in named libxslt/xsltconfig.h.

The first four changes are simply version numbers.

  1. #define LIBXSLT_DOTTED_VERSION "1.1.28"
  2. #define LIBXSLT_VERSION 10128
  3. #define LIBXSLT_VERSION_STRING "10128"
  4. #define LIBXSLT_VERSION_EXTRA "-GITv1.1.28"

The next four

  1. #if @WITH_XSLT_DEBUG@ -> #if 1 //Simply replace @WITH_XSLT_DEBUG@ with 1
  2. #if @WITH_MEM_DEBUG@ -> #if 1
  3. #if @WITH_TRIO@ -> #if 0
  4. #if @WITH_DEBUGGER@ -> #if 1

The last four

  1. #if @WITH_MODULES@ -> #if 1
  2. #define LIBXSLT_DEFAULT_PLUGINS_PATH() "@LIBXSLT_DEFAULT_PLUGINS_PATH@" -> #define LIBXSLT_DEFAULT_PLUGINS_PATH() "/usr/lib/libxslt-plugins"
  3. #if @XSLT_LOCALE_XLOCALE@ -> #if 1
  4. #if @XSLT_LOCALE_WINAPI@ -> #if 0

    Step 3

Now that you have manually performed the steps that ./configure would have performed you can follow the instructions outlined earlier for adding the libxslt files to your project:

  • config.h
  • libxslt/*.h
  • libxslt/*.c
Josh Peak
  • 5,898
  • 4
  • 40
  • 52
2

You cannot use libxslt on the iPhone even if you compile it and build it yourself. I have done that and have had my app rejected repeatedly. The tools used by the AppReview process do not distinguish between statically linked symbols in your code and dynamically linked symbols from the iOS. In other words, if it looks like you are using libxslt, your app will get rejected because the appstore cannot tell if you are using a private API.

  • USing it from source is perfectly acceptable since it is your source. What the appstore will automatically reject you on is if you still have a reference to a dynamically linked library. You can build libxslt as a static library and link it because you are presenting all of your binary at one time for review. libxslt-1.1.26 has a known security issue... potentially why Apple doesn't want to knowingly let you use a faulty library they provided. I think it is fixed in libxslt-1.1.28 – Josh Peak Sep 23 '13 at 01:58