在xslt中对缺少的表元素进行分组和填充

时间:2018-02-28 10:57:04

标签: xml xslt xslt-1.0 xslt-grouping

我有一个像下面给出的xml。我试图将此xml转换为html表。 " ServerName"节点成为列标题。行分为"类别"名称。当"类别 - >名称"或"参数 - >键"不存在任何"数据"节点,它应显示" NA"。

我尽力自己解决问题,但是我在分组和填补缺失的元素方面失败了。任何帮助都非常感谢。



<Results>
  <Data>
    <ServerName>Server1</ServerName>
    <CategorizedData>
      <Category>
        <Parameters>
          <Parameter key="A" value="1" />
          <Parameter key="B" value="2" />
          <Parameter key="C" value="3" />
        </Parameters>
      </Category>
      <Category Name="Misc">
        <Parameters>
          <Parameter key="A" value="2" />
          <Parameter key="B" value="5" />
        </Parameters>
      </Category>
    </CategorizedData>
  </Data>
  <Data>
    <ServerName>Server2</ServerName>
    <CategorizedData>
      <Category>
        <Parameters>
          <Parameter key="A" value="10" />
          <Parameter key="B" value="20" />
          <Parameter key="D" value="30" />
        </Parameters>
      </Category>
      <Category Name="Misc">
        <Parameters>
          <Parameter key="C" value="2" />
          <Parameter key="D" value="5" />
        </Parameters>
      </Category>
    </CategorizedData>
  </Data>
</Results>
&#13;
&#13;
&#13;

&#13;
&#13;
<table>
	<tr>
		<td></td>
		<td>Server1</td>
		<td>Server2</td>
	</tr>
	<tr>
		<td>A</td>
		<td>1</td>
		<td>10</td>
	</tr>
	<tr>
		<td>B</td>
		<td>2</td>
		<td>20</td>
	</tr>
	<tr>
		<td>C</td>
		<td>3</td>
		<td>NA</td>
	</tr>
	<tr>
		<td>D</td>
		<td>NA</td>
		<td>30</td>
	</tr>
	<tr>
		<td>Misc</td>
		<td></td>
		<td></td>
	</tr>
	<tr>
		<td>A</td>
		<td>2</td>
		<td>NA</td>
	</tr>
	<tr>
		<td>B</td>
		<td>5</td>
		<td>NA</td>
	</tr>
	<tr>
		<td>C</td>
		<td>NA</td>
		<td>2</td>
	</tr>
	<tr>
		<td>D</td>
		<td>NA</td>
		<td>5</td>
	</tr>
</table>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:1)

使用XSLT 2或3,您可以使用嵌套的<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" expand-text="yes" version="3.0"> <xsl:output method="html" indent="yes" html-version="5"/> <xsl:template match="/"> <html> <head> <title>.NET XSLT Fiddle Example</title> </head> <body> <xsl:apply-templates/> </body> </html> </xsl:template> <xsl:template match="Results"> <table> <xsl:variable name="servers" select="Data/ServerName"/> <thead> <tr> <th>Key</th> <xsl:for-each select="$servers"> <th>{.}</th> </xsl:for-each> </tr> </thead> <tbody> <xsl:for-each-group select=".//Category" group-by="string(@Name)"> <xsl:variable name="cat-group" select="current-group()"/> <tr> <th>{current-grouping-key()}</th> <th>{$servers[1]}</th> <th>{$servers[2]}</th> </tr> <xsl:for-each-group select="current-group()" group-by="Parameters/Parameter/@key"> <tr> <td>{current-grouping-key()}</td> <td>{($cat-group[ancestor::Data[ServerName = $servers[1]]]/Parameters/Parameter[@key = current-grouping-key()]/@value, 'N/A')[1]}</td> <td>{($cat-group[ancestor::Data[ServerName = $servers[2]]]/Parameters/Parameter[@key = current-grouping-key()]/@value, 'N/A')[1]}</td> </tr> </xsl:for-each-group> </xsl:for-each-group> </tbody> </table> </xsl:template> </xsl:stylesheet>

来解决它
  <table>
     <thead>
        <tr>
           <th>Key</th>
           <th>Server1</th>
           <th>Server2</th>
        </tr>
     </thead>
     <tbody>
        <tr>
           <th></th>
           <th>Server1</th>
           <th>Server2</th>
        </tr>
        <tr>
           <td>A</td>
           <td>1</td>
           <td>10</td>
        </tr>
        <tr>
           <td>B</td>
           <td>2</td>
           <td>20</td>
        </tr>
        <tr>
           <td>C</td>
           <td>3</td>
           <td>N/A</td>
        </tr>
        <tr>
           <td>D</td>
           <td>N/A</td>
           <td>30</td>
        </tr>
        <tr>
           <th>Misc</th>
           <th>Server1</th>
           <th>Server2</th>
        </tr>
        <tr>
           <td>A</td>
           <td>2</td>
           <td>N/A</td>
        </tr>
        <tr>
           <td>B</td>
           <td>5</td>
           <td>N/A</td>
        </tr>
        <tr>
           <td>C</td>
           <td>N/A</td>
           <td>2</td>
        </tr>
        <tr>
           <td>D</td>
           <td>N/A</td>
           <td>5</td>
        </tr>
     </tbody>
  </table>

https://xsltfiddle.liberty-development.net/6qM2e2i/3给出输出

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    expand-text="yes"
    version="3.0">


  <xsl:output method="html" indent="yes" html-version="5"/>

  <xsl:template match="/">
    <html>
      <head>
        <title>.NET XSLT Fiddle Example</title>
      </head>
      <body>
        <xsl:apply-templates/>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="Results">
      <table>
          <xsl:variable name="servers" select="Data/ServerName"/>
          <thead>
              <tr>
                  <th>Key</th>
                  <xsl:for-each select="$servers">
                      <th>{.}</th>
                  </xsl:for-each>
              </tr>
          </thead>
          <tbody>
              <xsl:for-each-group select=".//Category" group-by="string(@Name)">
                  <xsl:variable name="cat-group" select="current-group()"/>
                  <tr>
                      <th>{current-grouping-key()}</th>
                      <xsl:for-each select="$servers">
                          <th>{.}</th>
                      </xsl:for-each>
                  </tr>
                  <xsl:for-each-group select="current-group()" group-by="Parameters/Parameter/@key">
                      <tr>
                          <td>{current-grouping-key()}</td>
                          <xsl:for-each select="$servers">
                              <td>{($cat-group[ancestor::Data[ServerName = current()]]/Parameters/Parameter[@key = current-grouping-key()]/@value, 'N/A')[1]}</td>
                          </xsl:for-each>
                      </tr>
                  </xsl:for-each-group>
              </xsl:for-each-group>
          </tbody>
      </table>
  </xsl:template>

</xsl:stylesheet>

对于动态数量的服务器列,我希望适应

digraph My_test_without_subgraphs {

  graph [overlap = true, compound = true, rankdir = LR]

  node [shape = box, color = lightgrey, style = filled, fontcolor = black]
  T1 [label = "my task 1"]
  T2 [label = "my task 2"]
  T3 [label = "my task 3"]
  T4 [label = "my task 4"]

  T1 -> T3
  T2 -> T3
  T3 -> T4

}

管理:https://xsltfiddle.liberty-development.net/6qM2e2i/4

答案 1 :(得分:1)

使用XSLT 1: 例: https://xsltfiddle.liberty-development.net/bFukv8n

<?xml version="1.0" encoding="UTF-8"?>

    

<xsl:template match="/">
    <xsl:variable name="vMsg" select="."/>
    <xsl:variable name="vServerNames" select="/Results/Data/ServerName" />
    <table>
        <tr>
            <td/>
            <xsl:for-each select="$vServerNames">
                <td>
                    <xsl:value-of select="."/>
                </td>
            </xsl:for-each>
        </tr>
        <!-- Categories with no Name -->
        <xsl:for-each select="$vMsg//Category[not(@Name)]/Parameters/Parameter[not(@key = following::Category[not(@Name)]/Parameters/Parameter/@key)]">
            <xsl:variable name="vCurrKey" select="@key" />
            <tr>
                <td>
                    <xsl:value-of select="$vCurrKey"/>
                </td>
                <xsl:for-each select="$vServerNames">
                    <xsl:variable name="vCurrServer" select="text()" />
                    <xsl:variable name="vCurrVal" select="$vMsg/Results/Data[ServerName = $vCurrServer]/CategorizedData/Category[not(@Name)]/Parameters/Parameter[@key = $vCurrKey]"/>
                    <xsl:choose>
                        <xsl:when test="boolean($vCurrVal)">
                            <td>
                                <xsl:value-of select="$vCurrVal/@value"/>
                            </td>
                        </xsl:when>
                        <xsl:otherwise>
                            <td>NA</td>
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:for-each>
            </tr>
        </xsl:for-each>
        <!-- Categories with Name -->
        <xsl:for-each select="//Category[@Name and not(@Name = following::Category/@Name)]">
            <xsl:variable name="vCatName" select="@Name"/>
            <tr>
                <td>
                    <xsl:value-of select="$vCatName"/>
                </td>
                <td/>
                <td/>
            </tr>
            <xsl:variable name="vKeys" select="$vMsg//Category[@Name = $vCatName]/Parameters/Parameter[not(@key = following::Category[@Name = $vCatName]/Parameters/Parameter/@key)]" />
            <xsl:for-each select="$vKeys">
                <xsl:variable name="vCurrKey" select="@key" />
                <tr>
                    <td>
                        <xsl:value-of select="$vCurrKey"/>
                    </td>
                    <xsl:for-each select="$vServerNames">
                        <xsl:variable name="vCurrServer" select="text()" />
                        <xsl:variable name="vCurrVal" select="$vMsg/Results/Data[ServerName = $vCurrServer]/CategorizedData/Category[@Name = $vCatName]/Parameters/Parameter[@key = $vCurrKey]"/>
                        <xsl:choose>
                            <xsl:when test="boolean($vCurrVal)">
                                <td>
                                    <xsl:value-of select="$vCurrVal/@value"/>
                                </td>
                            </xsl:when>
                            <xsl:otherwise>
                                <td>NA</td>
                            </xsl:otherwise>
                        </xsl:choose>
                    </xsl:for-each>
                </tr>
            </xsl:for-each>
        </xsl:for-each>
    </table>
</xsl:template>