从下面的代码我想检查网络B是否存在于其中一个操作员站节点中。如果存在则返回true或false。 其实我想在循环中实现像break语句这样的代码。但是由于XSLT中不存在中断,请建议我实现它的解决方案。 请遵循相同的代码,并建议使用键或变量值作为记录列表。
XSLT:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:w3="http://www.w3.org">
<xsl:output method="html" indent="yes"/>
<xsl:variable name="allStations"
select="//w3:OperatorStation"/>
<xsl:template match="/">
<xsl:variable name="networks" select="$allStations"/>
<xsl:for-each select="$networks">
//check whether Network B is exist
// in any one OperatorStation node,
// if yes return true.
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
和XML:
<?xml version="1.0" encoding="utf-8"?>
<OperatorStationCollection xmlns="http://www.w3.org" >
<OperatorStation xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Nodes>
<ChildNodes>
<Name>Network A</Name>
</ChildNodes>
</Nodes>
</OperatorStation>
<OperatorStation xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Nodes>
<ChildNodes>
<Name>Network B</Name>
</ChildNodes>
</Nodes>
</OperatorStation>
<OperatorStation xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Nodes>
<ChildNodes>
<Name>Network A</Name>
</ChildNodes>
</Nodes>
</OperatorStation>
</OperatorStationCollection>
预期产出:
真
答案 0 :(得分:4)
正如Ian Roberts已经在his answer to your earlier question中建议的那样,如果你学会以声明方式而不是程序方式思考,那么你将在XSLT中做得更好。 (学习这样做也可能使你成为程序语言中更好的程序员,而不仅仅是在XSLT中,但这是你必须承担的风险。)
所以要做的第一件事就是不再认为你的目标是实现像循环中的break语句这样的代码&#34;。这是一个愚蠢的目标 - 如果你真的想在循环中使用break语句进行编程,那么选择一个具有循环和break语句的语言并且疯狂。如果您想在XSLT中解决问题,则需要以声明的方式理解您的目标。在过程语言中,你会在这里使用循环 - 做什么?带有break的循环语句在过程语言中解决了什么问题?在XSLT中解决这个问题,你就完成了。
您对目标的描述(不完整且难以置信)表示如果某个OperatorStation元素具有名为Network B的子节点,则返回true,否则返回false。您建议迭代使用名为Network B的子项的OperatorStation元素,如果您点击一个,则返回true,如果到达末尾而不点击一个,则返回false。
如果存在这样的OperatorStation元素,为什么不返回true,否则返回false?
<xsl:template match="/">
<xsl:choose>
<xsl:when test="//w3:OperatorStation
/w3:Nodes
/w3:ChildNodes
/w3:Name
= 'Network B'">
true
</xsl:when>
<xsl:otherwise>
false
</xsl:otherwise>
</xsl:choose>
</xsl:template>
如果您真正想要做的是做一件事,当且仅当有一个名为&#39;网络B&#39;否则,别的东西,然后取代&#39; true&#39;并且&#39; false&#39;以上是适当的说明。
如果你真正想做的是设置一个变量来表示是否有一个名为&#39;网络B&#39;的孩子的OperatorStation,那么你可以在各个点的某些条件处理中使用它,然后设置具有适当XPath表达式的变量很简单:
<xsl:variable name="Opstation-with-child-B"
select="//w3:OperatorStation
[w3:Nodes/w3:ChildNodes
/w3:Name = 'Network B']"/>
这里不需要循环:XPath负责隐式迭代。
用你的工具思考,而不是反对它们。它使编程变得更有趣。
答案 1 :(得分:2)
你的xsl:break
没有xsl:for-each
,这是正确的。
通常的做法是更有选择性地控制下列之一:
如果没有看到你想要的输出,我就不能更具体了,但无论细节如何,一般概念都是有用的:
控制是否开始循环( Good )
<!-- We want to loop only when no Network B's exist -->
<xsl:if test="//w3:OperatorStation[not(.//w3:ChildNodes/w3:Name = 'Network B')]"
<xsl:for-each select="//w3:OperatorStation">
<!-- ... -->
</xsl:for-each>
</xsl:if>
控制要迭代的内容(更好)
<!-- We want to loop over all non-Network-B OperatorStations -->
<xsl:for-each select="//w3:OperatorStation[not(.//w3:ChildNodes/w3:Name = 'Network B')]">
<!-- ... -->
</xsl:for-each>
控制将模板应用到的内容(最佳)
<!-- We want to apply templates to all non-Network-B OperatorStations -->
<xsl:apply-templates select="//w3:OperatorStation[not(.//w3:ChildNodes/w3:Name = 'Network B')]"/>
<!-- other templates handle each OperatorStation -->
请注意,我并不是要暗示这些结果都是一样的。 (你没有指定你想要的输出,所以我采取了自由。)
以声明方式使用XSLT与使用其他语言常用的通常程序方法不同,但如果有机会,最终确实可行。
答案 2 :(得分:1)
正如您已经知道的那样,没有选项可以突破for-each循环。但是可以选择是否存在值为“网络B”的“名称”元素。虽然效率不高,但这个解决方案对我有用
<xsl:template match="/">
<xsl:variable name="is-Network-B">
<xsl:for-each select="//w3:Name">
<xsl:value-of select="if (matches(.,'Network B')) then '1' else ''"/>
</xsl:for-each>
</xsl:variable>
<xsl:if test="$is-Network-B!=''">
True
</xsl:if></xsl:template>