XSLT: Как получить имена файлов из определенного каталога?

Есть ли функция в XSLT, которая может принимать путь к каталогу и возвращает все файлы в нем?

У меня есть xml файл, который теперь читается как

<filelist>
    <file>fileA.xml</file>
    <file>fileB.xml</file>
</filelist>

Теперь, там каталог под названием dir, имеет файлы fileX.xml, fileY.xml и множество других xml файлов. Я хочу добавить эти файлы в исходный xml файл, чтобы я мог получить:

<filelist>
    <file>fileA.xml</file>
    <file>fileB.xml</file>
    <file>fileX.xml</file>
    <file>fileY.xml</file>
    .... <!-- other files -->
</filelist>

Есть ли способ XSLT? что-то, что принимает в корне dir, и умеет итератор через все файлы в нем?? И тогда я мог бы просто называть что-то вроде:

<xsl:element name = file >
     <xsl:copy> <!--whatever file name--> <xsl:copy>
</xsl:element>0

[Редактировать-решение]

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

Я использую Ant для создания веб-приложения java и вам нужно перевести некоторые XML файлы перед развертыванием. Следовательно, я использовал задачу xslt для выполнения задания, добавив "saxon9.jar" в путь к классам. И в моем файле xsl я просто сделал что-то вроде этого:

<xsl:for-each select="collection('../dir/?select=*.xml')" >
     <xsl:element name='file'>
        <xsl:value-of select="tokenize(document-uri(.), '/')[last()]"/>
     </xsl:element>
</xsl:for-each>

Ответы

Ответ 1

XSLT не имеет ничего встроенного для этой задачи. XSLT - это язык преобразования - для динамического вывода вам обычно нужен источник преобразования, который содержит все уже (только в другой форме) – вы не можете создавать XML из ничего.

Три способа решения этой проблемы:

  • Постройте XML на языке программирования, полностью исключая XSLT. Это самый простой способ получить желаемый результат.
  • Создайте таблицу стилей XSL, которая принимает параметр, поместите (предварительно созданный) список файлов в этот параметр, пусть XSLT обрабатывает строку и делает XML из нее. Это также связано с внешней обработкой, в основном это вариант 1. Кроме того, вам нужно будет написать таблицу стилей XSL, которая выполняет обработку строк (что-то, к чему XSL не был привязан)
  • Используйте функции расширения и выполните обработку каталога из XSL. Пример, как начать, можно найти в моем ответе на этот вопрос. Это не очень портативно, поскольку функции расширения являются специфичными для платформы.

Это сводится к следующему:

  • Вам понадобится помощь с внешнего языка программирования.
  • Вам не нужно, чтобы XSLT выполнял задачу, так как вывод XML - это все, что вам нужно, и преобразование не требуется.

Ergo: Не используйте XSL для этого.

Ответ 2

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

Например, в С# вы можете добавить пользовательский URN:

 <xsl:stylesheet {snipped the usual xmlns stuff}
    xmlns:user="urn:user" >

затем используйте функции внутри пользователя

  <xsl:value-of select="user:getdirectory( @mydir )" />

внутри С# вы связываете "пользователь" с классом С#:

 XSLThelper xslthelper      = new XSLThelper( );  // your class here
 xslArgs.AddExtensionObject( "urn:user", xslthelper );

и ваш класс определяет функцию "getdirectory":

public class XSLThelper
{
public string getdirectory(System.Xml.XPath.XPathNavigator xml, string strXPath, string strNULL)
{
       //blah
    }
}

Хью количество домашних заданий осталось здесь! Ресурс MSDN

Ответ 3

Q шесть лет и ответили. Просто бросайте мои 2 цента за тех, кто приземляется здесь снова.

Мне нужен XML файл, представляющий имена файлов в каталоге. Я сделал это тремя способами:

  • Документ XSLT 2.0(), как указывали другие участники в этом потоке. Недостатком является производительность, поскольку он читает файл в парсере dom, когда все, что вам действительно нужно, - это имя. Кроме того, как указывал LarsH в комментариях к OP, это работает только с действительными XML файлами. Если в рекурсии есть файл, отличный от xml или malformed xml, он сбрасывает преобразование.

  • Инструмент xmlstarlet с помощью команды xmlstarlet ls > filenames.xml

  • Грубый bash script Я составил (его можно было оптимизировать):

DIRECTORY=$1
RESULTFILE=$2

# put the directory listing into a temp file
# modify the ls command for your needs
ls -A1 $DIRECTORY > /tmp/zFiles.txt

# remove detritus and wrap the lines in <file> elements
sed -i -e's/^[^$]*$/   <file filename="&"\/>/' /tmp/zFiles.txt

# build the file
echo '<?xml version="1.0" encoding="UTF-8"?>' > $RESULTFILE
echo "<files>" >> $RESULTFILE
cat /tmp/zFiles.txt >> $RESULTFILE
echo "</files>" >> $RESULTFILE

Я использовал bash script в течение длительного времени, но теперь я использую только метод xmlstarlet. Результат файла звездочки содержит определенные атрибуты файла, такие как разрешения и даты, я нашел это полезным.

Ответ 4

Вы можете использовать функцию document() для чтения XML файлов. Я не уверен, насколько это хорошо поддерживается на разных XSLT-машинах.

Это хороший пример, показывающий его использование.

Но это не касается проблемы чтения в именах файлов из каталога. Другой ответ дает способ сделать эту сторону.