Failed to load XML files inside XSLT
Added by Yevgeniy Yanavichus about 4 years ago
- We have different sets of stylesheets (modules). Each module looks like this:
lib1.xslt
lib2.xslt
...
lib10.xslt
transform.xslt
fileName1.xml
fileName2.xml
Some xslt
files can have XML
files loaded via:
<xsl:variable name="mapping" select="document(fileName1.xml')/mapping" />
- Then we compile modules and get folders like this:
transform.sef
fileName1.xml
fileName2.xml
- Each module is in it's own folder:
sef/module1/*
sef/module2/*
sef/module3/*
...
-
When we run transformation from command line using
JAR
file and fromsaxon-node
everything is fine -
But when we run this modules from
s9api
by putting these modules toresources
folder we're getting messages like this:
Warning on line 715 of lib5.xslt:
FODC0002: I/O error reported by XML parser processing
file:/D:/Code/HERE_IT_IS_PATH_TO_ROOT_PROJECT_FOLDER_NOT_TO_THE_RESOURCES_AND_NOT_TO_THE_MODULE_INSIDE_RESOURCES/fileName1.xml:
D:\Code\HERE_IT_IS_PATH_TO_ROOT_PROJECT_FOLDER_NOT_TO_THE_RESOURCES_AND_NOT_TO_THE_MODULE_INSIDE_RESOURCES\fileName1.xml (The system
cannot find the file specified)
Warning on line 715 of lib5.xslt:
FODC0002: Document has been marked not available: fileName1.xml
Warning on line 715 of lib5.xslt:
FODC0002: Document has been marked not available: fileName1.xml
Warning on line 715 of lib5.xslt:
FODC0002: Document has been marked not available: fileName1.xml
Warning on line 715 of lib5.xslt:
FODC0002: Document has been marked not available: fileName1.xml
Warning on line 254 of lib5.xslt:
FODC0002: Document has been marked not available: fileName1.xml
Any idea how to fix it? Maybe we should use any type of custom url resolvers? I did a brief check of resolvers here: https://www.saxonica.com/documentation9.2/javadoc/net/sf/saxon/FeatureKeys.html, but still not sure which one to use
Replies (8)
Please register to reply
RE: Failed to load XML files inside XSLT - Added by Michael Kay about 4 years ago
Here are a few suggested approaches.
(a) Change the calls on document()
in the stylesheet to call resolve-uri()
explicitly, perhaps taking the base URI from the value of a stylesheet parameter.
(b) Change the calls on document()
to use a classpath URI ("classpath://fileName1.xml") to load them from the Java classpath.
(c) When you generate the SEF file, specify -relocate:on
. If you do this, a relative URI passed to the document()
function will be interpreted as relative to the location of the SEF file, not relative to the location of the source XSLT module. (However, from your description, I'm not sure this is what you want, as the documents seem to be in a different folder).
(d) Supply a run-time URIResolver
(Xslt30Transformer.setURIResolver()
) to resolve the references.
RE: Failed to load XML files inside XSLT - Added by Yevgeniy Yanavichus about 4 years ago
I tried first three options but they didn't help. Fourth point is no about s9api
as I understood. I'll try to describe this issue from another view:
- We have compiled
SEF
file with siblingsXML
files nearby:
D:\Code\com\company\project\resources\static\module1\transform.sef
D:\Code\com\company\project\resources\static\module1\file1.xml
D:\Code\com\company\project\resources\static\module1\file2.xml
D:\Code\com\company\project\resources\static\module1\file3.xml
Here we load transform.sef
via:
resourceLoader.getResource("classpath:static/sef/module1/transform.sef");
And get exception saying that XML
files could not be loaded from folder D:\Code\com\company\project\
- When using similar project structure either using
saxon-node
or from command line it works fine:
D:\Code\project\sef\transform.sef
D:\Code\project\sef\file1.xml
D:\Code\project\sef\file2.xml
D:\Code\project\sef\file3.xml
D:\Code\project\app.js
Here we load transform.sef
and don't care about XML
files at all
- We opened
SEF
file in text editor and see that we have references to file names like:
file1.xml
file2.xml
file3.xml
We also tried:
./file1.xml
./file2.xml
./file3.xml
- I agree that
resolve-uri
can potentially help - it's creating full path to theXML
file. But would be good to have it working in development as well. So, the question is: can we use any kind of URI resolver so that it acceptsSEF
file name andXML
file name and produces final full path toXML
(using base path fromSEF
file name)?
RE: Failed to load XML files inside XSLT - Added by Michael Kay about 4 years ago
A couple of questions:
(a) Did you use the -relocate option when creating the SEF file?
(b) You say you loaded the SEF file using resourceLoader.getResource("classpath:static/sef/module1/transform.sef");
. I guess you're talking here about the Spring ResourceLoader. This method returns a Resource
object. What do you then do with this Resource
object? How do you construct the Source
object that is passed to the Saxon XsltCompiler
? Does this Source
object have a known systemId
property? If it doesn't, then Saxon can't know where the SEF file was loaded from, and can't load other things relative to it.
RE: Failed to load XML files inside XSLT - Added by Yevgeniy Yanavichus about 4 years ago
(a) Yes. Full command:
java -jar .\saxon\saxon9ee.jar -xsl:.\xslt\module1\transform.xsl -export:.\sef\module1\transform.sef -target:PE -nogo -relocate:on
(b) Yes, it's Spring
project. Here it's full code:
XsltCompiler compiler = getProcessor().newXsltCompiler();
final Resource xslFileResource = resourceLoader.getResource("classpath:static/sef/gp/transform.sef");
// return compiler.loadExecutablePackage(new URI("classpath:static/sef/module1/transform.sef"));
return compiler.compile(new StreamSource(xslFileResource.getInputStream()));
Transformation with commented line also works but I decided to stay with compile
(I agree looks strange to compile already precompiled stylesheet but I didn't have too much time investigating that)
I'm not sure about systemId
property. Probably no. I guess it's about jaxp
, but I decide to stay with s9api
(you also recommended that in another thread)
RE: Failed to load XML files inside XSLT - Added by Michael Kay about 4 years ago
OK, try changing the call to
new StreamSource(xslFileResource.getInputStream(), "classpath:static/sef/gp/transform.sef")
That way, Saxon will know the stylesheet location and will be able to resolve other URIs relative to that location.
The only caveat is, it won't be using Spring to locate these resources, so the search might not be identical to the one that Spring will do. Instead, it will be using classLoader.getResourceAsStream()
(and if you need to know exactly which classloader, the answer gets complicated). But give that a try. If it doesn't work, you'll have to resort to using your own URIResolver that invokes Spring.
RE: Failed to load XML files inside XSLT - Added by Michael Kay about 4 years ago
In fact, I don't know if this is going to be necessary, but if you want all resource loading to go via Spring (which might be handy for things like system logging and diagnostics), then the way to do it is probably to register your own DynamicLoader
with the Saxon Configuration. You could do something like
class SpringDynamicLoader extends net.sf.saxon.trans.DynamicLoader {
public SpringDynamicLoader(ResourceLoader springLoader) {
this.springLoader = springLoader;
}
@Override public InputStream getResourceAsStream(String name) {
return resourceLoader.getResource(name).getInputStream();
}
}
processor.getUnderlyingConfiguration().setDynamicLoader(new SpringDynamicLoader(resourceLoader));
and then Saxon's dereferencing of the URIs for the XML documents will be done via Spring.
RE: Failed to load XML files inside XSLT - Added by Yevgeniy Yanavichus about 4 years ago
Thanks for you responses. I'll try all of them. I just realized my questions could be not completely correct, because Spring
is injecting all resources into JAR
file. And final resolved path must be classpath
, not filesystem path. And I guess your suggestions should work. Otherwise I'll just used fixed paths different for dev/prod environments.
RE: Failed to load XML files inside XSLT - Added by Yevgeniy Yanavichus about 4 years ago
Tried to pass second parameter, and got error saying the same thing but file path now is classpath:file1.xml
. Will try another choice later
Please register to reply