1

一部の XSLT 変換で問題が発生しました。私の XML データには、次のような座標要素がいくつかあります。

XML:

[...]
<polygon some="attributes">
  <coordinates>
    <point>(8.234/9.435)</point>
    <point>(2.456/5.678)</point>
    [...]
  </coordinates>
</polygon>
[...]

等々。の値は、x および y 座標 (x/y) を表します。ここで、特定の座標セットから x OR y の最大値または最小値を取得する必要があります。

c++ コードで msxml を使用しているため、min() および max() 関数に XSLT 2.0 または XPath 2.0 を使用できません。

形式 (x/y) は静的であり、プログラムの出力であるため、変更することもできません。

私はこのようにXSLTでそれをやろうとしました:

XSLT:

<xsl:template name="getMinOf"> <!--this one is getting nodeset, min/max, x/y params-->
  <xsl:for-each select="$nodeSet"> <!--in this case "//polygon/coordinates/point"-->
    *<xsl:choose>
      <xsl:when test="$MinOrMax = 'min' ">
        <xsl:choose>
          <xsl:when test="$XorY = 'x'">*
        <xsl:sort select="substring-before(substring-after(.,'('),'/')" data-type="number" order="ascending"/> <!--Here is my problem-->
              <xsl:if test="position() = 1">
                <xsl:value-of select="." /><!--  return xMin -->
              </xsl:if>
          </xsl:when>
      [...]
</xsl:template>

select=" substring-before(substring-after(.,'('),'/')"は、( と / の間の部分、x 座標を取得する必要があります。

<!--this one does return the x value.-->
<xsl:value-of select="substring-before(substring-after(.,'('),'/')"/>

だから...私の問題を理解し、助けてくれることを願っています。私はさらに先に進む方法がわかりません。ありがとう。

編集:目的の出力を忘れました。次のようになります。

<polygon>
  <xMin>2.456</xMin>
  <xMax>8.234</xMax>
  <yMin>5.678</yMin>
  <yMax>9.435</yMax>
</polygon>
4

1 に答える 1

0

質問には記載されていませんが、あなたの問題は、「Keyword xsl:sort may not be used here.」というメッセージが表示されることだと推測しています。これは、xsl:sortがxsl:when内にネストされているために発生します。 xsl:for-eachの直下

パラメータに基づいて、事実上、条件付きソートを実行しようとしています。1 つの条件は、x 座標または y 座標のどちらでソートするか、もう 1 つは昇順または降順のどちらでソートするかです。

順序付けについては、「昇順」または「降順」のいずれかを保持する変数を定義し、それによって並べ替えることができます。

  <xsl:variable name="order">
     <xsl:choose>
        <xsl:when test="$MinOrMax='max'">descending</xsl:when>
        <xsl:otherwise>ascending</xsl:otherwise>
     </xsl:choose>
  </xsl:variable>
  <xsl:for-each select="coordinates/point">
     <xsl:sort select="substring-before(substring-after(.,'('),'/')" data-type="number" order="{$order}"/>

次の問題は、パラメータに基づいて「x」または「y」座標を選択する方法です。1 つの方法として、xsl:chooseを使用して並べ替え方法を選択することができます。

  <xsl:choose>
     <xsl:when test="$XorY='x'">
        <xsl:for-each select="coordinates/point">
           <xsl:sort select="substring-before(substring-after(.,'('),'/')" data-type="number" order="{$order}"/>
           <xsl:if test="position() = 1">
              <xsl:value-of select="substring-before(substring-after(.,'('),'/')"/>
           </xsl:if>
        </xsl:for-each>         
     </xsl:when>
     <xsl:otherwise>
        <xsl:for-each select="coordinates/point">
           <xsl:sort select="substring-before(substring-after(.,'/'),')')" data-type="number" order="{$order}"/>
           <xsl:if test="position() = 1">
              <xsl:value-of select="substring-before(substring-after(.,'/'),')')"/>
           </xsl:if>
        </xsl:for-each>         
     </xsl:otherwise>
  </xsl:choose>

ただし、この潜在的なコードの重複を回避し、単一のxsl:for-each を持つ方法があります。ソートのためにこれを試してください

     <xsl:sort select="concat(
          substring(substring-before(substring-after(.,'('),'/'), 1, 100 * ($XorY = 'x')), 
          substring(substring-before(substring-after(.,'/'),')'), 1, 100 * ($XorY = 'y')))" 
       data-type="number" order="{$order}"/>

($XorY = 'x')これは、式で が 0 または 1 に評価されるという事実を利用しています。さらに理解するために、次の 2 つの式を効果的に連結しています。

substring(<x co-ordinate>, 1, 100 * <0 or 1>)
substring(<y co-ordinate>, 1, 100 * <0 or 1>)

$XorY = 'x' の場合は 1 が返されるため、最初の部分文字列 (x 座標) は完全な文字列を返しますが、2 番目の部分文字列は空の文字列を返します。$XorY = 'y' の場合は逆で、2 番目の部分文字列 (y 座標) が返されます。

このXSLTを試してください

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="polygon">
      <polygon>
         <xMin>
            <xsl:call-template name="getMinOf">
               <xsl:with-param name="MinOrMax" select="'min'" />
               <xsl:with-param name="XorY" select="'x'" />
            </xsl:call-template>   
         </xMin>
         <xMax>
            <xsl:call-template name="getMinOf">
               <xsl:with-param name="MinOrMax" select="'max'" />
               <xsl:with-param name="XorY" select="'x'" />
            </xsl:call-template>   
         </xMax>
         <yMin>
            <xsl:call-template name="getMinOf">
               <xsl:with-param name="MinOrMax" select="'min'" />
               <xsl:with-param name="XorY" select="'y'" />
            </xsl:call-template>   
         </yMin>         
         <yMax>
            <xsl:call-template name="getMinOf">
               <xsl:with-param name="MinOrMax" select="'max'" />
               <xsl:with-param name="XorY" select="'y'" />
            </xsl:call-template>   
         </yMax>
      </polygon>
   </xsl:template>

   <xsl:template name="getMinOf">
      <xsl:param name="MinOrMax"/>
      <xsl:param name="XorY"/>
      <xsl:variable name="order">
         <xsl:choose>
            <xsl:when test="$MinOrMax='max'">descending</xsl:when>
            <xsl:otherwise>ascending</xsl:otherwise>
         </xsl:choose>
      </xsl:variable>
      <xsl:for-each select="coordinates/point">
         <xsl:sort select="concat(substring(substring-before(substring-after(.,'('),'/'), 1, 100 * ($XorY = 'x')), substring(substring-before(substring-after(.,'/'),')'), 1, 100 * ($XorY = 'y')))" data-type="number" order="{$order}"/>
         <xsl:if test="position() = 1">
            <xsl:value-of select="concat(substring(substring-before(substring-after(.,'('),'/'), 1, 100 * ($XorY = 'x')), substring(substring-before(substring-after(.,'/'),')'), 1, 100 * ($XorY = 'y')))"/>
         </xsl:if>
      </xsl:for-each>
   </xsl:template>

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

サンプル XML に適用すると、次のように出力されます。

<polygon>
   <xMin>2.456</xMin>
   <xMax>8.234</xMax>
   <yMin>5.678</yMin>
   <yMax>9.435</yMax>
</polygon>
于 2012-10-25T08:31:47.190 に答える