如何使用xslt将半结构化xml数据转换为表格并对选定的单元格进行颜色编码?

时间:2013-07-17 01:38:37

标签: xml xslt

我的xml数据是半结构化的。我需要将文本和数字数据传输到表中。另外,如果满足2个测试,我需要比较数字数据并对匹配进行颜色编码。我想知道在xml输入的情况下它是否可以实现高度结构化。 我的输入数据如下:

<DIV>
 <ul>
  <li>CC(fr3.1)<br/> : AX(en1.1)</li>
  <li>(fr4.1)<br/> : AX(en1.1)</li>
  <li>AA(fr1.1)<br/> : BX(en2.1)</li>
  <li>CC(fr3.1)<br/> : BX(en2.1)</li>

  <li>DD(fr1.2)<br/> : (en1.2)</li>
  <li>EE(fr2.2)<br/> : FX(en6.2)</li>
  <li>FF(fr3.2)<br/> : (en3.2)</li>
  <li>GG(fr4.2)<br/> : DX(en4.2)</li>
  <li>HH(fr5.2)<br/> : EX(en5.2)</li>
 </ul>
</DIV>

前缀为'fr'的数字数据应该进入同一行级别的列。因此,带有'en'前缀的数据应该进入下面的行。点后面的数字表示括号中的文本数据及其附带的数字属于同一个&lt; seg&gt;。输出中的元素。来自每个&lt; seg&gt;的数据。应安排在单独的表格中。例如。上面的输入需要2个单独的表。颜色编码应考虑2个测试:1)如果'fr'行的数值与'en'行下面单元格中的相应值相同,则两个单元格应分配背景颜色黄色(#FFFF00); 2)如果xml输入中的数字数据没有文本数据,那么输入中没有文本值的数值的单元格应该被赋予背景颜色红色(#ff0000)。

总而言之,HTML输出应如下所示:

Table

谢谢!

1 个答案:

答案 0 :(得分:2)

您需要做的第一件事就是通过'seg'数字对数据进行“分组”,在您的情况下,该数字是完全停止后但在最后一个括号之前的值。在XSLT 1.0中,这是通过称为Muenchian grouping的技术完成的。要执行此操作,首先要定义一个键,以便按此值对 li 元素进行分组,就像这样。

<xsl:key name="type" match="li" use="substring-before(substring-after(text(), '.'), ')')" />

然后,您将匹配在组中首先出现的 li 元素的相关“seg”数字。这样做是这样的:

<xsl:template match="li">
   <xsl:variable name="seg" select="substring-before(substring-after(text(), '.'), ')')"/>
   <xsl:if test="generate-id() = generate-id(key('type', $seg)[1])">

这为您提供了两个截然不同的“seg”组。

对于每个组,您将首先获得“fr”文本的所有文本节点(假设它们始终是出现的第一个)。

<xsl:apply-templates select="key('type', $seg)/text()[1]">
   <xsl:with-param name="cellnumber" select="1"/>
</xsl:apply-templates>

注意,我也传递了单元格编号,因为这将用于获取另一个“单元格”中的文本以进行比较。

获得'en'文字,类似

<xsl:apply-templates select="key('type', $seg)/text()[2]">
   <xsl:with-param name="cellnumber" select="2"/>
</xsl:apply-templates>

在与这些匹配的模板中,您将使用一些字符串操作来获取所需的值(在XSLT 2.0中,您可以使用正则表达式的功能来简化事情)

要获得前两个字母(例如“CC”或“AX”等),如果它们存在,您可以这样做

 <xsl:variable name="text" select="translate(substring-before(., '('), ' :', '')"/>

为了得到这个数字,你会这样做(这假设你只会有'fr'或'en')

<xsl:variable name="number" select="translate(substring-after(., '('), 'fren)', '')"/>

现在,要获取其他单元格中的文本,您可以使用传入的单元格数作为参数。

<xsl:variable name="othercell" select="../text()[3 - $cellnumber]"/>

然后,您可以以类似的方式提取数字,并在比较中使用它来获取颜色:

  <xsl:variable name="colour">
     <xsl:choose>
        <xsl:when test="$text = ''">FF0000</xsl:when>
        <xsl:when test="$number = $othernumber">FFFFFF</xsl:when>
        <xsl:otherwise>FFFF00</xsl:otherwise>
     </xsl:choose>
  </xsl:variable>

试试这个XSLT:

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

   <xsl:key name="type" match="li" use="substring-before(substring-after(text(), '.'), ')')"/>

   <xsl:template match="/">
      <xsl:apply-templates select="//li"/>
   </xsl:template>

   <xsl:template match="li">
      <xsl:variable name="seg" select="substring-before(substring-after(text(), '.'), ')')"/>
      <xsl:if test="generate-id() = generate-id(key('type', $seg)[1])">
         <h1 id="{$seg}">
            <xsl:value-of select="$seg"/>
         </h1>
         <table>
         <tr>
            <td>fr</td>
            <xsl:apply-templates select="key('type', $seg)/text()[1]">
               <xsl:with-param name="cellnumber" select="1"/>
            </xsl:apply-templates>
         </tr>
         <tr>
            <td>en</td>
            <xsl:apply-templates select="key('type', $seg)/text()[2]">
               <xsl:with-param name="cellnumber" select="2"/>
            </xsl:apply-templates>
         </tr>
         </table>
      </xsl:if>
   </xsl:template>

   <xsl:template match="text()">
      <xsl:param name="cellnumber"/>

      <xsl:variable name="text" select="translate(substring-before(., '('), ' :', '')"/>
      <xsl:variable name="number" select="translate(substring-after(., '('), 'fren)', '')"/>

      <xsl:variable name="othercell" select="../text()[3 - $cellnumber]"/>
      <xsl:variable name="othernumber" select="translate(substring-after($othercell, '('), 'fren)', '')"/>
      <xsl:variable name="colour">
         <xsl:choose>
            <xsl:when test="$text = ''">FF0000</xsl:when>
            <xsl:when test="$number = $othernumber">FFFFFF</xsl:when>
            <xsl:otherwise>FFFF00</xsl:otherwise>
         </xsl:choose>
      </xsl:variable>
      <td style="background-color:#{$colour}">
         <xsl:value-of select="$number"/>
      </td>
   </xsl:template>
</xsl:stylesheet>

这应输出以下内容

<h1 id="1">1</h1>
<table>
    <tr>
        <td>fr</td>
        <td style="background-color:#FFFF00">3.1</td>
        <td style="background-color:#FF0000">4.1</td>
        <td style="background-color:#FFFF00">1.1</td>
        <td style="background-color:#FFFF00">3.1</td>
    </tr>
    <tr>
        <td>en</td>
        <td style="background-color:#FFFF00">1.1</td>
        <td style="background-color:#FFFF00">1.1</td>
        <td style="background-color:#FFFF00">2.1</td>
        <td style="background-color:#FFFF00">2.1</td>
    </tr>
</table>
<h1 id="2">2</h1>
<table>
    <tr>
        <td>fr</td>
        <td style="background-color:#FFFFFF">1.2</td>
        <td style="background-color:#FFFF00">2.2</td>
        <td style="background-color:#FFFFFF">3.2</td>
        <td style="background-color:#FFFFFF">4.2</td>
        <td style="background-color:#FFFFFF">5.2</td>
    </tr>
    <tr>
        <td>en</td>
        <td style="background-color:#FF0000">1.2</td>
        <td style="background-color:#FFFF00">6.2</td>
        <td style="background-color:#FF0000">3.2</td>
        <td style="background-color:#FFFFFF">4.2</td>
        <td style="background-color:#FFFFFF">5.2</td>
    </tr>
</table>

这与你的图表并不“完全匹配”,但是你的图表与描述着色应如何工作的方式并不完全相关。