【问题标题】:Implementing Key Value Concept in XSLT在 XSLT 中实现键值概念
【发布时间】:2012-06-20 01:45:00
【问题描述】:

我正在研究 XSLT,我需要在其中实现以下内容。 我的 Source XML 示例如下所示。

<?xml version="1.0" encoding="ISO-8859-1"?>
    <catalog>
        <cd>
            <title>A</title>  
            <title>B</title>
            <title>C</title>  
        </cd>
    </catalog>

考虑有一些键值对列表。

    Key         Value
    A           Algebra
    B           Biology
    C           Chemistry
    D           Data Analysis
    ---         ---

    ----        ---

我需要编写一个 xslt,以便每次出现键“A”时,都需要用适当的值替换。

我还需要提到同一个 XSLT 中的键值对列表。 样本输出:

<Data>
    <Subject>Algebra</Subject>
    <Subject>Biology</Subject>
    <Subject>Chemistry</Subject>
 </Data>

谁能帮我看看怎么做。

谢谢。

【问题讨论】:

    标签: xslt xslt-1.0


    【解决方案1】:

    我。简单的 XSLT 1.0 解决方案

    这种转变

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:my="my:my">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>
    
     <my:codes>
       <code key="A" value="Algebra"/>
       <code key="B" value="Biology"/>
       <code key="C" value="Chemistry"/>
       <code key="D" value="Data Analysis"/>
     </my:codes>
    
     <xsl:template match="node()|@*">
      <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
     </xsl:template>
    
     <xsl:template match=
      "title/text()[. = document('')/*/my:codes/*/@key]">
    
      <xsl:value-of select=
       "document('')/*/my:codes/*[@key=current()]/@value"/>
     </xsl:template>
    </xsl:stylesheet>
    

    应用于提供的 XML 文档时:

    <catalog>
        <cd>
            <title>A</title>
            <title>B</title>
            <title>C</title>
        </cd>
    </catalog>
    

    产生想要的正确结果

    <catalog>
       <cd>
          <title>Algebra</title>
          <title>Biology</title>
          <title>Chemistry</title>
       </cd>
    </catalog>
    

    解释

    这是包含内联 XML 节点作为全局元素(xsl:stylesheet 的子元素)的标准方式,该元素属于(非空)命名空间,不同于 xsl 命名空间。


    二。更高效的 XSLT 1.0 解决方案,使用键

    <xsl:stylesheet version="1.0"
         xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
         xmlns:my="my:my">
         <xsl:output omit-xml-declaration="yes" indent="yes"/>
         <xsl:strip-space elements="*"/>
    
         <my:codes>
           <code key="A" value="Algebra"/>
           <code key="B" value="Biology"/>
           <code key="C" value="Chemistry"/>
           <code key="D" value="Data Analysis"/>
         </my:codes>
    
         <xsl:key name="kCodeByName" match="code" use="@key"/>
    
         <xsl:template match="node()|@*">
          <xsl:copy>
           <xsl:apply-templates select="node()|@*"/>
          </xsl:copy>
         </xsl:template>
    
         <xsl:template match=
          "title/text()[. = document('')/*/my:codes/*/@key]">
    
          <xsl:variable name="vCur" select="."/>
    
          <xsl:for-each select="document('')">
              <xsl:value-of select=
               "key('kCodeByName', $vCur)/@value"/>
          </xsl:for-each>
         </xsl:template>
    </xsl:stylesheet>
    

    当这个转换应用于同一个 XML 文档(上图)时,会产生同样正确的、想要的结果

    <catalog>
       <cd>
          <title value="Algebra"/>
          <title value="Biology"/>
          <title value="Chemistry"/>
       </cd>
    </catalog>
    

    解释

    通过key() 函数访问数据通常是次线性的——通常为 O(1),并且比线性搜索要快得多(如果要搜索的节点数量很大,这一点很重要)。

    如果包含要查找的节点的文档是当前文档,则可以在处理另一个文档的节点时通过索引 (xsl:key) 访问一个文档的节点。要从其他文档访问节点,它的根(或感兴趣的节点需要保存并从变量中引用。)


    三。 XSLT 2.0 解决方案

    <xsl:stylesheet version="2.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:my="my:my">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>
    
     <xsl:variable name="vCodes">
      <codes>
       <code key="A" value="Algebra"/>
       <code key="B" value="Biology"/>
       <code key="C" value="Chemistry"/>
       <code key="D" value="Data Analysis"/>
      </codes>
     </xsl:variable>
    
     <xsl:key name="kCodeByName" match="code" use="string(@key)"/>
    
     <xsl:template match="node()|@*">
      <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
     </xsl:template>
    
     <xsl:template match=
      "title/text()[key('kCodeByName', ., $vCodes)]">
    
      <xsl:sequence select=
       "key('kCodeByName', ., $vCodes)/@value"/>
     </xsl:template>
    </xsl:stylesheet>
    

    当这个转换应用于同一个 XML 文档(上图)时,会产生同样正确的、想要的结果

    <catalog>
       <cd>
          <title value="Algebra"/>
          <title value="Biology"/>
          <title value="Chemistry"/>
       </cd>
    </catalog>
    

    解释

    与高效的 XSLT 1.0 解决方案几乎相同,但是:

    1. 在 XSLT 2.0 中,模板匹配模式可以包含变量引用。

    2. 在 XSLT 2.0 中,不需要特技技巧来操纵当前和索引的文档——key() 函数的第三个参数是指定要使用其索引的树。

      李>

    【讨论】:

    • @Dimitre 我们可以调用解决方案 III 中的模板吗?另一个模板中的 XSLT 2.0。如果是,请告诉我怎么做?
    • 如何为每个循环创建具有动态键和值的键值数组?
    • @KishanPatadia,您需要更具体一些才能让别人准确理解您的要求。
    • @DimitreNovaatchev 我想通过迭代类别子节点来创建键值对。它具有 id 和 name 属性。我想使用 XSLT 将 id(key) 和 name(value) 存储为对(array)。
    • @KishanPatadia,请提出一个新问题,提供尽可能多的数据,包括输入、所需输出和所需的转换规则/限制。然后会有很多人能够提供帮助。
    猜你喜欢
    • 2014-07-15
    • 1970-01-01
    • 1970-01-01
    • 2022-11-02
    • 1970-01-01
    • 1970-01-01
    • 2017-05-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多