1

我有一个 xml 文件,其中包含一些正在输出的表中的数据,该表分为两列(有效)。这是 XML

<structuredBody>
  <component>
    <section>
      <templateId root="2.16.840.1.113883.10.20.22.2.3.1" />
      <entry>
        <organizer>
          <component>
            <observation>
              <code displayName="TIBC" />
              <effectiveTime value="8/29/2013 12:00:00 AM" />
              <value value="39" />
              <referenceRange>
                <observationRange>
                  <text />
                </observationRange>
              </referenceRange>
            </observation>
          </component>
        </organizer>
      </entry>
      <entry>
        <organizer>
          <component>
            <observation>
              <code displayName="TSAT" />
              <effectiveTime value="8/29/2013 12:00:00 AM" />
              <value value="25" />
              <referenceRange>
                <observationRange>
                  <text />
                </observationRange>
              </referenceRange>
            </observation>
          </component>
        </organizer>
      </entry>
      <entry>
        <organizer>
          <component>
            <observation>
              <code displayName="Albumin" />
              <effectiveTime value="9/5/2013 12:00:00 AM" />
              <value value="46" />
              <referenceRange>
                <observationRange>
                  <text />
                </observationRange>
              </referenceRange>
            </observation>
          </component>
        </organizer>
      </entry>
      <entry>
        <organizer>
          <component>
            <observation>
              <code displayName="ALT" />
              <effectiveTime value="9/5/2013 12:00:00 AM" />
              <value value="48" />
              <referenceRange>
                <observationRange>
                  <text>21-72</text>
                </observationRange>
              </referenceRange>
            </observation>
          </component>
        </organizer>
      </entry>
      <entry>
        <organizer>
          <component>
            <observation>
              <code displayName="Bicarbonate" />
              <effectiveTime value="9/5/2013 12:00:00 AM" />
              <value value="69" />
              <referenceRange>
                <observationRange>
                  <text />
                </observationRange>
              </referenceRange>
            </observation>
          </component>
        </organizer>
      </entry>
    </section>
  </component>
  <component>
    <section>
      <...>
    </section>
  </component>
  <component>
    <section>
      <...>
    </section>
  </component>
</structuredBody>

我已经使用 xslt 格式化了输出:

<xsl:template match="/">
    <xsl:if test="//section[templateId/@root='2.16.840.1.113883.10.20.22.2.3.1']!=''">
        <xsl:variable name="rowLabs" select="ceiling(count(//section[templateId/@root='2.16.840.1.113883.10.20.22.2.3.1']/entry) div $colLabs)" />

        <div style="margin-bottom: 5px; padding: 5px; border-bottom: 1px solid #000000;">
            <span style="font-weight: bold;">Lab Results:</span>
            <table border="0" cellspacing="0" cellpadding="1" width="99%" style="font-size: 11px;">
                <xsl:for-each select="//section[templateId/@root='2.16.840.1.113883.10.20.22.2.3.1']/entry[position() &lt;= $rowLabs]">
                    <tr>
                        <xsl:variable name="otherEntries" select=".|following-sibling::entry[position() mod $rowLabs = 0]" />
                        <xsl:apply-templates select="self::*|$otherEntries" />
                        <xsl:call-template name="blankentries">
                            <xsl:with-param name="entries" select="$colLabs - count($otherEntries) - 1" />
                        </xsl:call-template>
                        <!--<xsl:apply-templates select=".|following-sibling::entry[position() &lt; 2]" />-->
                    </tr>
                </xsl:for-each>
            </table>
        </div>
    </xsl:if>
</xsl:template>

<xsl:template match="section[templateId/@root='2.16.840.1.113883.10.20.22.2.3.1']/entry">
    <td width="75">
        <xsl:call-template name="StripTime">
            <xsl:with-param name="DateTime" select="organizer/component/observation/effectiveTime/@value" />
        </xsl:call-template>
    </td>
    <td width="198">
        <xsl:value-of select="organizer/component/observation/code/@displayName"/>
    </td>
    <td width="50">
        <xsl:value-of select="organizer/component/observation/value/@value"/>
    </td>
    <td width="75">
        <xsl:value-of select="organizer/component/observation/referenceRange/observationRange/text"/>
    </td>
</xsl:template>

<xsl:template name="blankentries">
    <xsl:param name="entries" />
    <xsl:if test="$entries > 0">
        <td></td>
        <xsl:call-template name="blankentries">
            <xsl:with-param name="entries" select="$entries - 1" />
        </xsl:call-template>
    </xsl:if>
</xsl:template>

以便生成的入口节点运行下来然后结束,以便输出为:

<table>
  <tr>
    <td>8/29/2013</td>
    <td>TIBC</td>
    <td>39</td>
    <td></td>
    <td>9/5/2013</td>
    <td>ALT</td>
    <td>48</td>
    <td>21-72</td>
  </tr>
  <tr>
    <td>8/29/2013</td>
    <td>TSAT</td>
    <td>25</td>
    <td></td>
    <td>9/5/2013</td>
    <td>Bicarbonate</td>
    <td>69</td>
    <td></td>
  </tr>
  <tr>
    <td>9/5/2013</td>
    <td>Albumin</td>
    <td>46</td>
    <td></td>
  </tr>
</table>

这给了我:

[entry 1] [entry 4]
[entry 2] [entry 5]
[entry 3]

这就是我正在寻找的东西,这很棒。

我想不通的是如何让不同的 4 单元条目集在它通过时交替显示颜色。我不能使用 position() 因为我正在操纵它以获得表中所需的输出顺序。如果我输出位置来计算数学,在左列,它总是“1”,在右列总是“2”,所以我不能做一个 position() mod 2 = 1 来设置样式属性.

其次,我只希望日期值出现一次,然后直到它发生变化才出现。这将使输出理想情况下应如下所示:

<table>
  <tr>
    <td>8/29/2013</td>
    <td>TIBC</td>
    <td>39</td>
    <td></td>
    <td bgcolor="dcdcdc"></td>
    <td bgcolor="dcdcdc">ALT</td>
    <td bgcolor="dcdcdc">48</td>
    <td bgcolor="dcdcdc">21-72</td>
  </tr>
  <tr>
    <td bgcolor="dcdcdc"></td>
    <td bgcolor="dcdcdc">TSAT</td>
    <td bgcolor="dcdcdc">25</td>
    <td bgcolor="dcdcdc"></td>
    <td></td>
    <td>Bicarbonate</td>
    <td>69</td>
    <td></td>
  </tr>
  <tr>
    <td>9/5/2013</td>
    <td>Albumin</td>
    <td>46</td>
    <td></td>
  </tr>
</table>

我不能将 bgcolor 属性放在“tr”标签中,因为它甚至应该在“列”之间交替,而不仅仅是整行。

谢谢你的帮助。这个网站给我带来了很长的 xslt 知识。我上个月才开始深入研究它。

4

1 回答 1

1

对于颜色,您基本上有两种情况,具体取决于$rowLabs奇数还是偶数。

  • 如果它是偶数,那么奇数行将完全是“白色”,偶数行将完全是“黑色”
  • 如果这很奇怪
    • 对于奇数行,奇数列为白色,偶数列为黑色
    • 对于偶数行,奇数列为黑色,偶数列为白色

(“奇数”和“偶数”像 XPathposition()一样从 1 开始计数,所以第一行/列是奇数,第二个是偶数,等等)。

您可以通过向模板添加一些参数来在 XSLT 中对该逻辑进行编码。更换

<xsl:apply-templates select="self::*|$otherEntries" />

<xsl:apply-templates select="self::*|$otherEntries">
    <xsl:with-param name="rowNum" select="position()" />
    <xsl:with-param name="totalRows" select="$rowLabs" />
</xsl:apply-templates>

并将参数添加到section模板

<xsl:template match="section[templateId/@root='2.16.840.1.113883.10.20.22.2.3.1']/entry">
    <xsl:param name="rowNum" select="1" />
    <xsl:param name="totalRows" select="2" />

现在我们需要一个可以调用的命名模板来实现我上面描述的逻辑:

<xsl:template name="bgcolor">
    <xsl:param name="rowNum" select="1" />
    <xsl:param name="totalRows" select="2" />
    <xsl:if test="($totalRows mod 2 = 0 and $rowNum mod 2 = 0) or
                  ($totalRows mod 2 = 1 and $rowNum mod 2 != position() mod 2)">
        <xsl:attribute name="bgcolor">dcdcdc</xsl:attribute>
    </xsl:if>
</xsl:template>

bgcolor如果存在偶数行且当前 rownum 为偶数,或者存在奇数行且行中的当前号与行号具有“不同的奇数”,则会添加该属性。

最后我们在<td>元素中调用这个模板,例如

<td width="50">
    <xsl:call-template name="bgcolor">
        <xsl:with-param name="rowNum" select="$rowNum" />
        <xsl:with-param name="totalRows" select="$totalRows" />
    </xsl:call-template>
    <xsl:value-of select="organizer/component/observation/value/@value"/>
</td>

使所有这些工作的关键是您将模板应用到self::*|$otherEntries,因此在应用模板中的调用会position()给出列号(此节点列表中的位置),而不是节点在其父节点中的原始位置。


要使日期在第一次遇到时只出现一次,您可以定义一个并使用与“Muenchian 分组”技术相关的技巧。宣布

<xsl:key name="effectiveTimeByDate" match="effectiveTime"
         use="substring-before(@value, ' ')" />

然后您可以使用以下方法检查这是否是文档中特定日期的第一次出现

<td width="75">
    <xsl:call-template name="bgcolor">
        <xsl:with-param name="rowNum" select="$rowNum" />
        <xsl:with-param name="totalRows" select="$totalRows" />
    </xsl:call-template>
    <xsl:if test="
         generate-id(organizer/component/observation/effectiveTime)
       = generate-id(key('effectiveTimeByDate', substring-before(
            organizer/component/observation/effectiveTime/@value, ' '))[1])">
        <xsl:call-template name="StripTime">
            <xsl:with-param name="DateTime" select="organizer/component/observation/effectiveTime/@value" />
        </xsl:call-template>
    </xsl:if>
</td>

(您也许可以StripTime完全废弃模板,只需使用与substring-before我在密钥中使用的相同的调用)

于 2013-09-10T18:26:28.327 回答