0

我有以下 XML:

 <discrepancyModel>
     <MissingSuppliers isMissingSuppliersCheckApplied="true">
            <SnsCode value="str1234" mi="GRAA350RR" syst="29" subsys="2"
    subsubsys="1" assy="XX" />
            <SnsCode value="str1234" mi="GRAA350RR" syst="29" subsys="2"
    subsubsys="3" assy="XX" />
            <SnsCode value="str1234" mi="TRENTXWB" syst="28" subsys="1"
    subsubsys="1" assy="XX" />
            <SnsCode value="str1234" mi="TRENTXWB" syst="29" subsys="1"
    subsubsys="1" assy="57" />
            <SnsCode value="str1234" mi="TRENTXWC" syst="29" subsys="1"
    subsubsys="1" assy="58" />
            <SnsCode value="str1234" mi="TRENTXWD" syst="29" subsys="1"
    subsubsys="1" assy="58" />
        </MissingSuppliers>
    </discrepancyModel>

预期的输出是:

在这里,我必须在表格行中显示每个 SNSCODE 的信息。如果 2 个或多个 SNSCODE 具有相同的 @mi 值,则 SNSCODE 仅写入一次,但其前面有多行(即第一列合并)

我被卡住的主要问题是我想要行的替代颜色,但我无法实现。我已经看到了所有早期的答案,但它们并没有解决我的问题。

我有以下 xslt 代码:

<table border="1">
  <tr>
    <th>Name (MI)</th>
    <th>systemCode</th>
    <th>subSystemCode</th>
    <th>subSubSystemCode</th>
    <th>assyCode</th>
  </tr>
  <xsl:for-each select="//SnsCode">
    <xsl:variable name="tmp">
      <xsl:value-of select="./@mi" />
    </xsl:variable>
    <xsl:if test="generate-id(.) = generate-id(key('stvalkey',$tmp)[1])">
      <xsl:variable name="miNumber" select="count(key('stvalkey',$tmp))" />
      <xsl:for-each select="//SnsCode[@mi=$tmp]">
        <xsl:value-of select="count(preceding-sibling::SnsCode)" />
        <tr>
          <xsl:attribute name="class">
            <xsl:if test="position() mod 2 = 0">
              <xsl:value-of select="'odd'" />
            </xsl:if>
          </xsl:attribute>
          <xsl:if test="position()=1">
            <td>
              <xsl:attribute name="rowspan">
                <xsl:value-of select="$miNumber" />
              </xsl:attribute>
              <xsl:value-of select="$tmp" />
            </td>
          </xsl:if>
          <td>
            <xsl:value-of select="./@syst" />
          </td>
          <td>
            <xsl:value-of select="./@subsys" />
          </td>
          <td>
            <xsl:value-of select="./@subsubsys" />
          </td>
          <td>
            <xsl:value-of select="./@assy" />
          </td>
        </tr>
      </xsl:for-each>
    </xsl:if>
  </xsl:for-each>
</table>

此用于着色的代码是:

 <xsl:attribute name="class">
   <xsl:if test="position() mod 2 = 0">
     <xsl:value-of select="'odd'"/>
   </xsl:if>
 </xsl:attribute> 

问题是,如果我在循环中使用此代码,它不会为整行着色,它只会着色 mi 值内的第二行。

另一方面,如果在循环外使用此代码,那么我不会将元素的位置设为 1,2,3,4 ....但我得到的值为 1,3,5,6,因为有 2第一个值出现,第二个值出现 2 次,依此类推。

谁能建议在这种情况下如何着色?

4

2 回答 2

1

以下 XSLT 使用问题中给出的整体结构。但是,它不是使用position()上下文来确定奇数表行,而是定义了一个变量,该变量group_index确定在当前组之前有多少组。

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

  <xsl:key name="stvalkey" match="//SnsCode" use="@mi"/>

  <xsl:template match="/">

    <table border="1">
      <tr>
        <th>Name (MI)</th>
        <th>systemCode</th>
        <th>subSystemCode</th>
        <th>subSubSystemCode</th>
        <th>assyCode</th>
      </tr>

      <xsl:for-each select="//SnsCode">

        <xsl:variable name="tmp" >
          <xsl:value-of select="./@mi"/>
        </xsl:variable>


        <xsl:if test="generate-id(.) = generate-id(key('stvalkey',$tmp)[1])">

          <xsl:variable name="group_index" select="count(preceding-sibling::SnsCode[generate-id(.) = generate-id(key('stvalkey',@mi)[1])])"/>

          <xsl:variable name="miNumber" select="count(key('stvalkey',$tmp))" />

          <xsl:for-each select="//SnsCode[@mi=$tmp]">    
            <xsl:value-of select="count(preceding-sibling::SnsCode)"/>
            <tr> 
              <xsl:attribute name="style">
                <xsl:if test="$group_index mod 2 = 0">
                  <xsl:value-of select="'background-color:yellow;'"/>
                </xsl:if>
              </xsl:attribute>     
              <xsl:if test="position()=1">
                <td>
                  <xsl:attribute name="rowspan">
                    <xsl:value-of select="$miNumber" />    
                  </xsl:attribute>
                  <xsl:value-of select="$tmp" />
                </td>
              </xsl:if>

              <td><xsl:value-of select="./@syst" /></td>
              <td><xsl:value-of select="./@subsys" /></td>
              <td><xsl:value-of select="./@subsubsys" /></td>
              <td><xsl:value-of select="./@assy" /></td>
            </tr>

          </xsl:for-each>
        </xsl:if>
      </xsl:for-each>  
    </table>
  </xsl:template>

</xsl:stylesheet>

导致这个 HTML 输出

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<table border="1">
  <tr>
    <th>Name (MI)</th>
    <th>systemCode</th>
    <th>subSystemCode</th>
    <th>subSubSystemCode</th>
    <th>assyCode</th>
  </tr>0<tr style="background-color:yellow;">
    <td rowspan="2">GRAA350RR</td>
    <td>29</td>
    <td>2</td>
    <td>1</td>
    <td>XX</td>
  </tr>1<tr style="background-color:yellow;">
    <td>29</td>
    <td>2</td>
    <td>3</td>
    <td>XX</td>
  </tr>2<tr style="">
    <td rowspan="2">TRENTXWB</td>
    <td>28</td>
    <td>1</td>
    <td>1</td>
    <td>XX</td>
  </tr>3<tr style="">
    <td>29</td>
    <td>1</td>
    <td>1</td>
    <td>57</td>
  </tr>4<tr style="background-color:yellow;">
    <td rowspan="1">TRENTXWC</td>
    <td>29</td>
    <td>1</td>
    <td>1</td>
    <td>58</td>
  </tr>5<tr style="">
    <td rowspan="1">TRENTXWD</td>
    <td>29</td>
    <td>1</td>
    <td>1</td>
    <td>58</td>
  </tr>
</table>

笔记:

  • 添加了键定义以使 XSLT 工作。
  • CSS 类定义odd被内联定义替换,以使颜色在生成的 HTML 页面中可见。
于 2013-11-11T00:28:37.770 回答
0

如果@mi在源 XML 中总是存在多个相同的记录相邻的情况,那么您不需要两个嵌套级别for-each,您可以将所有工作合二为一,for-each并使用键来处理第一列:

<table border="1">
  <tr>
    <th>Name (MI)</th>
    <th>systemCode</th>
    <th>subSystemCode</th>
    <th>subSubSystemCode</th>
    <th>assyCode</th>
  </tr>
  <xsl:for-each select="//SnsCode">
    <xsl:variable name="tmp" select="@mi" />
    <xsl:variable name="miNumber" select="count(key('stvalkey',$tmp))" />
    <tr>
      <xsl:attribute name="class">
        <xsl:if test="position() mod 2 = 0">odd</xsl:if>
      </xsl:attribute>
      <xsl:if test="generate-id() = generate-id(key('stvalkey', $tmp)[1])">
        <td>
          <xsl:attribute name="rowspan">
            <xsl:value-of select="$miNumber" />
          </xsl:attribute>
          <xsl:value-of select="$tmp" />
        </td>
      </xsl:if>
      <td>
        <xsl:value-of select="./@syst" />
      </td>
      <td>
        <xsl:value-of select="./@subsys" />
      </td>
      <td>
        <xsl:value-of select="./@subsubsys" />
      </td>
      <td>
        <xsl:value-of select="./@assy" />
      </td>
    </tr>
  </xsl:for-each>
</table>

现在你只有一个for-eachposition()每次都会给你正确的价值。

于 2013-11-11T00:13:54.153 回答