В настоящее время я преобразовываю xml в html с таблицей стилей xslt. Я использую VS Code с расширением XSLT/XPath и использую tasks.json для преобразования. Он отлично работает для одного файла xml, но на самом деле у меня есть несколько файлов, для которых применяется один и тот же шаблон, и все они должны быть в одном файле html.
Мои рабочие tasks.json для одного файла:
{
"version": "2.0.0",
"tasks": [
{
"type": "xslt-js",
"label": "Saxon-JS Transform (Briefe)",
"xsltFile": "briefe/tei_to_html.xsl",
"xmlSource": "briefe/3690096/3690096.xml",
"resultPath": "edition.html",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$saxon-xslt-js"
]
}
]
}
Я пытался использовать подстановочные знаки для источника "briefe/**/*.xml"
, что приводит к ошибке: Не удалось прочитать исходный ввод XML (Не удалось прочитать ... /briefe/**/*.xml (нет такого файла))
Массив файлов (их всего несколько, поэтому я мог ввести их все) невозможен, потому что xmlSource принимает только строку.
Я полагаю, что могу обрабатывать несколько файлов xml в своей таблице стилей с помощью for-each и document, но как мне указать несколько файлов в качестве источника в моей задаче?
Обновлять:
Цель состоит в том, чтобы обработать несколько XML-файлов с помощью одного XSLT и создать один результирующий файл.
Я понял, что могу передать json в качестве источника:
...
"useJsonSource": true,
"xmlSource": "briefe/list.json",
...
Я пытаюсь выяснить, могу ли я обработать json в xslt, и это решение.
Ваша задача может вызвать команду расширения VS Code для предоставления необходимого списка файлов. Как специалист по сопровождению используемого вами расширения, я рассмотрю вопрос о добавлении этой функции к существующим командам «filePick» (выбирающим только один файл) для XSLT, задокументированным по адресу: deltaxml.github.io/vscode-xslt-xpath. /run-xslt.html#references
@pgfearo filePick - это тихий и аккуратный способ, только что проверил его (с одним файлом) из любопытства :)
Предполагая, что list.json
, например. массив строк с именами файлов ["file1.xml", "file2.xml", "file3.xml"]
ваш XSLT 3 будет обрабатывать, например.
<xsl:template match = ".[. instance of array(xs:string)]">
<xsl:apply-templates select = "?*!doc(.)"/>
</xsl:template>
В зависимости от остальной части вашей таблицы стилей вы можете захотеть вывести структуру HTML-документа вокруг этого xsl:apply-templates
, например.
<xsl:template match = ".[. instance of array(xs:string)]">
<html>
<head>
<title>Example</title>
</head>
<body>
<xsl:apply-templates select = "?*!doc(.)"/>
</body>
</html>
</xsl:template>
Хотя SaxonJS, безусловно, имеет опцию -json
для обработки входного файла JSON, я не проверял, как это хорошо взаимодействует с задачей xslt-js
в VS Code, поэтому будьте готовы поэкспериментировать, как это работает.
Из командной строки вы запустите, например. xslt3 -json:list.json -xsl:xslt.xsl
чтобы list.json
содержал массив JSON со строкой имен файлов, обработанных таблицей стилей xslt.xsl
, где шаблон, показанный выше, соответствовал бы этому массиву и помещал бы каждый файл с именем в качестве узла документа, созданного с помощью функции doc
, в любой из ваших других шаблонов.
Другой вариант - передать имена файлов в качестве глобального параметра и начать с именованного шаблона name = "xsl:initial-template"
, вариант -it
сделать, например.
<?xml version = "1.0" encoding = "utf-8"?>
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
version = "3.0"
xmlns:xs = "http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes = "#all"
expand-text = "yes">
<xsl:param name = "file-names" as = "xs:string*" select = "'file1.xml', 'file2.xml', 'file3.xml'"/>
<xsl:template name = "xsl:initial-template">
<html>
<head>
<title>Example</title>
</head>
<body>
<xsl:apply-templates select = "$file-names!doc(.)"/>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
задача xslt-js имеет «useJsonSouce», который, если установлено «true», обрабатывает свойство «XmlSource» как путь/URI JSON при вызове SaxonJS через командную строку — используя -json: вместо -xsl:
@pgfearo, спасибо, есть ли возможность начать с именованного шаблона xsl:initial-template
вместо любого источника XML или JSON?
да, это свойство InitialTemplate. Редактор задач JSON будет жаловаться, если нет свойства XmlSouce, но задача все равно будет выполняться.
Я изучаю возможность добавления команды выбора нескольких файлов, которая могла бы предоставлять значения file-names
в задаче Visual Studio Code. Существующие команды предназначены только для выбора одного файла и предлагают пользователю выбрать файл: deltaxml.github.io/vscode-xslt-xpath/run-xslt.html#references
Я пробовал другие способы заставить это работать. Например, я оставил свой xmlSource
таким же и объявил переменную в своей таблице стилей с коллекцией, содержащей папку со всеми xml-файлами: <xsl:variable name = "letter" select = "collection('letters')"/>
(этот подход работает в Oxygen XML Editor, и я могу перебирать все файлы с for-each и создавать несколько html с результирующим документом, но не с VS Code). Я также попытался создать отдельный xml с коллекцией и использовать его как xmlSource
. Результат: Error FODC0002 at multi.xsl#7 Unknown collection (no collectionFinder supplied)
@sleepyhead, я боюсь, что с точки зрения коллекций SaxonJS не так прост в использовании, как Saxon Java, я бы посоветовал начать с чтения раздела о collectionFinder
в saxonica.com/saxon-js/documentation2/index.html# !api/transform, не уверен, насколько легко интегрировать это с вашим кодом, запускаемым расширением кода VS. Возможно, поднимите эту проблему с коллекцией как другой вопрос.
@MartinHonnen, ваш последний комментарий был на самом деле последним кусочком головоломки. большое спасибо!
Я решил эту задачу созданием коллекции в отдельном файле letters.xml
и использовал его как xmlSource
.
Коллекция:
<?xml version = "1.0" encoding = "UTF-8"?>
<?xml-model href = "http://www.w3.org/2001/XMLSchema"?>
<collection stable = "true">
<doc href = "letter_1.xml"/>
<doc href = "letter_2.xml"/>
</collection>
С последним комментарием я переключился с xslt-js на xslt, потому что использование xslt-js не было обдуманным решением.
Мои задачи.json:
{
"version": "2.0.0",
"tasks": [
{
"type": "xslt",
"label": "xslt: Saxon Transform (Briefe Ebner-Eschenbach)",
"saxonJar": "SaxonHE11-3J/saxon-he-11.3.jar",
"xsltFile": "tei_to_html.xsl",
"xmlSource": "letters.xml",
"resultPath": "index.html",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$saxon-xslt"
]
}
]
}
В моем tei_to_html.xsl
я использую коллекцию в переменной и создаю страницы для писем:
<xsl:variable name = "letters" select = "collection('briefe.xml')"/>
[...]
<xsl:for-each select = "$letters">
<xsl:result-document href = "{concat('letter_', position(),'.html')}" method = "html">
<xsl:call-template name = "letter_page"/>
</xsl:result-document>
</xsl:for-each>
Всем спасибо за помощь и участие! Я определенно многому научился.
Чего вы хотите достичь, запустить один XSLT один раз, обрабатывая несколько входных файлов вместе, чтобы создать один файл результата, или запустить один и тот же XSLT для нескольких входных файлов, чтобы создать несколько файлов результатов?