2

私は XSLT にかなり慣れていませんが、XSLT を介して特定のノード セットを表示する XML ファイルを取得しようとしています。XSL 1.0 を使用しています。xml は次のようになります。

<...>
  <entry>
    <organizer>
      <component>
        <observation>
          <code displayName="Weight" />
          <effectiveTime value="5/21/2013 12:00:00 AM" />
          <value value="75" unit="lbs" />
        </observation>
      </component>
    </organizer>
  </entry>
  <entry>
    <organizer>
      <component>
        <observation>
          <code displayName="BMI" />
          <effectiveTime value="5/21/2013 12:00:00 AM" />
          <value value="14.6" unit="98" />
        </observation>
      </component>
    </organizer>
  </entry>
  <entry>
    <organizer>
      <component>
        <observation>
          <code displayName="Weight" />
          <effectiveTime value="5/20/2013 12:00:00 AM" />
          <value value="255" unit="lbs" />
        </observation>
      </component>
    </organizer>
  </entry>
  <entry>
    <organizer>
      <component>
        <observation>
          <code displayName="BMI" />
          <effectiveTime value="5/20/2013 12:00:00 AM" />
          <value value="49.8" unit="98" />
        </observation>
      </component>
    </organizer>
  </entry>
  <entry>
    <organizer>
      <component>
        <observation>
          <code displayName="Blood Pressure" />
          <effectiveTime value="5/20/2013 12:00:00 AM" />
          <value value="100/76" unit="mm Hg" />
        </observation>
      </component>
    </organizer>
  </entry>
</...>

出力を次のように表示したいのは、次のようなものです。

<table>
  <tr>
    <td>5/21/2013</td>
    <td>&nbsp;</td>
    <td>Weight: 75lbs</td>
    <td>BMI: 14.6 90</td>
  </tr>
  <tr>
    <td>5/20/2013</td>
    <td>Blood Pressure: 100/76 mm Hg</td>
    <td>Weight: 255lbs</td>
    <td>BMI: 49.8 90</td>
  </tr>
</table>

基本的には、(観測ノード内の) effectiveTime でグループ化し、血圧、体重、および BMI を後続の列に入れます。また、その特定の日付に特定のコード表示名が存在しない場合は、空白のテーブル セルが必要です (最初の日付にリストされていない血圧を参照してください)。

助けてくれてありがとう。XSLTを拾っているのですが、量が多すぎて時間がかかってしまいます。

4

3 に答える 3

0

これは、XSLT 1.0 を使用したソリューションのバージョンです ... フィールド名の変数を使用するのではなく、それぞれの列処理をコーディングしました。

T:\ftemp>type entries.xml 
<entries>
  <entry>
    <organizer>
      <component>
        <observation>
          <code displayName="Weight" />
          <effectiveTime value="5/21/2013 12:00:00 AM" />
          <value value="75" unit="lbs" />
        </observation>
      </component>
    </organizer>
  </entry>
  <entry>
    <organizer>
      <component>
        <observation>
          <code displayName="BMI" />
          <effectiveTime value="5/21/2013 12:00:00 AM" />
          <value value="14.6" unit="98" />
        </observation>
      </component>
    </organizer>
  </entry>
  <entry>
    <organizer>
      <component>
        <observation>
          <code displayName="Weight" />
          <effectiveTime value="5/20/2013 12:00:00 AM" />
          <value value="255" unit="lbs" />
        </observation>
      </component>
    </organizer>
  </entry>
  <entry>
    <organizer>
      <component>
        <observation>
          <code displayName="BMI" />
          <effectiveTime value="5/20/2013 12:00:00 AM" />
          <value value="49.8" unit="98" />
        </observation>
      </component>
    </organizer>
  </entry>
  <entry>
    <organizer>
      <component>
        <observation>
          <code displayName="Blood Pressure" />
          <effectiveTime value="5/20/2013 12:00:00 AM" />
          <value value="100/76" unit="mm Hg" />
        </observation>
      </component>
    </organizer>
  </entry>
</entries>
T:\ftemp>call xslt entries.xml entries1.xsl 
<table>
   <tr>
      <td>5/21/2013</td>
      <td>&nbsp;</td>
      <td>Weight: 75 lbs</td>
      <td>BMI: 14.6 98</td>
   </tr>
   <tr>
      <td>5/20/2013</td>
      <td>Blood Pressure: 100/76 mm Hg</td>
      <td>Weight: 255 lbs</td>
      <td>BMI: 49.8 98</td>
   </tr>
</table>
T:\ftemp>type entries1.xsl 
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

<xsl:output method="html"/>

<xsl:key name="times" match="entry"
         use="organizer/component/observation/effectiveTime/@value"/>

<xsl:template match="entries">
  <!--create the table-->
  <table>
    <!--grouped by time-->
    <xsl:for-each select="entry[generate-id(.)=
  generate-id(key('times',
                  organizer/component/observation/effectiveTime/@value)[1])]">
      <tr>
        <!--subset of time-->
        <td>
          <xsl:value-of select="substring-before(
                  organizer/component/observation/effectiveTime/@value,' ')"/>
        </td>
        <!--the fields in order-->
        <xsl:variable name="values" 
          select="key('times',
                      organizer/component/observation/effectiveTime/@value)/
                  organizer/component/observation"/>
        <xsl:choose>
          <xsl:when test="$values/code[@displayName='Blood Pressure']">
            <td>
              <xsl:for-each
                select="$values[code/@displayName='Blood Pressure']">
                <xsl:value-of 
          select="concat('Blood Pressure: ',value/@value,' ',value/@unit)"/>
              </xsl:for-each>
            </td>
          </xsl:when>
          <xsl:otherwise><td>&#xa0;</td></xsl:otherwise>
        </xsl:choose>
        <xsl:choose>
          <xsl:when test="$values/code[@displayName='Weight']">
            <td>
              <xsl:for-each
                select="$values[code/@displayName='Weight']">
                <xsl:value-of 
                    select="concat('Weight: ',value/@value,' ',value/@unit)"/>
              </xsl:for-each>
            </td>
          </xsl:when>
          <xsl:otherwise><td>&#xa0;</td></xsl:otherwise>
        </xsl:choose>
        <xsl:choose>
          <xsl:when test="$values/code[@displayName='BMI']">
            <td>
              <xsl:for-each
                select="$values[code/@displayName='BMI']">
                <xsl:value-of 
                  select="concat('BMI: ',value/@value,' ',value/@unit)"/>
              </xsl:for-each>
            </td>
          </xsl:when>
          <xsl:otherwise><td>&#xa0;</td></xsl:otherwise>
        </xsl:choose>
      </tr>
    </xsl:for-each>
  </table>
</xsl:template>
</xsl:stylesheet>
T:\ftemp>rem Done! 
于 2013-08-15T17:38:28.487 に答える
0
<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <xsl:output method="html" indent="yes" />

  <xsl:key name="kObservationByTime" match="observation" use="effectiveTime/@value" />

  <xsl:template match="/">
    <table>
      <tr>
        <th>Time</th>
        <th>Blood Pressure</th>
        <th>Weight</th>
        <th>BMI</th>
      </tr>
      <xsl:apply-templates mode="group" select="
        *//observation[
          generate-id() 
          =
          generate-id(key('kObservationByTime', effectiveTime/@value)[1])
        ][position() &gt; last() - 3]
      " />
        <xsl:sort select="effectiveTime/@value" order="descending" />
      </xsl:apply-templates>
    </table>
  </xsl:template>

  <xsl:template match="observation" mode="group">
    <xsl:variable name="time" select="effectiveTime/@value" />
    <xsl:variable name="thisGroup" select="key('kObservationByTime', $time)" />

    <tr>
      <td><xsl:value-of select="substring-before($time, ' ')" /></td>
      <td><xsl:apply-templates select="$thisGroup[code[@displayName = 'Blood Pressure']]" /></td>
      <td><xsl:apply-templates select="$thisGroup[code[@displayName = 'Weight']]" /></td>
      <td><xsl:apply-templates select="$thisGroup[code[@displayName = 'BMI']]" /></td>
    </tr>
  </xsl:template>

  <xsl:template match="observation">
    <xsl:value-of select="normalize-space(concat(value/@value, ' ', value/@unit))" />
  </xsl:template>
</xsl:stylesheet>

あなたにあげる

<table>
<tr>
<th>Time</th>
<th>Blood Pressure</th>
<th>Weight</th>
<th>BMI</th>
</tr>
<tr>
<td>5/21/2013</td>
<td></td>
<td>75 lbs</td>
<td>14.6 98</td>
</tr>
<tr>
<td>5/20/2013</td>
<td>100/76 mm Hg</td>
<td>255 lbs</td>
<td>49.8 98</td>
</tr>
</table>

http://www.xmlplayground.com/O9Z9DT

このソリューションでは、<xsl:key>グループ化に を使用します。

述語は[position() &gt; last() - 3]、表示する最後の 2 つのグループを選択します。代替手段 は[position() &lt; 3]、最初の 2 つを選択します。どちらもドキュメントの順序で機能しますが、<xsl:sort>出力順序にのみ影響します。

日付フォーマットの選択が賢明でないため、きれいなコードでは結果を賢明に順序付けることはできないことに注意してください。

エントリを日付順にソートするためのきれいでないコードは、次のようになります。

<xsl:sort select="
  concat(
    substring-after(substring-after(substring-before(effectiveTime/@value, ' '), '/'), '/'),
    '-',
    10 + substring-before(effectiveTime/@value, '/'),
    '-',
    10 + substring-before(substring-after(effectiveTime/@value, '/'), '/')
  )
" order="descending" />

... または、適切な日付形式を使用するだけで、問題はなくなります。;)

于 2013-08-15T17:31:27.053 に答える