Search code examples
javaxmlxsltjar

Unable find href within XSLT, when transforming XML. Java


Some background... I am transforming a xml (condensedModel) file using a xslt (deployments.xslt).

I have a deployments.xslt file that is using a functions.xslt file that is included using href. This is where the problem looks to be. It seems to not be able to find the functions.xslt file I made and am referencing within that file.

<xsl:stylesheet version="1.0"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
<xsl:variable name="lowercase" select="'abcdefghijklmnopqrstuvwxyz-_'"/>
<xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ. '"/>
<!--    <xsl:variable name="kubename" select="'name'"/>-->
<xsl:variable name="kubename" select="'app.kubernetes.io/name'"/>
<xsl:variable name="quot">"</xsl:variable>
<xsl:variable name="apos">'</xsl:variable>
<xsl:include href="functions.xslt"/>

Java:

  private TransformerFactory factory = TransformerFactory.newInstance();
  private Transformer transformer;

  private void init(String xslt) throws IOException, TransformerConfigurationException, AggregatorException {
   if (xslt == null || xslt.isEmpty()) {
     throw new AggregatorException("XSLT was null or empty. Unable to transform condensed model to yaml");
   }
   transformer = factory.newTransformer(new StreamSource(new StringReader(xslt)));

   Security.addProvider(new BouncyCastleProvider()); 
 }

  public String transform(TransformingYamlEnum transformerToUse) throws TransformerException, IOException, AggregatorException {
    String xslt = determineXsltToUse(transformerToUse);
    init(xslt);

    try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
      InputStream inputStream = new ByteArrayInputStream(condensedModel.getBytes(StandardCharsets.UTF_8));
      process(inputStream, bos);

      return bos.toString("UTF-8");
    }
  }

  private void process(InputStream inputStream, OutputStream outputStream) throws TransformerException {
    transformer.transform(
        new StreamSource(inputStream),
        new StreamResult(outputStream));
  }

This is obviously within a jar and the deployments.xslt is being loaded in within my init(). The actual transformation takes place when I call trasform().

It does work when I hard code the path to let's say the desktop and manually place the functions.xslt file on the desktop. But as you can imagine, this is not a viable option. Any ideas about what I am doing wrong?


Solution

  • The XSLT processor cannot resolve a relative URI in xsl:include/xsl:import unless it knows the base URI of the stylesheet. If you supply the input as a StreamSource wrapping an InputStream, without also supplying a SystemId, then the base URI will be unknown.

    In your example the XSLT processor has no idea where the stylesheet code came from.