如何从 xsl:for-each 块的"scope"外部访问 xsl:变量



我试图从for-each中访问一个变量。我今天读了很多书,试图弄清楚这个问题,但没有什么符合我的设想。最终,我将得到如下所示的多个级数我将使用我提出来的变量来制造不同的条件。我下面的for-each是从400条记录中带回数据的。很抱歉,我不能提供XML。我不能公开guid之类的。

       <?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output media-type="xml" indent="yes"/>
  <xsl:template match="/">
    <Records>
      <xsl:for-each select="Records/Record/Record[@levelGuid = 'level1']">
        <xsl:variable name="rocName1" select="Field[@guid = '123']"/>
        <xsl:variable name ="rocName2" select="substring-before($rocName1, ' - ')"/>
      </xsl:for-each>

      <xsl:for-each select="Records/Record/Record[@levelGuid = 'levelA']">
        <xsl:variable name ="findingName" select="Field[@guid = '123']"/>
        <xsl:variable name="findingName1" select="substring-after($findingName, ': ')"/>
        <xsl:variable name="findingName2" select="substring-after($findingName1, 'PCIDSSv3.1:')"/>
      </xsl:for-each>
      <xsl:if test="$findingName1 = $rocName1">
        <Records>
          <findingID>
            <xsl:for-each select="Records/Record/Record[@levelGuid = '123']">
              <xsl:value-of select ="Field[@guid = '123']"/>
            </xsl:for-each>
          </findingID>
        </Records>
      </xsl:if>
  </Records>
  </xsl:template>
</xsl:stylesheet>

期望的输出是具有等于$rocName1的$findingName1的任何findingID。GUIDS只出现一次,但每个级别都有数百条记录。

我试图从for-each中访问一个变量。

变量$rocRecord在for-each的作用域中。你可以简单地引用它并使用它。

但是我认为你在试图做别的事情。例如,在 for-each中定义了一个变量,并希望在之外使用它。

变量的作用域在其焦点设置包含块内。所以简短的回答是:你做不到。然而,长话短说……

使用模板。做你想做的事情的唯一原因是需要访问其他地方的数据:

<xsl:template match="/">
    <!-- in fact, you don't need for-each at all, but I leave it in for clarity -->
    <xsl:for-each select="records/record">
        <!-- 
            apply-templates means: call the declared xsl:template that 
            matches this node, it is somewhat similar to a function call in other 
            languages, except that it works the other way around, the processor will 
            magically find the "function" (i.e., template) for you 
        -->
        <xsl:apply-templates select="Field[@guid='123']" />
    </xsl:for-each>
</xsl:template>
<xsl:template match="Field">
    <!-- the focus here is what is the contents of your variable $rocName1 -->
    <rocName>
        <xsl:value-of select="substring=-before(., ' - ')" />
    </rocName>
</xsl:template>

XSLT是一种声明性的、面向模板的函数式语言,其概念与大多数其他语言相比非常独特。你可能需要几个小时来适应它。

你说你读了很多书,但是也许是时候去学习一些XSLT课程了?网上有一些,搜索"XSLT基础课程"。它将为你节省数小时/数天的沮丧。

这是一个很好的、简短的阅读,可以帮助您了解XSLT中的变量。

更新

在第二次读取时,我认为看起来您对循环进行了400项而您只想输出$rocName1的值这一事实感到困扰。我上面展示的例子正是这样做的,,因为如果选择为空, apply-templates什么也不做,这就是没有找到guid时发生的情况。

如果guid出现一次,上面的代码将输出它一次。如果它出现了多次,而你只想要第一次,将[1]附加到select语句。

更新#2(在使用示例更新之后)

有两个循环:

<xsl:for-each select="Records/Record/Record[@levelGuid = 'level1']">

<xsl:for-each select="Records/Record/Record[@levelGuid = 'levelA']">

当第一个循环中的记录与第二个循环中的记录匹配时,您想要做一些事情(创建findingId)。

虽然可以使用(嵌套)循环解决这个问题,但没有必要这样做,事实上,不鼓励这样做,因为这会使您的代码难以阅读。正如我在最初的回答中所解释的那样,应用模板通常是实现这一点的更简单的方法。

由于Record元素是彼此的兄弟元素,我将按如下方式处理:

<xsl:template match="/">
    <Records>
        <xsl:apply-templates select="Records/Records/Record[@levelGuid = 'level1']" />
    </Records>
</xsl:template>
<xsl:template match="Record">
    <xsl:variable name="rocName1" select="Field[@guid = '123']"/>
    <xsl:variable name ="rocName2" select="substring-before($rocName1, ' - ')"/>
    <xsl:variable name="findingNameBase" select="../Record[@levelGuid = 'levelA']" />
    <xsl:variable name ="findingName" select="$findingNameBase/Field[@guid = '123']"/>
    <xsl:variable name="findingName1" select="substring-after($findingName, ': ')"/>
    <xsl:variable name="findingName2" select="substring-after($findingName1, 'PCIDSSv3.1:')"/>
    <findingId rocName="{$rocName1}">
        <xsl:value-of select="$findingName" />
    </findingId>
</xsl:template>

虽然这可以进一步简化,但这是学习应用模板的一个良好开端,模板是使用XSLT所做任何事情的核心。了解如何应用模板,因为没有模板,XSLT将非常难以理解。

相关内容

  • 没有找到相关文章

最新更新