2

我在创建地图时看到了类似的问题。

该答案具有以下代码:

<xsl:stylesheet version="1.0" 
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:template match="/">
    <xsl:variable name="map">
        <map>
            <entry key="key-1">value1</entry>
            <entry key="key-2">value2</entry>
            <entry key="key-3">value3</entry>
        </map>
    </xsl:variable>
    <output>
        <xsl:value-of select="msxsl:node-set($map)/map/entry[@key='key-1']"/>
    </output>
</xsl:template>

我想替换输出命令以在我的 XML 中使用一个值,以查看它是否是映射中的键,然后用该值替换它。

在地图上进行 for-each 选择并与包含进行比较的最佳方法是什么?

这是 XML 的一个片段:

<document>
   <content name="PART_DESC_SHORT" type="text" vse-streams="2" u="22" action="cluster" weight="1">
   SCREW - ADJUST
   </content>
</document>

内容节点值可能有一个包含我想用完整值替换的缩写的字符串。

谢谢,保罗

4

1 回答 1

2

无需使用for-each- 这个 XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt">

  <xsl:output indent="yes" method="xml" />

  <xsl:variable name="abbreviations">
    <abbreviation key="Brkt Pivot R">Bracket Pivot R</abbreviation>
    <abbreviation key="Foo">Expanded Foo</abbreviation>
    <abbreviation key="Bar">Expanded Bar</abbreviation>
  </xsl:variable>

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="text()">
    <xsl:variable name="text" select="."/>
    <xsl:variable name="abbreviation" select="msxsl:node-set($abbreviations)/*[@key=$text]"/>
    <xsl:choose>
      <xsl:when test="$abbreviation">
        <xsl:value-of select="$abbreviation"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:copy/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>

将在精确副本中转换任何 XML,扩展abbreviations与顶部变量中定义的缩写匹配的所有文本。

如果您只想在特定元素内扩展缩写,您可以修改第二个模板match="..."规则。

另一方面,如果您想扩展文本中所有缩写的任何出现,您需要循环 - 这意味着 XSLT 中的递归:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt">

  <xsl:output indent="yes" method="xml" />

  <xsl:variable name="abbreviations">
    <abbreviation key="Brkt">Bracket</abbreviation>
    <abbreviation key="As">Assembly</abbreviation>
    <abbreviation key="Foo">Expanded Foo</abbreviation>
    <abbreviation key="Bar">Expanded Bar</abbreviation>
  </xsl:variable>

  <!-- Replaces all occurrences of a string with another within a text -->
  <xsl:template name="replace">
    <xsl:param name="text"/>
    <xsl:param name="from"/>
    <xsl:param name="to"/>
    <xsl:choose>
      <xsl:when test="contains($text,$from)">
        <xsl:value-of select="concat(substring-before($text,$from),$to)"/>
        <xsl:call-template name="replace">
          <xsl:with-param name="text" select="substring-after($text,$from)"/>
          <xsl:with-param name="from" select="$from"/>
          <xsl:with-param name="to" select="$to"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$text"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- Replace all occurences of a list of abbreviation with their expanded version -->
  <xsl:template name="replaceAbbreviations">
    <xsl:param name="text"/>
    <xsl:param name="abbreviations"/>
    <xsl:choose>
      <xsl:when test="count($abbreviations)>0">
        <xsl:call-template name="replaceAbbreviations">
          <xsl:with-param name="text">
            <xsl:call-template name="replace">
              <xsl:with-param name="text" select="$text"/>
              <xsl:with-param name="from" select="$abbreviations[1]/@key"/>
              <xsl:with-param name="to" select="$abbreviations[1]"/>
            </xsl:call-template>
          </xsl:with-param>
          <xsl:with-param name="abbreviations" select="$abbreviations[position()>1]"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$text"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="text()">
    <xsl:call-template name="replaceAbbreviations">
      <xsl:with-param name="text" select="."/>
      <xsl:with-param name="abbreviations" select="msxsl:node-set($abbreviations)/*"/>
    </xsl:call-template>
  </xsl:template>

</xsl:stylesheet>

将第二个 XSLT 应用于

<document>
  <content name="PART_DESC_SHORT" type="text" vse-streams="2" u="22" action="cluster" weight="1">
    Brkt Pivot R
  </content>
</document>

生产

<document>
  <content name="PART_DESC_SHORT" type="text" vse-streams="2" u="22" action="cluster" weight="1">
    Bracket Pivot R
  </content>
</document>

注意:

  • 此解决方案假定没有缩写 ovlap(例如,两个单独的缩写BrkBrkt

  • 它使用 XSLT 1.0 - XSLT 2.0 可能有更好的解决方案

  • 这种繁重的字符串处理在 XSLT 中可能效率很低,最好用其他语言编写扩展函数并从 XSLT 中调用它。

于 2012-05-09T19:07:02.503 回答