Несколько преобразований XSL в сегмент XML-документа

#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
        }
    )
 

https://xqueryfiddle.liberty-development.net/3Nzd8c2