XSLT的新手,我的问题是是否可以在路径的不同级别中使用"or"进行逻辑测试,还是我必须以某种方式将其分开?
示例 xml:
<LandXML>
<HexagonLandXML>
<Point lineworkFlag="START LINJE">
<PointCode codeLinework="open line">
</PointCode>
</Point>
</HexagonLandXML>
</LandXML>
和示例 xls:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:landxml="http://www.landxml.org/schema/LandXML-1.2"
xmlns:hexagon="http://xml.hexagon.com/schema/HeXML-1.7"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"
version="1.0"
encoding="UTF-16"
indent="no"
omit-xml-declaration="yes"/>
<xsl:variable name="XML" select="/"/>
<xsl:template match="/">
<xsl:for-each select="$XML">
<xsl:for-each select="landxml:LandXML/hexagon:HexagonLandXML/hexagon:Point">
<xsl:for-each select="hexagon:PointCode">
<xsl:when test="../following-sibling::*[1]
/hexagon:PointCode[@codeLinework='none']
or
../../following-sibling::*[1]
/hexagon:Point[@lineworkFlag='START LINJE']">
do something...
</xsl:when>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
欢迎来到堆栈溢出。
由于您没有提及任何错误消息的文本,因此我想您没有收到任何错误。 由于您仍然会询问是否可以执行代码正在做的事情,因此我猜您没有得到想要或期望的结果。 而且由于我不完全确定您所说的"在路径的不同级别中使用'or'进行逻辑测试"或"以某种方式将其分开"是什么意思,因此我必须猜测一下您的意思。 (这是很多猜测;如果我的任何猜测是错误的,这个答案不会有太大帮助。
我认为您最初想问的问题可能是这样的:当or
的两个操作数是对两个完全不同的元素进行测试时,编写一个顶级运算符是or
的 test
属性是否合法? 还是必须将测试限制在单个test
属性中,以便它们不会在整个输入中漫游? 或者,换句话说,这合法吗?
<xsl:when test="../following-sibling::*[1]
/hexagon:PointCode[@codeLinework='none']
or
../../following-sibling::*[1]
/hexagon:Point[@lineworkFlag='START LINJE']">
do something...
</xsl:when>
还是必须重写为
<xsl:when test="../following-sibling::*[1]
/hexagon:PointCode[@codeLinework='none'] ">
do something...
</xsl:when>
<xsl:when test="../../following-sibling::*[1]
/hexagon:Point[@lineworkFlag='START LINJE']">
do the exact same something...
</xsl:when>
这个问题(或:那些问题)的答案是:是的,test
可能有一个or
作为其顶级运算符;不,or
的两个操作数不需要相关,或者通过任何可定义的邻近度量来解决彼此接近的元素。 第一种形式(一种xsl:when
)很好,并且每当"做某事"很复杂时,首选于第二种形式(两个xsl:when
元素)。
如果我上面的猜测是正确的,那么你的代码是合法的新闻将消除你试图解决的任何问题的一种可能的解释,但留下一个悬而未决的问题"那为什么我没有得到我期望的输出? 由于您尚未提供将触发此关键代码的示例输入,也没有说明所需的输出和当前获得的输出,因此这里的任何人都无法回答这个未提出的问题。
目前,很明显,您本质上是在编写带有尖括号的过程代码;如果您努力获得一种更具声明性的样式(包括我在内的大多数人似乎意味着,除其他外,使用 xsl:apply-templates
提供的隐式循环而不是xsl:for-each
,您可能会发现 XSLT 变得更容易使用, 并在模板上使用匹配模式来选择/何时)。 或者你可能没有;不是每个人都这样做。
作为说明,以下是以不同样式重写样式表:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:landxml="http://www.landxml.org/schema/LandXML-1.2"
xmlns:hexagon="http://xml.hexagon.com/schema/HeXML-1.7"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"
version="1.0"
encoding="UTF-16"
indent="no"
omit-xml-declaration="yes"/>
<xsl:template match="hexagon:Point
[following-sibling::*[1]
/hexagon:PointCode
/@codeLinework = 'none']
/hexagon:PointCode">
<xsl:call-template name="do-something"/>
</xsl:template>
<!--* pattern on following template seems likely wrong *-->
<xsl:template match="hexagon:HexagonLandXML
[following-sibling::*[1]
/hexagon:Point
/@lineworkFlag = 'START LINJE']
//hexagon:PointCode">
<xsl:call-template name="do-something"/>
</xsl:template>
<xsl:template name="do-something">
do something ...
</xsl:template>
</xsl:stylesheet>
如果您的输入像您的示例所暗示的那样有规律,那么您的条件可以归结为"下一个后续 PointCode 元素具有 @codeLinework='none',或者下一个后续 Point 元素具有 @lineworkFlag='START LINJE'。 如果是这样,那么条件可以缩短一些:
<xsl:template match="hexagon:PointCode
[following::hexagon:PointCode[1]
/@codeLinework = 'none'
or
following::hexagon:Point[1]
@lineworkFlag='START LINJE']">
do something...
</xsl:template>
条件的复杂性可能会向一些读者(对我来说确实如此)表明,XML 的设计可能会被有效地更改以允许更直接的处理。 但这超出了你问题的范围。