1

I am storing xslt in database. I want to call the a template from another xslt that too is stored in database. Using below sample code I am able to run the xslt correctly (consider xsltOneStr is xslt string coming from database via dao layer so is xmlStr which is xml to be parsed)

However if I use in xsltOne.xsl, it will obviously complain since the source xsltOne.xsl is from db and the called xsltTwo.xsl too is in DB. Obviously it is logically incorrect to use import in my case since I am not using filesystem to get xsl but stream of characters coming from DB but for sake of conversation I used import tag.

So the question since xsl is coming from DB what should I use instead of xsl:import. I am using Java & xslt is able to call java method. Is there any way I can use java method to call second xslt that resides in db (xsltTwo.xsl). If xsltTwo.xsl in it entirety can cannot be called by java method can I at least insert a template declared in xsltTwo on the fly in xsltOne.xsl

For example we can call java method to assign value to xsl parameter using java as

Similarly can we assign the whole template or call one xslt from another xslt using java method?

        Source xsltOne=new StreamSource(new StringReader(xsltOneStr));
        Source xml =new StreamSource(new StringReader(xmlStr));

        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer transformer = factory.newTransformer(xsltOne);

        StringWriter writer = new StringWriter();
        transformer.transform(xml, new StreamResult(writer));
user593029
  • 511
  • 7
  • 18
  • 1
    There is no problem with having `xsl:import` in your XSLT, even if you read it from database. Your issue is more on how to deal with XSLT including another XSLT in Java, no matter the database.. Have you looked at this link :http://stackoverflow.com/questions/3699860/resolving-relative-paths-when-loading-xslt-files ? – Gaël J Oct 22 '15 at 19:23
  • 1
    @user593029 I just noticed that you ask a lot of questions but rarely [accept](https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work/5235#5235) answers. – wero Oct 22 '15 at 19:33

2 Answers2

2

You can tweak the loading of XML stylesheets or documents done with document(), xsl:import or xsl:include by providing an URIResolver:

TransformerFactory factory = TransformerFactory.newInstance();
factory.setURIResolver(new MyURIResolver());
Transformer transformer = factory.newTransformer(xsltOne);

Now when the factory encounters the xsl:import directive your URIResolver is notified to provide a Source for the imported stylesheet. You therefore just need to provide a URIResolver which loads the imported stylesheet from the database and returns it as Source object.

wero
  • 32,544
  • 3
  • 59
  • 84
  • i got some more info in below link using URIResolver, but this is helpful to resolve relative path or if it is loaded from classpath. In either case xslt is present physically in my case the second xslt is coming from database so I am not sure how URIResolver can help that. Can some one let me know how can I integrate/import second XSLT which is coming as string from DB http://stackoverflow.com/questions/3699860/resolving-relative-paths-when-loading-xslt-files – user593029 Oct 22 '15 at 19:47
  • 2
    you have some code to load a stylesheet from the database (that is how you populated `xsltOneStr`). Now in your URIResolver call the same code to load the imported stylesheet. – wero Oct 22 '15 at 19:49
  • The URIResolver returns a Source object. Read the stylesheet from the database as a string, wrap this in a StringReader, wrap the StringReader in a StreamSource, and return the StreamSource (which implements Source). It's probably also a good idea to call setSystemId() on the StreamSource so it has a known base URI. – Michael Kay Oct 22 '15 at 20:24
0

In case if someone is looking for how to create resolver I found a way as described below. 'MyResolver' class uses a constructor that takes the xslt string as parameter & is passed to 'factory.setURIResolver' method. On transformation it invokes resolve method which in turn passes StreamSource obj that is formed using the xstl string that is coming from db/file. (You can construct resolve method with more if & else clause depending on number of xslt you are passing & make if more generic using path & names)

The line factory.setURIResolver(new MyResolver(xsltTwoStr)); you can see that it uses "xsltTwoStr" which is nothing but the import xslt string that is expected in xsltOne. You can bring xslt string ("xsltTwoStr") using dao layer which makes call to db or just load the file itself.

        Source xsltOne=new StreamSource(new StringReader(xsltOneStr));
        Source xml =new StreamSource(new StringReader(xmlStr));


        TransformerFactory factory = TransformerFactory.newInstance();
        factory.setURIResolver(new MyResolver(xsltTwoStr));

        Transformer transformer = factory.newTransformer(xsltOne);

        StringWriter writer = new StringWriter();
        transformer.transform(xml, new StreamResult(writer));



class MyResolver implements URIResolver {
          String xsltStr;

          public MyResolver(String xsltStr) {
            this.xsltStr = xsltStr;
          }

          public Source resolve(String href,String base) {

              return new StreamSource(new StringReader(this.xsltStr));
          }
        }
user593029
  • 511
  • 7
  • 18