代码之家  ›  专栏  ›  技术社区  ›  liubitel

从java资源目录文件访问的文件的相对路径

  •  0
  • liubitel  · 技术社区  · 2 年前

    我有一个 example.xsl File 在Java资源目录中,通过以下方式在Java中访问:

    class.getClassLoader().getResourceAsStream("example.xsl");
    

    但是 example.xsl文件 它本身有一个参考:

    <xsl:include href="dir/i18n.inc.xslt"/>
    

    我想把 dir directory 具有 i18n.inc.xslt 在resource目录中,但是当我部署代码时,程序似乎在寻找 dir/i18n.inc.xslt 在…内 glassfish/domains/domain1/config

    我应该如何参考 目录/i18n.inc.xslt 在里面 href 这样它就能查看内部资源?

    编辑: 我使用 Java 17 Payara 6 XSLT用于将XML转换为PDF。我正在使用 Apache FOP 为此目的。

    InputStream  styleSheetInput = MyClass.class.getClassLoader().getResourceAsStream("example.xsl");
    
                final FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
                FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
    
                try {
                    Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, outputStream);
                    // Setup XSLT
                    TransformerFactory factory = TransformerFactory.newInstance();
                    Transformer transformer = factory.newTransformer(new StreamSource(styleSheetInput));
    
                    // Set the value of a <param> in the stylesheet
                    transformer.setParameter("versionParam", "2.0");
    
                    // Setup input for XSLT transformation
                    Source src = new StreamSource(datafile);
    
                    // Resulting SAX events (the generated FO) must be piped through to FOP
                    Result res = new SAXResult(fop.getDefaultHandler());
    
                    // Start XSLT transformation and FOP processing
                    transformer.transform(src, res);
               }
    

    我得到的例外情况:

     [tid: _ThreadID=279 _ThreadName=__ejb-thread-pool11] [timeMillis: 1693598088423] [levelVal
      /usr/local/payara6/glassfish/domains/domain1/config/dir/i18n.inc.xslt (No such file or directory)]]
    

    所以它看起来是在config目录中作为一个基本目录。但我不想把 XSLT File 那里我把它放在和 example.xsl 在资源方面。

    1 回复  |  直到 2 年前
        1
  •  1
  •   liubitel    2 年前

    最后,通过在Transformer的Source中设置systemId解决了问题。

    String sysId = this.class.getClassLoader().getResource("example.xsl").toURI().toString();
    InputStream  styleSheetInput = this.class.getClassLoader().getResourceAsStream("example.xsl");
    ...
    Source mySrc = new StreamSource(styleSheetInput);
    mySrc.setSystemId(sysId);
    Transformer transformer = factory.newTransformer(mySrc);
    

    我还将 i18n.inc.xslt 进入 i18n.inc.xsl 否则它就不会进入 WEB-INF/classes 出于某种原因。

        2
  •  -1
  •   AztecCodes    2 年前

    XSLT file 加载的路径有时可能很难理解,因此了解如何根据文件上下文解析这些路径非常重要。

    这个 XSLT文件 位于资源目录中,因此使用相对路径引用 i18n.inc.xslt 位于 dir subdirectory 因此,解决方案是提供一条相对于 XSLT文件 。 假设您的目录结构如下所示:

    src
    └── main
        └── resources
            ├── example.xsl
            └── dir
                └── i18n.inc.xslt
    

    提到 it8n.inc.xslt example.xsl 文件。 这样做:

    <xsl:include href="dir/i18n.inc.xslt"/>
    

    当然 Deployment Configuration 也可能会搞砸。如果配置或类路径中存在问题,请确保正确设置了应用程序类路径和资源加载配置。

    请注意,在引用中的资源时,在资源位置的上下文中使用正确的相对路径至关重要 XSLT 从类路径加载的文件或其他资源。否则它将无法正常工作。

    更新:

    使用 Different Path Resolution Method 可以解决此问题。我们不要只依赖相对路径,而是尝试使用指向类路径中资源的绝对路径。使用代码获取绝对路径,然后在 XSLT File :

    String includePath = class.getClassLoader().getResource("dir/i18n.inc.xslt").toExternalForm();
    // Pass includePath to the XSLT as a parameter or substitute it in the XSLT file.
    

    XSLT File:

    <xsl:include href="{includePath}"/>
    

    System ClassLoader方法: 不同的类加载器或部署环境可能会导致资源加载中出现意外行为。使用 System Class Loader 加载资源可能有助于:

    InputStream inputStream = ClassLoader.getSystemResourceAsStream("dir/i18n.inc.xslt");
    // If this idea works differently from the original one you were using
    // this could be a workaround for your situation.