Hai all,
I have a problem with resolving the relative path of a entity file
within a xsl file.
I am using docbook for in my web application
In the Docbook the file named docbook.xsl which includes other xsl files
Among two such included xsl file(autoidx.xsl and glossary.xsl) in the a
.ent file in its header as follows
<!DOCTYPE xsl:stylesheet [
<!ENTITY % common.entities *SYSTEM "../common/entities.ent"*>
%common.entities;
]>
Here comes the relative path problem.
I am getting the error
java.lang.Exception: Transformation error:
yanelrepo:/docbook-xsl-1.73.2/html/autoidx.xsl:Line=4;Column=18:
exception:Had IO Exception with stylesheet file: autoidx.xsl
root-cause:null
line: logSourceLine unavailable due to: unknown protocol: yanelrepo
All xsl includes are resolved by two java class file written by me
named BasicXMLResource.java and SourceResolver.java
The BasicXMLResource is called from servlet.The getXMLView() is
processing the xsl files and call the resolve() method in SourceResolver
to resolve the relative path.
////////////////////////////getXSLView//////////////////////////////////////////////////////////////////////////////////////////
public View getXMLView(String viewId, InputStream xmlInputStream) throws
Exception {
View view = new View();
if (viewId == null) {
viewId = DEFAULT_VIEW_ID;
}
ConfigurableViewDescriptor viewDescriptor =
(ConfigurableViewDescriptor)getViewDescriptor(viewId);
String mimeType = getMimeType(viewId);
view.setMimeType(mimeType);
StringWriter errorWriter = new StringWriter();
try {
if (viewId != null && viewId.equals(SOURCE_VIEW_ID)) {
view.setInputStream(xmlInputStream);
return view;
}
// create reader:
XMLReader xmlReader = XMLReaderFactory.createXMLReader();
CatalogResolver catalogResolver = new CatalogResolver();
//SourceEntityResolver sourceEntityResolver = new
SourceEntityResolver();
xmlReader.setEntityResolver(catalogResolver);
xmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes",
true);
SourceResolver uriResolver = new SourceResolver(this);
ListingErrorHandler errorListener = new
ListingErrorHandler(new PrintWriter(errorWriter));
// create xslt transformer:
SAXTransformerFactory tf =
(SAXTransformerFactory)TransformerFactory.newInstance();
tf.setURIResolver(uriResolver);
tf.setErrorListener(errorListener);
String[] xsltPaths = viewDescriptor.getXSLTPaths();
if (xsltPaths == null || xsltPaths.length == 0) {
xsltPaths = getXSLTPath(getPath());
}
Repository repo = getRealm().getRepository();
TransformerHandler[] xsltHandlers = new
TransformerHandler[xsltPaths.length];
for (int i = 0; i < xsltPaths.length; i++) {
// TODO: Use resolver
if (xsltPaths[i].startsWith("file:")) {
log.warn("Scheme: file (" + xsltPaths[i] + ")");
xsltHandlers[i] = tf.newTransformerHandler(new
StreamSource(new java.io.FileInputStream(xsltPaths[i].substring(5))));
} else if(xsltPaths[i].startsWith("rthtdocs:")) {
log.warn("Scheme: rthtdocs (" + xsltPaths[i] + ")");
xsltHandlers[i] = tf.newTransformerHandler(new
org.wyona.yanel.core.source.RTHtdocsResolver(this).resolve(xsltPaths[i],
null));
} else {
if (xsltPaths[i].indexOf(":/") > 0) {
log.error("No such protocol implemented: " +
xsltPaths[i].substring(0, xsltPaths[i].indexOf(":/")));
} else {
if (log.isDebugEnabled()) {
log.debug("Default Content repository will
be used!");
}
}
xsltHandlers[i] = tf.newTransformerHandler(new
StreamSource(repo.getNode(xsltPaths[i]).getInputStream(), "yanelrepo:" +
xsltPaths[i]));
}
xsltHandlers[i].getTransformer().setURIResolver(uriResolver);
xsltHandlers[i].getTransformer().setErrorListener(errorListener);
passTransformerParameters(xsltHandlers[i].getTransformer());
}
// create i18n transformer:
I18nTransformer3 i18nTransformer = new
I18nTransformer3(getI18NCatalogueNames(), getRequestedLanguage(),
getRealm().getDefaultLanguage(), uriResolver);
i18nTransformer.setEntityResolver(catalogResolver);
// create xinclude transformer:
XIncludeTransformer xIncludeTransformer = new
XIncludeTransformer();
xIncludeTransformer.setResolver(uriResolver);
// create serializer:
Serializer serializer = createSerializer(viewDescriptor);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// chain everything together (create a pipeline):
if (xsltHandlers.length > 0) {
xmlReader.setContentHandler(xsltHandlers[0]);
for (int i=0; i<xsltHandlers.length-1; i++) {
xsltHandlers[i].setResult(new
SAXResult(xsltHandlers[i+1]));
}
xsltHandlers[xsltHandlers.length-1].setResult(new
SAXResult(xIncludeTransformer));
} else {
xmlReader.setContentHandler(new
SAXResult(xIncludeTransformer).getHandler());
}
xIncludeTransformer.setResult(new SAXResult(i18nTransformer));
i18nTransformer.setResult(new
SAXResult(serializer.asContentHandler()));
serializer.setOutputStream(baos);
System.out.println("No error before parse");
// execute pipeline:
xmlReader.parse(new InputSource(xmlInputStream));
System.out.println("No error after parse");
// write result into view:
view.setInputStream(new
ByteArrayInputStream(baos.toByteArray()));
return view;
} catch(Exception e) {
log.error(e + " (" + getPath() + ", " + getRealm() + ")", e);
String errorMsg;
String transformationError = errorWriter.toString();
if (transformationError != null) {
errorMsg = "Transformation error:\n" + transformationError;
log.error(errorMsg);
} else {
errorMsg = e.getMessage();
}
throw new Exception(errorMsg);
}
}
////////////////////////////////////////////////////Inside
SourceResolver
class///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public InputSource resolveEntity(String href, String base) {
System.out.println("Entered");
InputSource result;
result = super.resolveEntity(href, base);
result.setSystemId(base);
return result;
}
/**
*
*/
public Source resolve(String uri, String base) throws SourceException {
if (log.isDebugEnabled()) {
log.debug("URI to be resolved: " + uri);
log.debug("Base: "+ base);
}
// NOTE: One cannot use ":/" in order to find the
protocol/scheme, because one can also specifiy the realm id and
repository id, for example: yanelrepo:REALM_ID:REPO_ID:/foo/bar.gif
int colonIndex = uri.indexOf(":");
//int colonIndex = uri.indexOf(":/");
String uriScheme = "";
if (colonIndex <= 0) {//Check for scheme in URI, if true, then
URI has no scheme
//log.error("DEBUG: URI has no scheme: " + uri);
if (base != null) {
int colBaseIndex = base.indexOf(":");
//int colBaseIndex = base.indexOf(":/");
if(colBaseIndex <=0 ){//Check for scheme in Base
throw new SourceException("invalid url syntax
(missing scheme): " + uri);//no scheme found in uri and base
}else{//base contains scheme. Use base scheme for uri scheme
uriScheme = base.substring(0, colBaseIndex);
uri = PathUtil.concat(base,uri);
//log.error("DEBUG: Use scheme of base: " +
uriScheme + ", " + uri);
}
} else {
log.error("Neither scheme for URI nor base specified for
URI: " + uri);
throw new SourceException("invalid url syntax (missing
scheme): " + uri);//no scheme found in uri and base
}
} else {//uri contains scheme
uriScheme = uri.substring(0, colonIndex);
//log.error("DEBUG: URI has scheme: " + uriScheme + ", " + uri);
}
URIResolver resolver = getResolver(uriScheme);
if (resolver != null) {
try {
// TODO: What shall be used as base?!
Source s = resolver.resolve(uri, base);
s.setSystemId(uri);
return s;
} catch (TransformerException e) {
throw new SourceException(e.getMessage(), e);
}
} else {
throw new SourceException("No resolver could be loaded for
scheme: " + uriScheme);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
please help me
Best Regards
Navas