В конечном итоге мне нужно создать удобный способ чтения нескольких файлов конфигурации для управления обработкой сложного преобразования xsl (в настоящее время 2.0). Каждый файл конфигурации может иметь или не иметь конкретные узлы. Относительный приоритет существует между файлами конфигурации, и конечное значение для любого конкретного значения должно исходить из файла конфигурации с наивысшим приоритетом, в котором оно существует.
Простой файл конфигурации (so.xml) с одной переменной приведен ниже:
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="urn:config.template.config" >
<primary>Yes, this is primary</primary>
</config>
Старый метод: Я читаю один файл, устанавливая параметр взначение «primary» в одном файле конфигурации для узла «primary»:
<xsl:param name="primary" select="$primaryConfig/myConfig:config/myConfig:primary/text()"/>
Теперь: У меня может быть до четырех файлов конфигурации, которые может иметь«первичный» как значение. Для этого я решил написать два шаблона. pickConfigNode
- для поиска в файлах шаблонов (используя выбор для определения приоритетов чтения), чтобы узнать, запрошен ли узел со значением, содержащимся в 'level1'.
<xsl:template name="pickConfigNode">
<xsl:param name="level1"/>
<xsl:choose>
<xsl:when test="$primaryConfig/myConfig:config/*[local-name() = $level1]">
<xsl:value-of select="$primaryConfig/myConfig:config/*[local-name() = $level1]"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$secondaryConfig/myConfig:config/*[local-name() = $level1]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Это работает достаточно хорошо для меня , пока значение существует в некотором файле конфигурации (показывается при поиске основного и дополнительного). Однако возможно, что значение нигде не определено. Я думаю, что я хотел бы, чтобы возвращалась пустая последовательность, что происходит, если узел не существует с старым методом . Однако я, возможно, неправильно понимаю что-то о том, как работает *, когда ничего не найдено.
pickConfigNode
возвращает частичный документ. Таким образом, это приводит к проблемам с pickConfigText
:
<xsl:template name="pickConfigText" as="xs:string">
<xsl:param name="level1"/>
<xsl:variable name="chosenNode">
<xsl:call-template name="pickConfigNode">
<xsl:with-param name="level1" select="$level1"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$chosenNode/text()"/>
</xsl:template>
Вот дополнительный файл:
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="urn:config.template.config" >
<onlySecondary>from secondary</onlySecondary>
<primary>No, this is secondary</primary>
</config>
Вот полный тестовый пример, который использует два файла конфигурации:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:myConfig="urn:config.template.config"
xpath-default-namespace="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="myConfig xs"
>
<xsl:output method="xml" omit-xml-declaration="no" indent="yes" encoding="us-ascii" cdata-section-elements="p i b u li"/>
<xsl:variable name="configFile" select="'so.xml'"/>
<xsl:variable name="primaryConfig" select="document($configFile)"/>
<xsl:variable name="secondaryConfig" select="document('second.xml')"/>
<xsl:template name="pickConfigNode">
<xsl:param name="level1"/>
<xsl:choose>
<xsl:when test="$primaryConfig/myConfig:config/*[local-name() = $level1]">
<xsl:value-of select="$primaryConfig/myConfig:config/*[local-name() = $level1]"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$secondaryConfig/myConfig:config/*[local-name() = $level1]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="pickConfigText" as="xs:string">
<xsl:param name="level1"/>
<xsl:variable name="chosenNode">
<xsl:call-template name="pickConfigNode">
<xsl:with-param name="level1" select="$level1"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$chosenNode/text()"/>
</xsl:template>
<xsl:param name="primary">
<xsl:call-template name="pickConfigText">
<xsl:with-param name="level1" select="'primary'"/>
</xsl:call-template>
</xsl:param>
<xsl:param name="onlySecondary">
<xsl:call-template name="pickConfigText">
<xsl:with-param name="level1" select="'onlySecondary'"/>
</xsl:call-template>
</xsl:param>
<xsl:param name="neither">
<xsl:call-template name="pickConfigText">
<xsl:with-param name="level1" select="'neither'"/>
</xsl:call-template>
</xsl:param>
<xsl:template match="/">
<PRIMARY>
<xsl:choose>
<xsl:when test="$primary"><SUCCESS><xsl:value-of select="$primary"/></SUCCESS></xsl:when>
<xsl:otherwise>
<FAILURE>
<xsl:value-of select="'No value for primary'"/>
</FAILURE>
</xsl:otherwise>
</xsl:choose>
</PRIMARY>
<SECONDARY>
<xsl:choose>
<xsl:when test="$onlySecondary"><SUCCESS><xsl:value-of select="$onlySecondary"/></SUCCESS></xsl:when>
<xsl:otherwise>
<FAILURE>
<xsl:value-of select="'No value for onlySecondary'"/>
</FAILURE>
</xsl:otherwise>
</xsl:choose>
</SECONDARY>
<NEITHER>
<xsl:choose>
<xsl:when test="not($neither)"><SUCCESS>NOT in either file</SUCCESS></xsl:when>
<xsl:otherwise>
<FAILURE>
<xsl:value-of select="'Got value of for neither='"/>
<xsl:value-of select="$neither"/>
</FAILURE>
</xsl:otherwise>
</xsl:choose>
</NEITHER>
</xsl:template>
</xsl:stylesheet>
Вывод:
<?xml version="1.0" encoding="us-ascii"?>
<PRIMARY>
<SUCCESS>Yes, this is primary</SUCCESS>
</PRIMARY>
<SECONDARY>
<SUCCESS>from secondary</SUCCESS>
</SECONDARY>
<NEITHER>
<FAILURE>Got value of for neither=</FAILURE>
</NEITHER>
Итак, я хочу, чтобы результат НИКОГДА не был "УСПЕХ".
Благодарим Вас за помощь в понимании моего неправильного представления об обработке xslt. Кроме того, если у вас есть альтернативный подход к обработке приоритетных файлов конфигурации, я бы тоже хотел это услышать.