XSLT 1.0 值查找映射
XSLT 1.0 Value look up Map
我是 XSLT 的新手,花了相当多的时间来掌握创建一个内联查找映射以将特定值替换为 XSLT 2.0 中映射列表的另一个值,结果发现我可以只使用 1.0。 :-(
我的问题是如何在 1.0 中复制以下有效的 XSLT 2.0 代码。我尝试了一些方法,但似乎无法正常工作。
需要注意的是,如果没有地图,则该元素应该为空。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:variable name="mapxml" >
<map>
<Country>
<input value="GB">RZ</input>
<input value="FR">TH</input>
</Country>
</map>
</xsl:variable>
<xsl:variable name="vMap"
select="$mapxml" />
<xsl:key name="kInputByVal" match="input"
use="@value" />
<xsl:template match="Country/text()">
<xsl:sequence select=
"(key('kInputByVal', ., $vMap/*/Country)[1]/text()
)[1]
"/>
</xsl:template>
</xsl:stylesheet>
输入XML:
<user>
<Country>GB</Country>
<Name>FOO</Name>
<Address>BAR</Address>
<user>
这是等效的 XSLT 1.0 程序:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="http://tempuri.org/dummy"
exclude-result-prefixes="my"
>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*" />
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<my:config>
<map>
<Country>
<input value="GB">RZ</input>
<input value="FR">TH</input>
</Country>
</map>
</my:config>
<xsl:variable name="vCountryMap" select="document('')/*/my:config/map/Country/input" />
<xsl:template match="Country/text()">
<xsl:value-of select="$vCountryMap[@value = current()]" />
</xsl:template>
</xsl:stylesheet>
备注:
- 您可以在 XSLT 中设置额外的节点,因为 XSLT 本身就是 XML。例如配置数据,就像这里一样。您只需要确保为它们使用不同的命名空间。
- 命名空间 URI 需要是唯一的,它们不需要指向现有文档。像
http://tempuri.org/dummy
这样的临时 URI 是完全没问题的。
<xsl:strip-space elements="*" />
指示 XSLT 处理器忽略输入中无关紧要的空格。这有助于创建整齐缩进的输出。
document('')
指的是 XSLT 样式表本身。如果需要,您还可以将配置保存在额外的 XML 文件中。
exclude-result-prefixes
防止我们的临时命名空间泄漏到输出。
current()
指 XSLT 处理器当前正在处理的节点。 ($vCountryMap[@value = .]
不起作用,因为这里的 .
指的是 XPath 上下文,即 <input>
节点。)
XSLT 1.0 中的键仅在当前文档中起作用。为了使用键从样式表本身查找,您必须在使用键之前将上下文切换到样式表:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="http://example.com/my"
exclude-result-prefixes="my">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="input-by-value" match="input" use="@value" />
<my:map>
<input value="GB">RZ</input>
<input value="FR">TH</input>
</my:map>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Country/text()">
<xsl:variable name="value" select="." />
<!-- switch context to stylesheet in order to use key -->
<xsl:for-each select="document('')">
<xsl:value-of select="key('input-by-value', $value)"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
我是 XSLT 的新手,花了相当多的时间来掌握创建一个内联查找映射以将特定值替换为 XSLT 2.0 中映射列表的另一个值,结果发现我可以只使用 1.0。 :-(
我的问题是如何在 1.0 中复制以下有效的 XSLT 2.0 代码。我尝试了一些方法,但似乎无法正常工作。
需要注意的是,如果没有地图,则该元素应该为空。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:variable name="mapxml" >
<map>
<Country>
<input value="GB">RZ</input>
<input value="FR">TH</input>
</Country>
</map>
</xsl:variable>
<xsl:variable name="vMap"
select="$mapxml" />
<xsl:key name="kInputByVal" match="input"
use="@value" />
<xsl:template match="Country/text()">
<xsl:sequence select=
"(key('kInputByVal', ., $vMap/*/Country)[1]/text()
)[1]
"/>
</xsl:template>
</xsl:stylesheet>
输入XML:
<user>
<Country>GB</Country>
<Name>FOO</Name>
<Address>BAR</Address>
<user>
这是等效的 XSLT 1.0 程序:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="http://tempuri.org/dummy"
exclude-result-prefixes="my"
>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*" />
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<my:config>
<map>
<Country>
<input value="GB">RZ</input>
<input value="FR">TH</input>
</Country>
</map>
</my:config>
<xsl:variable name="vCountryMap" select="document('')/*/my:config/map/Country/input" />
<xsl:template match="Country/text()">
<xsl:value-of select="$vCountryMap[@value = current()]" />
</xsl:template>
</xsl:stylesheet>
备注:
- 您可以在 XSLT 中设置额外的节点,因为 XSLT 本身就是 XML。例如配置数据,就像这里一样。您只需要确保为它们使用不同的命名空间。
- 命名空间 URI 需要是唯一的,它们不需要指向现有文档。像
http://tempuri.org/dummy
这样的临时 URI 是完全没问题的。 <xsl:strip-space elements="*" />
指示 XSLT 处理器忽略输入中无关紧要的空格。这有助于创建整齐缩进的输出。document('')
指的是 XSLT 样式表本身。如果需要,您还可以将配置保存在额外的 XML 文件中。exclude-result-prefixes
防止我们的临时命名空间泄漏到输出。current()
指 XSLT 处理器当前正在处理的节点。 ($vCountryMap[@value = .]
不起作用,因为这里的.
指的是 XPath 上下文,即<input>
节点。)
XSLT 1.0 中的键仅在当前文档中起作用。为了使用键从样式表本身查找,您必须在使用键之前将上下文切换到样式表:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="http://example.com/my"
exclude-result-prefixes="my">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="input-by-value" match="input" use="@value" />
<my:map>
<input value="GB">RZ</input>
<input value="FR">TH</input>
</my:map>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Country/text()">
<xsl:variable name="value" select="." />
<!-- switch context to stylesheet in order to use key -->
<xsl:for-each select="document('')">
<xsl:value-of select="key('input-by-value', $value)"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>