15

我找到了很多为此引用 Java 和 C 的示例,但是我如何或可以使用 XSL 检查是否存在外部文件。

首先,我意识到这只是一个片段,但它是一个巨大的样式表的一部分,所以我希望它足以显示我的问题。

    <!-- Use this template for Received SMSs -->
<xsl:template name="ReceivedSMS">
    <!-- Set/Declare "SMSname" variable (local, evaluates per instance) -->
    <xsl:variable name="SMSname">
        <xsl:value-of select=" following-sibling::Name"/>
    </xsl:variable>
    <fo:table font-family="Arial Unicode MS" font-size="8pt" text-align="start">
        <fo:table-column column-width=".75in"/>
        <fo:table-column column-width="6.75in"/>
        <fo:table-body>
            <fo:table-row>
                <!-- Cell contains "speakers" icon -->
                <fo:table-cell display-align="after">
                    <fo:block text-align="start">
                        <fo:external-graphic src="../images/{$SMSname}.jpg" content-height="0.6in"/>

我想要做的,是放在一个“if”语句中,围绕该{$SMSname}.jpg行。那是:

                     <fo:block text-align="start">
                        <xsl:if test="exists( the external file {$SMSname}.jpg)">
                            <fo:external-graphic src="../images/{$SMSname}.jpg" content-height="0.6in"/>                            
                        </xsl:if>
                        <xsl:if test="not(exists( the external file {$SMSname}.jpg))">
                            <fo:external-graphic src="../images/unknown.jpg" content-height="0.6in"/>                            
                        </xsl:if>
                    </fo:block>                       

由于“分组”等原因,我使用的是 XSLT 2.0。我希望这是可以做到的。我更希望它是简单的。

与往常一样,提前感谢您的帮助。洛

4

10 回答 10

11

对于可能偶然发现这个老问题的其他人,通过拼凑来自互联网上各种来源的信息,我想出了这个 XSLT2 函数,它使用 Java 扩展来检查文件是否存在:

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:java="http://www.java.com/"
  exclude-result-prefixes="java xs">

  <xsl:function name="java:file-exists" xmlns:file="java.io.File" as="xs:boolean">
    <xsl:param name="file" as="xs:string"/>
    <xsl:param name="base-uri" as="xs:string"/>

    <xsl:variable name="absolute-uri" select="resolve-uri($file, $base-uri)" as="xs:anyURI"/>
    <xsl:sequence select="file:exists(file:new($absolute-uri))"/>
  </xsl:function>

</xsl:stylesheet>

然后,您可以像这样使用该函数:

<xsl:if test="java:file-exists($filename, base-uri())">
  <!-- ... -->
</xsl:if>

这至少适用于 Saxon 9.1.0.5J — 尚未使用任何其他 XSLT 处理器对其进行测试。

注意:如果您要检查其存在的文件是 XML 文件并且您正在使用 XSLT2,您还可以使用内置doc-available()函数:

<xsl:if test="doc-available('hello_world.xml')">
  <!-- ... -->
</xsl:if>
于 2013-01-14T17:53:53.760 回答
10

不,这不能使用 XSLT 2.0/XPath 2.0 完成。

XSLT 2.0 函数unparsed-text-available()仅适用于定位文本文件,即使存在具有指定 URI 的文本文件,此函数也可能返回 false(),因为它还必须读取文件的内容并检查它只包含允许的字符。

规格

“未解析文本可用函数确定对具有相同参数的未解析文本函数的调用是否会返回字符串。

如果第一个参数是空序列,则函数返回 false。如果第二个参数是一个空序列,则函数的行为就像第二个参数被省略一样。

在其他情况下,如果对具有相同参数的未解析文本的调用成功,则该函数返回 true;如果对具有相同参数的未解析文本的调用失败并出现不可恢复的动态错误,则该函数返回 false。

笔记:

这要求 unparsed-text-available 函数实际上应该尝试读取由 URI 标识的资源,并检查它是否正确编码并且不包含 XML 中的无效字符"

报价结束。

于 2010-05-27T01:25:58.497 回答
3

如果其他人需要它并且正在使用 fop,我想分享这个答案,因为它对我很有用。

我找到了一个解决方案:

<xsl:when test="fs:exists(fs:new('myfile.html'))" xmlns:fs="java.io.File">
    <!-- do something here... -->
</xsl:when>

它独立于 XSLT 1.0 或 2.0 工作

于 2015-09-02T18:57:46.277 回答
2

编辑:使用unparsed-text-available function。它是xslt 2.0的一部分,但不是 XQuery 或独立 XPath。

我已经在这里留下了我之前的答案,所以你可以追踪不确定性......

我不相信在 XSLT 中使用标准函数可以做到这一点。您可以使用扩展函数来完成此操作,如此处所述适用于 java。

unparsed-text-available函数,但我不确定这是否是标准函数。在Zvon有一个使用示例。这里提到的 unparsed-text-available 是xslt 2.0 的一部分,并且在 Saxon 中受支持。

于 2010-05-27T00:02:21.240 回答
2

提议的文件模块 EXPath 规范将支持文件系统函数,例如(file:exists()在规范中)作为标准 XPath 扩展函数。目前还没有针对此的 XSLT 实现,但值得一看。

于 2010-05-27T09:19:32.917 回答
1

回到 pgfearo 的通知。

提议的文件模块 EXPath 规范将支持文件系统函数,例如这个(规范中的 file:exists())作为标准 XPath 扩展函数。目前还没有针对此的 XSLT 实现,但值得一看。

对于那些需要检查文件是否存在的人。

file:exists($path as xs:string)

现在工作正常。

于 2017-09-14T12:46:50.860 回答
1

如果您仍然想在 XSLT 中执行此操作,这是解决方案,我已经为自己完成了,如下所述。

这不适用于 XSLT 中的常规java.io.File类。所以我使用了java.nio.file.Files类。

需要 JARS - servelt.jar w: 是我们自己的 Java 类的命名空间,其中定义了 pathFromURI 方法。

代码:

<xsl:variable name="fileURI" select="u:new($absoluteFilePath)" xmlns:u="java:java.net.URI"/>
<xsl:variable name="filePathFromURI" select="w:pathFromURI($fileURI)"/>
<xsl:variable name="fileNotExist" select="not(files:exists($filePathFromURI, /..)) or files:size($filePathFromURI) = 0"/>

public static java.nio.file.Path pathFromURI(java.net.URI uri) throws Exception {
    return java.nio.file.Paths.get(uri);
}
于 2019-01-30T07:02:11.657 回答
0

它不能仅由标准 XSLT 完成,您必须使用扩展功能或一些烦人的解决方法。有两种使用扩展函数的方法:将标准 java/.NET 用于自定义函数(适用于 Saxon、AltovaXML 等的某些版本),或使用特定于处理器的扩展函数,如 saxon:file-last-modified() /撒克逊:最后修改()你可以在这里找到一些示例代码,寻找 intern:file-exists()。

如果您不能使用扩展功能,您可以在外部生成一个 XML 文件,其中包含有关您的文件系统的信息并将其传递给您的样式表,或者您可以将二进制图像包装在 SVG 中,而不是使用 fn:doc-available()。

于 2011-11-05T09:00:17.640 回答
0

如果您需要检查 XML 文件是否存在,请使用外部实体和内联文档类型:

<!DOCTYPE foo [ <!ENTITY bar SYSTEM "baz.xml"> ]>

然后将实体添加到样式表中:

&bar;

如果找不到文件,处理器将超时。

如果您知道文件存在但想动态加载其中一个,请使用该concat函数和一个choose/when块:

<xsl:variable name="page_name">
<xsl:choose>
  <xsl:when test="$page = 1">
    <xsl:value-of select="'page1.xml'"/>
  </xsl:when>
  <xsl:when test="$page = 2">
    <xsl:value-of select="'page2.xml'"/>
  </xsl:when>
  <!--...-->
  <xsl:when test="$page = 9">
    <xsl:value-of select="'page9.xml'"/>
  </xsl:when>
  <xsl:when test="$page = 10">
    <xsl:value-of select="'page10.xml'"/>
  </xsl:when>
  <xsl:otherwise>
    <xsl:value-of select="'page0.xml'"/>
  </xsl:otherwise>
</xsl:choose>
</xsl:variable>

<xsl:variable name="agree" select="document(concat('include/pages/',$page_name))//processing-instruction()"/>

参考

于 2013-09-12T06:49:35.097 回答
0

对于任何需要普通 XSLT 解决方案来检查文件是否存在的人,您可以使用

unparsed-text-available(concat(system-property('user.dir'),'/filename.text'))

或将其包装成一个函数

<xsl:function name="functx:file-exists" xmlns:functx="http://www.functx.com">
    <xsl:param name="path"/>
    <xsl:value-of select="unparsed-text-available(concat(system-property('user.dir'),'/',$path))"/>
</xsl:function>

使用它unparsed-text-available(concat(system-property('user.dir'),'/filename.text'))=false()意味着该文件不存在。

玩得开心!

于 2020-02-27T14:42:50.050 回答