2

一部の XML 出力を評価テーブル (水文学関連) に変換しようとしています。これは、100 分の 1 の値が上を横切り、10 分の 1 の値が下になります。私が直面している問題は、ht属性の部分文字列を使用して一意の値をソートできないように見えることです。

XML 出力のサンプルを次に示します。

<env:Envelope>
<env:Header/>
<env:Body>
<RatingTableUpdate>      
  <Gauge xmlns="" type="STORAGE" id="123">
    <Input input="0">
      <Conv ht="19.76" cap="5040" />
      <Conv ht="19.77" cap="5045" />
      <Conv ht="19.78" cap="5051" />
      <Conv ht="19.79" cap="5057" />
      <Conv ht="19.80" cap="5063" />
      <Conv ht="19.81" cap="5069" />
      <Conv ht="19.82" cap="5074" />
      <Conv ht="19.83" cap="5080" />
      <Conv ht="19.84" cap="5086" />
      <Conv ht="19.85" cap="5092" />
      <Conv ht="19.86" cap="5098" />
      <Conv ht="19.87" cap="5104" />
      <Conv ht="19.88" cap="5109" />
      <Conv ht="19.89" cap="5115" />
      <Conv ht="19.90" cap="5121" />
      <Conv ht="19.91" cap="5127" />
      <Conv ht="19.92" cap="5133" />
      <Conv ht="19.93" cap="5138" />
    </Input>
  </Gauge>
</RatingTableUpdate>
</env:Body>
</env:Envelope>

出力は次のようになります。

GH    0.00  0.01  0.02  0.03  0.04  0.05  0.06  0.07  0.08  0.09
19.7                                      5040  5045  5051  5057  
19.8  5063  5069  5074  5080  5086  5092  5098  5104  5109  5115
19.9  5121  5127  5133  5138

正しい列で cap 属性を取得できますが、GH 列 (100 分の 1 の値が削除された ht 属性) を取得して、行ごとに 1 回だけ表示することはできません。私はこのようなものを得る:

GH    0.00  0.01  0.02  0.03  0.04  0.05  0.06  0.07  0.08  0.09
19.7                                      5040  
                                                5045  
                                                      5051  
                                                            5057  
19.8  5063  
            5069  
                  5074  
                        5080  
                              5086  
                                    5092  
                                          5098  
                                                5104  
                                                      5109  
                                                            5115
19.9  5121  
            5127  
                  5133  
                        5138

これが、このセクションをフォーマットする xsl の私のセクションです。xsl:choose は、列に対してうまく機能しているようです。Muenchian メソッドを試してみましたが、うまくいきません (部分文字列キーで機能させるのに苦労しています)。

これが最善の方法ですか、それとも、指定された部分文字列に対して各行を 1 回だけ表示する別の方法がありますか (19.76、19.77、19.78、19.79 の値に対して 19.7 回)? 評価は通常、例のようにゼロ以外の値から始まるため、100 番目の 0 の値を使用してグループを開始し、9 をグループの終了に使用することはできません。

<xsl:for-each select="env:Envelope/env:Body/RatingTableUpdate/Gauge">

<table width="100%">
<tr class="site">                           
  <td width="150px">Site ID: <u><xsl:value-of select="@id" /></u></td>
  <td>Site Name: <u><xsl:value-of select="@idname" /></u></td>
  <td>Type: <u><xsl:value-of select="@type" /></u></td>
</tr>   
</table>        

<table width="100%">
  <tr class="tbldata">
    <th rowspan="1" class="tbldataheader">GH</th>
    <th rowspan="1" class="tbldataheader">0.00</th>
    <th rowspan="1" class="tbldataheader">0.01</th>
    <th rowspan="1" class="tbldataheader">0.02</th>
    <th rowspan="1" class="tbldataheader">0.03</th>
    <th rowspan="1" class="tbldataheader">0.04</th>
    <th rowspan="1" class="tbldataheader">0.05</th>
    <th rowspan="1" class="tbldataheader">0.06</th>
    <th rowspan="1" class="tbldataheader">0.07</th>
    <th rowspan="1" class="tbldataheader">0.08</th>
    <th rowspan="1" class="tbldataheader">0.09</th>
  </tr>  

  <xsl:for-each select="./Input/Conv">
    <tr class="tbldata">

      <xsl:choose>
        <xsl:when test="substring(@ht,string-length(@ht),1) = 0">
          <td class="ifrtext"><xsl:value-of select="substring(@ht,1,string-length(@ht)-1)" /></td>
        </xsl:when>
        <xsl:otherwise>
          <td class="ifrtext"></td>
        </xsl:otherwise>
      </xsl:choose>
       <xsl:choose>
        <xsl:when test="substring(@ht,string-length(@ht),1) = 0">
          <td class="ifrtext"><xsl:value-of select="@cap" /></td>
        </xsl:when>
        <xsl:otherwise>
          <td class="ifrtext"></td>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:choose>
        <xsl:when test="substring(@ht,string-length(@ht),1) = 1">
          <td class="ifrtext"><xsl:value-of select="@cap" /></td>
        </xsl:when>
        <xsl:otherwise>
          <td class="ifrtext"></td>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:choose>
        <xsl:when test="substring(@ht,string-length(@ht),1) = 2">
          <td class="ifrtext"><xsl:value-of select="@cap" /></td>
        </xsl:when>
        <xsl:otherwise>
          <td class="ifrtext"></td>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:choose>
        <xsl:when test="substring(@ht,string-length(@ht),1) = 3">
          <td class="ifrtext"><xsl:value-of select="@cap" /></td>
        </xsl:when>
        <xsl:otherwise>
          <td class="ifrtext"></td>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:choose>
        <xsl:when test="substring(@ht,string-length(@ht),1) = 4">
          <td class="ifrtext"><xsl:value-of select="@cap" /></td>
        </xsl:when>
        <xsl:otherwise>
          <td class="ifrtext"></td>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:choose>
        <xsl:when test="substring(@ht,string-length(@ht),1) = 5">
          <td class="ifrtext"><xsl:value-of select="@cap" /></td>
        </xsl:when>
        <xsl:otherwise>
          <td class="ifrtext"></td>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:choose>
        <xsl:when test="substring(@ht,string-length(@ht),1) = 6">
          <td class="ifrtext"><xsl:value-of select="@cap" /></td>
        </xsl:when>
        <xsl:otherwise>
          <td class="ifrtext"></td>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:choose>
        <xsl:when test="substring(@ht,string-length(@ht),1) = 7">
          <td class="ifrtext"><xsl:value-of select="@cap" /></td>
        </xsl:when>
        <xsl:otherwise>
          <td class="ifrtext"></td>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:choose>
        <xsl:when test="substring(@ht,string-length(@ht),1) = 8">
          <td class="ifrtext"><xsl:value-of select="@cap" /></td>
        </xsl:when>
        <xsl:otherwise>
          <td class="ifrtext"></td>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:choose>
        <xsl:when test="substring(@ht,string-length(@ht),1) = 9">
          <td class="ifrtext"><xsl:value-of select="@cap" /></td>
        </xsl:when>
        <xsl:otherwise>
          <td class="ifrtext"></td>
        </xsl:otherwise>
      </xsl:choose>
    </tr>   
  </xsl:for-each>
</table>
</xsl:for-each>

ありがとう、マット

4

1 に答える 1

2

この変換:

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

 <xsl:key name="kValByTenths" match="Conv"
      use="substring(@ht, 1, 4)"/>

 <xsl:key name="kCapFromHt" match="@cap"
      use="../@ht"/>

 <xsl:template match="Input">
  <table>
   <xsl:for-each select=
    "Conv[generate-id()
         =
          generate-id(key('kValByTenths',substring(@ht, 1, 4))[1])
          ]">
     <xsl:variable name="vKey" select="substring(@ht, 1, 4)"/>
     <tr>
      <td><xsl:value-of select="$vKey"/></td>

      <xsl:for-each select=
       "(//node() | //namespace::*)[not(position() > 10)]">
        <xsl:variable name="vPos" select="position()"/>
        <td>
         <xsl:value-of select="key('kCapFromHt', concat($vKey,$vPos -1))"/>
        </td>
      </xsl:for-each>
     </tr>
    </xsl:for-each>
   </table>
 </xsl:template>
</xsl:stylesheet>

提供された XML ドキュメント(整形式の XML ドキュメントになるように修正) に適用した場合:

<env:Envelope xmlns:env="some:env">
    <env:Header/>
    <env:Body>
        <RatingTableUpdate>
            <Gauge xmlns="" type="STORAGE" id="123">
                <Input input="0">
                    <Conv ht="19.76" cap="5040" />
                    <Conv ht="19.77" cap="5045" />
                    <Conv ht="19.78" cap="5051" />
                    <Conv ht="19.79" cap="5057" />
                    <Conv ht="19.80" cap="5063" />
                    <Conv ht="19.81" cap="5069" />
                    <Conv ht="19.82" cap="5074" />
                    <Conv ht="19.83" cap="5080" />
                    <Conv ht="19.84" cap="5086" />
                    <Conv ht="19.85" cap="5092" />
                    <Conv ht="19.86" cap="5098" />
                    <Conv ht="19.87" cap="5104" />
                    <Conv ht="19.88" cap="5109" />
                    <Conv ht="19.89" cap="5115" />
                    <Conv ht="19.90" cap="5121" />
                    <Conv ht="19.91" cap="5127" />
                    <Conv ht="19.92" cap="5133" />
                    <Conv ht="19.93" cap="5138" />
                </Input>
            </Gauge>
        </RatingTableUpdate>
    </env:Body>
</env:Envelope>

必要な(装飾なしで)正しい結果を生成します:

<table>
   <tr>
      <td>19.7</td>
      <td/>
      <td/>
      <td/>
      <td/>
      <td/>
      <td/>
      <td>5040</td>
      <td>5045</td>
      <td>5051</td>
      <td>5057</td>
   </tr>
   <tr>
      <td>19.8</td>
      <td>5063</td>
      <td>5069</td>
      <td>5074</td>
      <td>5080</td>
      <td>5086</td>
      <td>5092</td>
      <td>5098</td>
      <td>5104</td>
      <td>5109</td>
      <td>5115</td>
   </tr>
   <tr>
      <td>19.9</td>
      <td>5121</td>
      <td>5127</td>
      <td>5133</td>
      <td>5138</td>
      <td/>
      <td/>
      <td/>
      <td/>
      <td/>
      <td/>
   </tr>
</table>

説明:

  1. 要素がその属性の文字列値の最初の 4 文字によってインデックス付けされるMuenchian グループ化方法の適切な使用。Convht

  2. N 回の非再帰反復に対するPiez メソッドの適切な使用。

更新

OP は、MSXML3 のバグにより、IE 8 を使用すると正しい結果が得られないと報告しています。

これは、MSXML3 / IE 8 でも問題なく動作する修正されたソリューションです。

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kValByTenths" match="Conv"
      use="substring(@ht, 1, 4)"/>

 <xsl:variable name="vConvs" select="//Conv"/>

 <xsl:template match="Input">
  <table>
   <xsl:for-each select=
    "Conv[generate-id()
         =
          generate-id(key('kValByTenths',substring(@ht, 1, 4))[1])
          ]">
     <xsl:variable name="vKey" select="substring(@ht, 1, 4)"/>
     <tr>
      <td><xsl:value-of select="$vKey"/></td>

      <xsl:for-each select=
       "(//node() | //namespace::*)[not(position() > 10)]">
        <xsl:variable name="vPos" select="position()"/>

        <td>
         <xsl:value-of select=
         "$vConvs[substring-after(@ht, $vKey) = $vPos]/@cap"/>
        </td>
      </xsl:for-each>
     </tr>
    </xsl:for-each>
   </table>
 </xsl:template>
</xsl:stylesheet>
于 2012-07-15T20:08:36.107 に答える