如何从xsl:for-each块的“范围”之外访问xsl:变量

时间:2015-09-15 19:36:45

标签: xslt xslt-1.0

我正在尝试从for-each中访问变量。我今天做了很多阅读,试图弄清楚这一点,但没有什么比我的情况更合适。最终,我将有如下所示的多个系列,我将使用我正在拉出的变量并制作不同的条件。我在下面的for-each将从400条记录中恢复数据。对不起,我无法提供XML。我无法公开GUID等。

更新

var
  p1 = Paranoiac.create({width: 55, height: 66}),
  p2 = Paranoiac.create({width: 44, height: 77}),
  p3 = Paranoiac.create({width: 33, height: 99})
;
console.log("Object.keys(p1) - ", Object.keys(p1));
console.log("Object.keys(p2) - ", Object.keys(p2));
console.log("Object.keys(p3) - ", Object.keys(p3));

console.log("p1.getWidth(), p1.getHeight() - ", [p1.getWidth(), p1.getHeight()]);
console.log("p2.getWidth(), p2.getHeight() - ", [p2.getWidth(), p2.getHeight()]);
console.log("p3.getWidth(), p3.getHeight() - ", [p3.getWidth(), p3.getHeight()]);

console.log('p1.setWidth("5"), p1.setHeight("6") - ', [p1.setWidth("5"), p1.setHeight("6")]);

console.log("p1.getWidth(), p1.getHeight() - ", [p1.getWidth(), p1.getHeight()]);
console.log("p2.getWidth(), p2.getHeight() - ", [p2.getWidth(), p2.getHeight()]);
console.log("p3.getWidth(), p3.getHeight() - ", [p3.getWidth(), p3.getHeight()]);

console.log('p2.setWidth("4"), p2.setHeight("7") - ', [p2.setWidth("4"), p2.setHeight("7")]);
console.log('p3.setWidth("3"), p3.setHeight("9") - ', [p3.setWidth("3"), p3.setHeight("9")]);

console.log("p1.getWidth(), p1.getHeight() - ", [p1.getWidth(), p1.getHeight()]);
console.log("p2.getWidth(), p2.getHeight() - ", [p2.getWidth(), p2.getHeight()]);
console.log("p3.getWidth(), p3.getHeight() - ", [p3.getWidth(), p3.getHeight()]);

console.log("Paranoiac.isParanoiac(p1) - ", Paranoiac.isParanoiac(p1));
console.log("Paranoiac.isParanoiac(p2) - ", Paranoiac.isParanoiac(p2));
console.log("Paranoiac.isParanoiac(p3) - ", Paranoiac.isParanoiac(p3));

console.log("Paranoiac.isParanoiac() - ", Paranoiac.isParanoiac());
console.log("Paranoiac.isParanoiac({}) - ", Paranoiac.isParanoiac({}));

所需的输出是任何具有$ findingName1等于$ rocName1的findsID。 GUID只出现一次,但每个级别都有数百条记录。

1 个答案:

答案 0 :(得分:2)

  

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

变量$rocRecord在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课程了吗?有一些在线,搜索&#34; XSLT基础课程&#34;。它会为你节省数小时/天的挫折感。

这是一个很好的,简短的阅读to catch up on variables in 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)。

虽然你可以使用(嵌套)循环来解决这个问题,但是没有必要这样做,事实上,不鼓励它,因为它会使你的代码难以阅读。正如我在原始答案中所解释的那样,apply-templates通常是更简单的方法来实现这一点。

由于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做的任何事情的核心。 Learn about applying templates,因为没有它,XSLT将很难理解。