Embedding FOP: resolving 'href' and 'url' references

305 views
Skip to first unread message

Paul Hoadley

unread,
Sep 14, 2010, 7:14:27 AM9/14/10
to WebObjects Apple
Hello,

I see some references to FOP in the archives over the years, so there are obviously people using it.  I hope they're still subscribed.  :-)

I am trying to embed Apache FOP into an application.  It's going quite well, but I have an outstanding issue: resolution of 'href' attributes in XSLT files and 'url' attributes in XSLFO files.  For example, I have a 'driver.xsl' file which sets some app-specific params, and then imports the stylesheet proper:

  <xsl:import href="invoice.xsl"/>

'driver.xsl' and 'invoice.xsl' are both in Resources.  Neither "/invoice.xsl" nor "/Resources/invoice.xsl" helped.  The error is fairly non-specific:

SystemId Unknown; Line #5; Column #35; Had IO Exception with stylesheet file: invoice.xsl

(Line 5, Column 35 is the location in driver.xsl where the import element finishes.)  Similarly, that transform generates some XSLFO which refers to an image:

background-image="url('invoice-logo.png')"

(The XSLFO is ephemeral, just living in an NSData object until the PDF is generated, so maybe a relative URL like that doesn't even make sense.)  In this case, I get this logged:

Sep 14 20:17:07 PBF[56565] DEBUG FOP  - File not found: file:invoice-logo.png
Sep 14 20:17:07 PBF[56565] DEBUG AbstractImageSessionContext  - URI could not be resolved: invoice-logo.png

It's not clear to me where FOP is looking for these resources, nor how to tell it to look in Resources.  Does anyone know?

Q

unread,
Sep 14, 2010, 8:31:09 AM9/14/10
to Paul Hoadley, WebObjects Apple

On 14/09/2010, at 9:14 PM, Paul Hoadley wrote:
..
background-image="url('invoice-logo.png')"

(The XSLFO is ephemeral, just living in an NSData object until the PDF is generated, so maybe a relative URL like that doesn't even make sense.)  In this case, I get this logged:

Sep 14 20:17:07 PBF[56565] DEBUG FOP  - File not found: file:invoice-logo.png
Sep 14 20:17:07 PBF[56565] DEBUG AbstractImageSessionContext  - URI could not be resolved: invoice-logo.png

It's not clear to me where FOP is looking for these resources, nor how to tell it to look in Resources.  Does anyone know?

Unless FOP supports some kind of resource resolution delegate there may not be a nice solution to this issue. You can try supplying the full filesystem path of the resource to the transform files and see if that works, or alternatively you could try using full WSR URL's that point back to the application itself. This may work for static content, but if you need to use a dynamic resource like a WOImage in your content you will likely need to find a different solution.

Have a look at the source for ERPDFGeneration in wonder for how this problem is currently handled. If you aren't tied to using FOP you may wish to try using it instead.

-- 

Seeya...Q


Quinton Dolan - qdo...@gmail.com

Gold Coast, QLD, Australia (GMT+10)





Fabian Peters

unread,
Sep 14, 2010, 8:34:44 AM9/14/10
to WebObjects Apple
Hi Paul,

Am 14.09.2010 um 13:14 schrieb Paul Hoadley:

> Hello,
>
> I see some references to FOP in the archives over the years, so there are obviously people using it. I hope they're still subscribed. :-)
>
> I am trying to embed Apache FOP into an application. It's going quite well, but I have an outstanding issue: resolution of 'href' attributes in XSLT files and 'url' attributes in XSLFO files. For example, I have a 'driver.xsl' file which sets some app-specific params, and then imports the stylesheet proper:
>
> <xsl:import href="invoice.xsl"/>
>
> 'driver.xsl' and 'invoice.xsl' are both in Resources. Neither "/invoice.xsl" nor "/Resources/invoice.xsl" helped. The error is fairly non-specific:
>
> SystemId Unknown; Line #5; Column #35; Had IO Exception with stylesheet file: invoice.xsl
>
> (Line 5, Column 35 is the location in driver.xsl where the import element finishes.) Similarly, that transform generates some XSLFO which refers to an image:
>
> background-image="url('invoice-logo.png')"
>
> (The XSLFO is ephemeral, just living in an NSData object until the PDF is generated, so maybe a relative URL like that doesn't even make sense.) In this case, I get this logged:
>
> Sep 14 20:17:07 PBF[56565] DEBUG FOP - File not found: file:invoice-logo.png
> Sep 14 20:17:07 PBF[56565] DEBUG AbstractImageSessionContext - URI could not be resolved: invoice-logo.png

I'm only using straight FOP (w/o any XSLT). Ages ago, I set up an FOImage component. This is the .wod:

Image: WOXMLNode {
alt = ^alt;
border = ^border;
elementName = "fo:external-graphic";
mimetype = ^mimeType;
src = src;
height = ^height;
line-height = ^lineHeight;
width = ^width;
content-width = ^content-width;
content-height = ^content-height;
}

The src is:

public URL src() {
WOResourceManager resourceManager = application().resourceManager();

String filename = (String) valueForBinding("filename");
String framework = (String) valueForBinding("framework");

return resourceManager.pathURLForResourceNamed(filename, framework, null);
}

I'd guess you'll also have to get the URL from the resource manager and pass that in somehow. I'd also guess the same applies to the URLs for any xsl files.

cheers, Fabian

> It's not clear to me where FOP is looking for these resources, nor how to tell it to look in Resources. Does anyone know?
>
>
> --
> Paul.
>
> http://logicsquad.net/
>
>

> _______________________________________________
> Do not post admin requests to the list. They will be ignored.
> Webobjects-dev mailing list (Webobje...@lists.apple.com)
> Help/Unsubscribe/Update your Subscription:
> http://lists.apple.com/mailman/options/webobjects-dev/lists.fabian%40e-lumo.com
>
> This email sent to lists....@e-lumo.com

_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (Webobje...@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/webobjects-dev/webobjects-dev-garchive-31333%40googlegroups.com

This email sent to webobjects-dev...@googlegroups.com

r...@synapticstorm.com

unread,
Sep 14, 2010, 11:00:13 AM9/14/10
to Paul Hoadley, WebObjects Apple
Hi Paul,

I switch from FOP to iText, but when I was using FOP I found I had to specify the full system path for it to work.

Rob.

_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list      (Webobje...@lists.apple.com)
Help/Unsubscribe/Update your Subscription:

Paul Hoadley

unread,
Sep 14, 2010, 9:25:21 PM9/14/10
to Q, WebObjects Apple
On 14/09/2010, at 10:01 PM, Q wrote:

Unless FOP supports some kind of resource resolution delegate

Thanks for the idea.  It turns out that FOP does indeed support custom URI resolvers.  I created a subclass of FOURIResolver which just overrides resolve(String, String), and returns a StreamSource by calling WOResourceManager.inputStreamForResourceNamed():

public class WOURIResolver extends FOURIResolver {
@Override
public Source resolve(java.lang.String href, java.lang.String base) throws javax.xml.transform.TransformerException {
return new StreamSource(WOApplication.application().resourceManager().inputStreamForResourceNamed(href, null, null));
}
}

(Obviously this is an incomplete proof of concept.  That method would certainly need to call super.resolve() at some point if the WOResourceManager can't find the resource, as it's effectively swallowing up all _other_ URI references.  I just happen to have none in this particular situation.)

Passing one of these to TransformerFactory.setURIResolver() sorts out the xsl:import issue, and to FopFactory.setURIResolver() sorts out the fo:external-graphic problem.

Have a look at the source for ERPDFGeneration in wonder for how this problem is currently handled. If you aren't tied to using FOP you may wish to try using it instead.

As an aside, I'm only tied to FOP to the extent that I have an existing XSLFO solution for simple invoice generation that I currently use with RenderX's XEP.  The cost of embedding XEP for this particular application is prohibitive.  FOP seemed like an interesting alternative if I could get it to work.  I haven't looked at it since about version 0.2, and it seems to be doing well enough to render the very simple documents I'm throwing at it here.  And the price is right.



Paul Hoadley

unread,
Sep 14, 2010, 9:30:29 PM9/14/10
to Fabian Peters, WebObjects Apple
Hi Fabian,

On 14/09/2010, at 10:04 PM, Fabian Peters wrote:

> I'm only using straight FOP (w/o any XSLT). Ages ago, I set up an FOImage component. This is the .wod:
>
> Image: WOXMLNode {
> alt = ^alt;
> border = ^border;
> elementName = "fo:external-graphic";
> mimetype = ^mimeType;
> src = src;
> height = ^height;
> line-height = ^lineHeight;
> width = ^width;
> content-width = ^content-width;
> content-height = ^content-height;
> }
>
> The src is:
>
> public URL src() {
> WOResourceManager resourceManager = application().resourceManager();
>
> String filename = (String) valueForBinding("filename");
> String framework = (String) valueForBinding("framework");
>
> return resourceManager.pathURLForResourceNamed(filename, framework, null);
> }
>
> I'd guess you'll also have to get the URL from the resource manager and pass that in somehow. I'd also guess the same applies to the URLs for any xsl files.

Thanks for that. I actually hadn't thought of generating the FO directly from a component. (I generate an XML document from a component, and transform that.) Nice idea.


--
Paul.

http://logicsquad.net/


_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (Webobje...@lists.apple.com)
Help/Unsubscribe/Update your Subscription:

Patrick Robinson

unread,
Oct 1, 2010, 10:55:34 PM10/1/10
to Paul Hoadley, WebObjects Apple
Hi Paul,

I just saw this (late to the party).  I solved this for one of our apps in a way very similar to what you have there:

public class XSLURIResolver implements URIResolver {

        public Source resolve(String href, String base) throws TransformerException {
                StringBuffer path = new StringBuffer(WOApplication.application().path());
                path.append("/Contents/Resources/");
                path.append(href);
                File file = new File(path.toString());
                if(file.exists()) return new StreamSource(file);
                return null;
        }

}

This works whether it's running on development or deployment machine, and whether from Eclipse or from command line.

- Patrick

Paul Hoadley

unread,
Oct 2, 2010, 5:06:53 AM10/2/10
to Patrick Robinson, WebObjects Apple
Hi Patrick,

On 02/10/2010, at 12:25 PM, Patrick Robinson wrote:

> I just saw this (late to the party). I solved this for one of our apps in a way very similar to what you have there:
>
> public class XSLURIResolver implements URIResolver {
>
> public Source resolve(String href, String base) throws TransformerException {
> StringBuffer path = new StringBuffer(WOApplication.application().path());
> path.append("/Contents/Resources/");
> path.append(href);
> File file = new File(path.toString());
> if(file.exists()) return new StreamSource(file);
> return null;
> }
>
> }
>
> This works whether it's running on development or deployment machine, and whether from Eclipse or from command line.

Thanks for that. Quite similar.

Reply all
Reply to author
Forward
0 new messages