我有一个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() <= $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() < 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 知识带来了很长一段路。我上个月才开始深入研究它。
对于颜色,您基本上有两种情况,具体取决于$rowLabs
是奇数还是偶数。
- 如果是偶数,
- 那么奇数行将完全"白色",偶数行将完全"黑色"
- 如果很奇怪,那么
- 对于奇数行,奇数列
- 将为白色,偶数列为黑色 对于偶数
- 行,奇数列为黑色,偶数列为白色
和"偶数"从 1 开始计数,就像 XPath position()
所做的那样,所以第一行/列是奇数,第二行/列是偶数,依此类推)。
可以通过向模板添加一些参数来在 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
属性。
最后,我们在<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
调用)