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 選択を行い、contains と比較する最良の方法はありますか?

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>

abbreviations上部の変数で定義された略語に一致するすべてのテキストを展開する正確なコピーで XML を変換します。

match="..."特定の要素内でのみ略語を展開する場合は、2 番目のテンプレートルールを変更できます。

一方、テキスト内のすべての略語を展開したい場合は、ループが必要です。これは、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>

この 2 番目の 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>

ご了承ください:

  • このソリューションでは、省略形が重複していないことを前提としています (たとえば、2 つの別個の省略形BrkBrkt) 。

  • XSLT 1.0 を使用しています - XSLT 2.0 を使用すると、おそらくより良い解決策が可能です。

  • この種の重い文字列処理は、XSLT では非常に効率が悪い可能性があります。おそらく、他の言語で拡張関数を作成し、XSLT から呼び出す方がよいでしょう。

于 2012-05-09T19:07:02.503 に答える