XSL循环不返回正确的值

时间:2013-12-12 10:45:48

标签: xml xslt xslt-1.0

我想创建一个XSL循环来处理这样的XML:

<pop name="TEST">
<server>
   <name>host1</name>
      <status>red</status>
      <staleric>
        <ric service="A" name="a" />
        <ric service="A" name="b" />
        <ric service="A" name="c" />
        <ric service="A" name="d" />
        <ric service="A" name="e" />
        <ric service="A" name="f" />
      </staleric>
</server>
<server>
   <name>host2</name>
     <status>green</status>
</server>
<server>
   <name>host3</name>
     <status>red</status>
     <staleric>
      <ric service="B" name="1" />
      <ric service="B" name="2" />
     </staleric>
</server>
</pop>

XSL文件:

<?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"
              doctype-system="about:legacy-compat"
              encoding="UTF-8"
              indent="yes" />

  <xsl:template match="/">
    <html>
      <head>
        <title>Distribution POP Green Light</title>
        <link rel="stylesheet" href="../index_files/staleric.css" />
      </head>
      <body>
        <table class="staleric">
          <thead>
            <tr>
              <td>POP :</td><td><xsl:value-of select="pop/@name"/></td>
            </tr>
            <tr>
              <th>Server</th>
              <th>Status</th>
              <th>Stale RIC</th>
            </tr>
          </thead>
          <tbody>
            <xsl:for-each select="pop/server">
            <tr>
              <td><xsl:value-of select="name"/></td>
              <td>
                <xsl:variable name="statusTxt" select="status" />
                <xsl:choose>
                <xsl:when test="$statusTxt = 'red'">
                        <img src="../images/red.png"></img>
                </xsl:when>
                <xsl:otherwise>
                        <img src="../images/green.png"></img>
                </xsl:otherwise>
       </xsl:choose>
              </td>
              <td>
                <xsl:call-template name ="incr">
                        <xsl:with-param name ="value">1</xsl:with-param>
                        <xsl:with-param name ="limit">
                        <xsl:value-of select ="count(staleric/*)"/>
                        </xsl:with-param>
                </xsl:call-template>

              </td>
            </tr>
            </xsl:for-each>
          </tbody>
        </table>
      </body>
    </html>
  </xsl:template>

<xsl:template name="incr">
  <xsl:param name="value"/>
  <xsl:param name ="limit"/>
  <xsl:if test ="$value!=$limit+1">
    Service : <xsl:value-of select ="//ric[$value]/@service"/>
    RIC : <xsl:value-of select ="//ric[$value]/@name"/>
    <br/>
    <xsl:if test ="$value mod $limit =0">
    </xsl:if>
    <xsl:call-template name ="incr">
      <xsl:with-param name ="value" select ="$value+1"/>
      <xsl:with-param name ="limit" select ="$limit"/>
    </xsl:call-template>
  </xsl:if>
</xsl:template>
</xsl:stylesheet>

参考XML文件,host3必须是服务B和RIC名称= 1,2。不幸的是,我运行脚本后得到的结果是服务B和RIC名称= a,b。任何人都可以解释这个或者帮我解决一下吗?

Server                Status                Stale
host1                  red                  Service : A RIC : a
                                            Service : A RIC : b
                                            Service : A RIC : c
                                            Service : A RIC : d
                                            Service : A RIC : e
                                            Service : A RIC : f
host2                  green                
host3                  red                  Service : A RIC : a
                                            Service : A RIC : b

2 个答案:

答案 0 :(得分:0)

incr模板中:

<xsl:value-of select ="//ric[$value]/@service"/>

将始终为输入文档中的第一个服务器提供结果,而不一定是当前服务器,用于for-each 1的此迭代。但在我看来,这是解决问题的一种非常复杂的方式。不是让你调用的模板查找要按索引号处理的元素,为什么不简单地使用匹配的模板:

<?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"
              doctype-system="about:legacy-compat"
              encoding="UTF-8"
              indent="yes" />

  <xsl:template match="/">
    <html>
      <head>
        <title>Distribution POP Green Light</title>
        <link rel="stylesheet" href="../index_files/staleric.css" />
      </head>
      <body>
        <table class="staleric">
          <thead>
            <tr>
              <td>POP :</td><td><xsl:value-of select="pop/@name"/></td>
            </tr>
            <tr>
              <th>Server</th>
              <th>Status</th>
              <th>Stale RIC</th>
            </tr>
          </thead>
          <tbody>
            <!-- process all the servers -->
            <xsl:apply-templates select="pop/server" />
          </tbody>
        </table>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="server">
    <tr>
      <td><xsl:value-of select="name"/></td>
      <td>
        <xsl:choose>
          <xsl:when test="status = 'red'">
            <img src="../images/red.png"></img>
          </xsl:when>
          <xsl:otherwise>
            <img src="../images/green.png"></img>
          </xsl:otherwise>
        </xsl:choose>
      </td>
      <td>
        <!-- process all the ric elements for this server (if any) -->
        <xsl:apply-templates select="staleric/ric" />
      </td>
    </tr>
  </xsl:template>

  <xsl:template match="ric">
    <xsl:text>Service : </xsl:text>
    <xsl:value-of select ="@service"/>
    <xsl:text> RIC : </xsl:text>
    <xsl:value-of select ="@name"/>
    <br/>
  </xsl:template>
</xsl:stylesheet>

1:从技术上讲,对于$value=1,例如,select会提取一个由整个文档中所有ric元素组成的集合,这些元素是第一个ric在他们各自的父母内部,XSLT 1.0中的value-of多节点集被定义为文档顺序中集合中第一个节点的值 - 后续节点完全被忽略

答案 1 :(得分:0)

我相信这一点:

Service : <xsl:value-of select ="//ric[$value]/@service"/>
RIC : <xsl:value-of select ="//ric[$value]/@name"/>

需要:

Service : <xsl:value-of select ="staleric/ric[$value]/@service"/>
RIC : <xsl:value-of select ="staleric/ric[$value]/@name"/>