#xml #web #xslt
Вопрос:
Я преобразую XML — файлы с помощью XSL. Моя основная настройка-это «общий» файл XSL, который содержит стандартные процессы для всех файлов и несколько более специфичных таблиц стилей, которые работают с различными типами/классами документов. Общий лист импортируется в конкретные листы, и конкретные листы фактически выполняются.
Иногда мне нужно, чтобы некоторые XML-документы преобразовывали вещи иначе, чем это обычно делается в общем файле. Очень простой, урезанный пример приведен ниже:
XML
<data>
<name>John</name>
<age>25</age>
</data>
«Обычный» XSL (common.xsl)
<xsl:template match="//data">
<h1><xsl:value-of select="name" /></h1>
<div>Age: <xsl:value-of select="age" /></div>
</xsl:template>
Конкретный/выполненный XSL
<xsl:import href="common.xsl />
<!-- The following have not worked, but are two attempts at making this work-->
<!-- Attempt 1-->
<xsl:template match="//h1">
<p>My name is <xsl:value-of select="." />!</p>
</xsl:template>
<!-- Attempt 2-->
<xsl:template match="//data">
<p>My name is <xsl:value-of select="name" />!</p>
</xsl:template>
Основываясь на моей первоначальной отладке, кажется, что проблема в том, что вторые преобразования не находят никаких элементов для преобразования. Потенциально я мог бы переместить соответствующий код из общего файла в конкретные и/или использовать инструкции xsl:choose, чтобы предотвратить его запуск в определенных документах. Тем не менее, я хотел бы найти более чистое решение (если возможно), которое позволило бы мне добавить дополнительный бит в конкретную таблицу стилей, которая мне нужна, и не нужно изменять какие-либо другие таблицы стилей. Я также изучал конвейерную обработку XSL, но я не смог понять, как это работает в данном случае.
Заранее благодарим вас за любую помощь!
Комментарии:
1. Таблица стилей XSLT, независимо от того, как она построена, работает с входным XML, а не с собственными продуктами. Если вы хотите создать несколько узлов, а затем обработать эти узлы дальше, вы можете сделать это, сохранив результат шага 1 в переменной, а затем применив шаблоны к переменной.
Ответ №1:
Я не понимаю, почему во втором примере не было бы данных для работы, я думаю, что вы скорее хотите
<xsl:template match="data">
<xsl:apply-imports/>
<p>My name is <xsl:value-of select="name" />!</p>
</xsl:template>
но это , безусловно, должно затем выводить h1
, div
из импортированного шаблона и p
из импортируемой таблицы стилей.
Что касается конвейерной обработки, вы можете сделать это с помощью XProc или с помощью XPath 3.1 , XQuery 3.1 или XSLT 3 fold-left
, transform
например, в XQuery 3.1 ваш первый образец может выглядеть так
let $xslt1 := <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">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="data">
<h1><xsl:value-of select="name" /></h1>
<div>Age: <xsl:value-of select="age" /></div>
</xsl:template>
</xsl:stylesheet>,
$xslt2 := <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">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="h1">
<p>My name is <xsl:value-of select="." />!</p>
</xsl:template>
</xsl:stylesheet>
let $xslts := ($xslt1, $xslt2)
return
fold-left(
$xslts,
.,
function($node, $xslt) {
transform(
map {
'source-node' : $node,
'stylesheet-node' : $xslt
}
)?output
}
)