如何使用XSL检查外部文件是否存在?

时间:2010-05-26 23:54:08

标签: xslt document external xsl-fo exists

我发现了许多引用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"/>

我想做的是,在{$SMSname}.jpg行中加入“if”语句。那就是:

                     <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。我希望这是可以做到的。我希望它更简单。

一如既往,提前感谢任何帮助。 LO

10 个答案:

答案 0 :(得分:10)

对于任何可能偶然发现这个老问题的人,通过拼接互联网上各种来源的信息,我想出了这个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>

答案 1 :(得分:9)

不,使用XSLT 2.0 / XPath 2.0无法做到这一点。

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

来自 spec

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

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

在其他情况下,如果对具有相同参数的unparsed-text的调用成功,则该函数返回true;如果对具有相同参数的unparsed-text调用将因不可恢复的动态错误而失败,则该函数返回false。 p>

注意:

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

报价结束。

答案 2 :(得分:2)

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

我已将此前的答案留在此处,以便您可以追踪不确定性......

我不相信有一种方法可以使用标准函数在XSLT中执行此操作。您可以使用扩展函数来执行此操作,如{。{3}}所述,适用于java。

here函数,但我不确定这是否是标准函数。在unparsed-text-available有一个例子。未解析的文本可用作为xslt 2.0的一部分被提及Zvon,并且在Saxon中受支持。

答案 3 :(得分:2)

建议的File Module EXPath specification将支持文件系统函数,例如(规范中的file:exists())作为标准XPath扩展函数。目前还没有针对此的XSLT实现,但值得关注。

答案 4 :(得分:2)

如果其他人需要它并使用fop,我想分享this answer,因为它对我来说就像一个魅力。

我找到了解决方案:

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

,它独立于XSLT 1.0或2.0

答案 5 :(得分:1)

回到pgfearo的通知。

  

建议的文件模块EXPath规范将支持文件系统   诸如此类的函数(规范中的文件:exists())作为标准XPath   扩展功能。目前还没有针对此的XSLT实现,   但值得关注。

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

file:exists($path as xs:string)

现在工作正常。

答案 6 :(得分:0)

它不能单独通过标准XSLT完成,您必须使用扩展功能或一些恼人的解决方法。有两种使用扩展函数的方法:使用标准java / .NET进行自定义函数(适用于某些版本的Saxon,AltovaXML等),或使用特定于处理器的扩展函数,如saxon:file-last-modified() / saxon:last-modified()。您可以找到一些示例代码here,查找实习生:file-exists()。

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

答案 7 :(得分:0)

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

<!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()"/>

<强>参考

答案 8 :(得分:0)

如果您仍然想在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);
}

答案 9 :(得分: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()表示该文件不存在。

玩得开心!