Я адаптирую XSLT от третьей стороны, которая преобразует произвольное количество XML-файлов в один документ HTML. Это довольно сложный сценарий, и он будет пересмотрен в будущем, поэтому я стараюсь сделать минимальную адаптацию, чтобы заставить ее работать для наших нужд.XSLT: нужна альтернатива document() - функция для обработки с несколькими источниками
Ниже урезанная версия XSLT (содержащей необходимое):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
<xsl:output method="text" encoding="UTF-8" omit-xml-declaration="yes"/>
<xsl:param name="files" select="document('files.xml')//File"/>
<xsl:param name="root" select="document($files)"/>
<xsl:template match="/">
<xsl:for-each select="$root/RootNode">
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:template>
<xsl:template match="RootNode">
<xsl:for-each select="//Node">
<xsl:text>Node: </xsl:text><xsl:value-of select="."/><xsl:text>, </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Теперь files.xml
содержит список всех URL-адресов из файлов, которые будут включены (в этом случае локальные файлы file1.xml
и file2.xml
). Поскольку мы хотим читать XML-файлы из памяти, а не с диска, и потому что вызов XSLT допускает только один источник XML, я объединил эти два файла в одном документе XML. Ниже представляет собой комбинацию из двух файлов (может быть больше в реальной ситуации)
<?xml version="1.0" encoding="UTF-8"?>
<TempNode>
<RootNode>
<Node>1</Node>
<Node>2</Node>
</RootNode>
<RootNode>
<Node>3</Node>
<Node>4</Node>
</RootNode>
</TempNode>
где первый RootNode
первоначально проживали в file1.xml
и второй в file2.xml
. Из-за сложности реального XSLT, я понял, что мой лучший снимок - попытаться изменить $root
-param. Я пробовал следующее:
<xsl:param name="root" select="/TempNode"/>
Проблема в этом. В случае <xsl:param name="root" select="document($files)"/>
, выражение XPath "//Node"
в <xsl:for-each select="//Node">
выбирает узел от file1.xml
и file2.xml
независимо друг от друга, то есть производить следующее (по желанию) список:
Узел: 1, Узел: 2, Узел: 3, Узел: 4,
Однако, когда я объединить содержимое двух файлов в один XML и проанализировать это (и использовать предложенный $root
-Определение), выражение "//Node"
будет выбрать все ноды, которые являются детьми TempNode
. (Другими словами, требуемый список, как представлено выше, производится в два раза за счет комбинации с наружной <xsl:for-each select="$root/RootNode">
петли.)
(примечание стороны: как это наблюдалось в комментарии а) в this page, document()
по-видимому, изменяет корень узел, возможно, объясняет такое поведение)
Мой вопрос будет:. Как можно повторно определить $root
, используя комбинированный XML в качестве источника вместо нескольких источников через документ(), так что список производится только один раз, не касаясь остальной части XSLT? Это как если бы $root
, определяемый с помощью функции document()
, в параметре нет общего корневого узла. Можно ли определить параметр с двумя «отдельными» деревьями узлов?
Btw: Я попытался определение документа, как этот
<xsl:param name="root">
<xsl:for-each select="/TempNode/*">
<xsl:document>
<xsl:copy-of select="."/>
</xsl:document>
</xsl:for-each>
</xsl:param>
думая, что это может решить проблему, но выражение "//Node"
еще выбирает все узлы. Является ли узел контекста в файле <xsl:template match="RootNode">
-template фактически где-то во входном документе, а не параметром? (Честно говоря, я довольно смущен, когда дело доходит до контекстных узлов.)
Заранее спасибо!
+1 хороший вопрос, и, очевидно, хорошее внимание уделялось объяснению и форматированию описания проблемы. – LarsH
Спасибо LarsH! На мой взгляд, вы не получите хороший ответ, если вопрос не будет поставлен правильно. Я надеюсь, что это было не слишком раздутым. – conciliator