【问题标题】:XSLT 1.0 Value look up MapXSLT 1.0 值查找图
【发布时间】:2015-09-07 13:08:18
【问题描述】:

我是 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>

【问题讨论】:

    标签: xml xslt xslt-1.0 xslt-2.0


    【解决方案1】:

    这是等效的 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 完全没问题。
    • &lt;xsl:strip-space elements="*" /&gt; 指示 XSLT 处理器忽略输入中无关紧要的空白。这有助于创建整齐的缩进输出。
    • document('') 指的是 XSLT 样式表本身。如果您愿意,也可以将配置保存在一个额外的 XML 文件中。
    • exclude-result-prefixes 防止我们的临时命名空间泄漏到输出。
    • current() 指的是 XSLT 处理器当前正在处理的节点。 ($vCountryMap[@value = .] 不起作用,因为这里的 . 指的是 XPath 上下文,即 &lt;input&gt; 节点。)

    【讨论】:

    • 感谢@Tomalak 的快速回答和解释 - 这很有效,可以帮助我准确了解发生了什么:-)
    • 看看@michael.hor257k 的回答,因为他加倍努力获得工作的钥匙。我考虑过使用密钥来完成这项任务,所以我将它从我的解决方案中删除,但当然可以保留它。如果您有非常多的映射和非常大的输入文档(大约有数千个节点),则使用密钥将显着提高性能。如果您的输入通常很小,那不会有太大的不同。
    【解决方案2】:

    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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      • 2022-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多