在 XSLT 中实现键值概念



我正在研究XSLT,我需要实现如下内容。我的源 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>

任何人都可以帮我解决这个问题。

谢谢。

I.

简单的 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 的子元素)包含在内联 XML 节点的标准方法,该元素属于不同于 xsl 命名空间的(非空)命名空间。


II. 更高效的 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()函数的第三个参数是指定要使用的索引树。

相关内容

  • 没有找到相关文章