Как проверить наличие внешнего файла с XSL?

Я нашел много примеров, которые ссылаются на 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. Я надеюсь, что это то, что можно сделать. Я надеюсь, что еще больше, что это что-то простое.

Как всегда, заблаговременно за помощь. LO

Ответы

Ответ 1

Нет, это невозможно сделать с помощью XSLT 2.0/XPath 2.0.

Функция XSLT 2.0 unparsed-text-available() подходит только для поиска текстовых файлов и даже если текстовый файл с указанным URI существует, эта функция может возвращать false(), поскольку она также должна читать содержимое файла и проверять, что оно содержит только допустимые символы.

Из spec:

"Функция, недоступная для текста, определяет, будет ли вызов функции unparsed-text с идентичными аргументами возвращать строку.

Если первый аргумент представляет собой пустую последовательность, функция возвращает false. Если второй аргумент представляет собой пустую последовательность, функция ведет себя так, как если бы второй аргумент был опущен.

В других случаях функция возвращает true, если вызов непараметрированного текста с теми же аргументами будет успешным, а false, если вызов с непараметрированным текстом с теми же аргументами завершится неудачей с невосстановимой динамической ошибкой.

Примечание:

Для этого требуется, чтобы функция, не содержащая абзацев, действительно пыталась прочитать ресурс, идентифицированный URI, и проверить, что он правильно закодирован и не содержит символов, которые недействительны в XML "

Конец цитаты.

Ответ 2

Для всех, кто может наткнуться на этот старый вопрос, собрав информацию из разных источников в Интернете, я придумал эту функцию 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>

Ответ 3

EDIT: используйте функция unparsed-text-available. Это часть xslt 2.0, но не XQuery или автономный XPath.

Я оставил свой предыдущий ответ здесь, чтобы вы могли следить за следствием неопределенности...

Я не верю, что есть способ сделать это в XSLT, используя стандартные функции. Вы можете сделать это с помощью функций расширения, как описано здесь, для java.

Существует функция unparsed-text-available, но я не уверен, что это стандартная функция. Там пример использования: Zvon. Доступный unparsed-text упоминается здесь как часть xslt 2.0 и поддерживается в Saxon.

Ответ 4

Предлагаемая File Module EXPath спецификация будет поддерживать такие функции файловой системы, как эта (file:exists() в спецификации) в качестве стандартного расширения XPath функции. Для этого еще нет реализации XSLT, но стоит посмотреть.

Ответ 5

Если кому-то это понадобится и использует 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

Ответ 6

Это не может быть сделано только стандартным XSLT, вам нужно использовать функцию расширения или некоторое раздражающее обходное решение. Существует два метода использования функций расширения: использование стандартных java/.NET для пользовательских функций (работает с некоторыми версиями Saxon, AltovaXML и т.д.) Или использование функций расширения, специфичных для процессора, таких как saxon: file-last-modified()/saxon: last-modified(). Вы можете найти пример кода здесь, найдите intern: file-exists().

Если вы не можете использовать функции расширения, вы можете либо сгенерировать внешний файл XML файла, который содержит информацию о вашей файловой системе, и передать его в таблицу стилей, либо вы можете обернуть двоичные изображения в SVG и использовать fn: doc-available().

Ответ 7

Если вам нужно проверить наличие файла 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

Назад к уведомлению pgfearo.

Предлагаемая спецификация файла EXPath для файлового модуля будет поддерживать файловую систему такие функции, как это (файл: exists() в спецификации) в качестве стандартного XPath функции расширения. Для этого еще нет реализации XSLT, но его стоит посмотреть.

Для тех, кому необходимо проверить, существует ли файл.

file:exists($path as xs:string)

теперь работает нормально.

Ответ 9

Если вы все еще хотите сделать это в XSLT, вот решение, я сделал это для себя, как описано ниже.

Это не будет работать с обычным классом java.io.File в XSLT. Поэтому я использовал класс 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);
}