Вот пример использования процессора XSLT 3, поддерживающего xsl:evaluate
(https://www.w3.org/TR/xslt-30/#dynamic-xpath) (т. Е. Saxon 9.8 или более поздней версии с коммерческими выпусками PE или EE или Altova 2017 или более поздней версии) для обработки файла «config»:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="#all"
version="3.0">
<xsl:param name="config-url" as="xs:string">test2018121301.xml</xsl:param>
<xsl:param name="config-doc" select="doc($config-url)"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:key name="element" match="*" use="node-name()"/>
<xsl:function name="mf:config-evaluation" as="item()*">
<xsl:param name="config-doc" as="document-node()"/>
<xsl:param name="element-name" as="xs:QName"/>
<xsl:variable name="display" select="key('element', $element-name, $config-doc)/DisplayName"/>
<xsl:evaluate xpath="$display/regex" with-params="map:merge($display!(* except regex)!map { QName('', local-name()) : string() })"/>
</xsl:function>
<xsl:template match="*[key('element', node-name(), $config-doc)]">
<xsl:copy>
<xsl:value-of select="mf:config-evaluation($config-doc, node-name()), ."/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
То есть с config.xml
<Location >
<DisplayName>
<Attribute1>ABC</Attribute1>
<Attribute2>XYZ</Attribute2>
<regex>concat($Attribute1,$Attribute2)</regex>
</DisplayName>
</Location >
это преобразовало бы входной сэмпл, например, с
<Root>
<Items>
<Item>
<Data>data 1</Data>
<Location>location 1</Location>
</Item>
<Item>
<Data>data 2</Data>
<Location>location 2</Location>
</Item>
</Items>
</Root>
в
<Root>
<Items>
<Item>
<Data>data 1</Data>
<Location>ABCXYZ location 1</Location>
</Item>
<Item>
<Data>data 2</Data>
<Location>ABCXYZ location 2</Location>
</Item>
</Items>
</Root>
Это дает вам большую гибкость, позволяя использовать выражения XPath в файлах конфигурации, но, как указано в https://www.w3.org/TR/xslt-30/#evaluate-effect,, также является проблемой безопасности: «Авторы таблиц стилей должны знать о рисках безопасности, связанных с использованием xsl: define. Инструкция не должна использоваться для выполнения кода из ненадежного источника. ".
Что касается использования функции saxon:evaluate
, поддерживаемой в более старых версиях Saxon, не поддерживающей инструкцию XSLT 3 xsl:evaluate
, aпростой пример -
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:saxon="http://saxon.sf.net/"
exclude-result-prefixes="#all"
version="2.0">
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="example">
<xsl:copy>
<xsl:value-of select="saxon:evaluate(@expression, @foo, @bar)"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
, который преобразует входные данные
<root>
<example expression="concat($p1, $p2)" foo="This is " bar="an example."/>
<example expression="replace(., $p1, $p2)" foo="\p{L}" bar="X">This is example 2.</example>
</root>
в результат
<root>
<example>This is an example.</example>
<example>XXXX XX XXXXXXX 2.</example>
</root>