我有以下代码,如果Destination不存在,则不应显示Terminal或Attention。
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:import href="Request.xsl" />
<xsl:template name="Params">
<xsl:apply-templates select="/Params/Destinations"/>
</xsl:template>
<xsl:template name="Params">
<xsl:choose>
<xsl:when test="string-length($Destinations) > 0">
<xsl:value-of select="$Destinations"/>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:variable name="Desinations">
<xsl:for-each select="/Params/Destination1/text() |
/Params/Destination2/text() |
/Params/Destination3/text() |
/Params/Destination4/text() |
/Params/Destination5/text()">
<xsl:value-of select="."/>
<xsl:if test="name(.) = 'Destination1'">
<xsl:apply-templates select="/Params/Terminal1"/>
<xsl:apply-templates select="/Params/Attention1"/>
</xsl:if>
<!-- This xsl:if is repeated 5 more times with Destination2, Destination3, etc. -->
<xsl:if test="not(position() = last())">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:template match="Destination1">
<!-- Covered in the Destinations template -->
</xsl:template>
<xsl:template match="Terminal1">
<xsl:if test="(. != '')">
<xsl:text>-</xsl:text>
<xsl:copy-of select="." />
</xsl:if>
</xsl:template>
<xsl:template match="Attention1">
<xsl:if test="(. != '')">
<xsl:text>-</xsl:text>
<xsl:copy-of select="." />
</xsl:if>
</xsl:template>
</xsl:stylesheet>
我希望能够得到这样的结果:
Destination1-Terminal1,Destination2-Terminal2,Destination3-Terminal3-Attention3
我得到以下结果:
Destination3,Destination1,Destination2-Terminal2-Terminal3-Attention3
如您所见,目的地无序,Terminal1丢失,所有其他Terminal和Attention元素都附加到Destination2。
我不太确定如何将Destination-Terminal-Attention元素组合在一起,并将逗号放在该集合中的最后一个元素之后。例如,如果Attention没有值,我希望逗号到达终端后,如果Terminal或Attention都没有值,则逗号应该在Destination之后。
添加了XML源:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:include href="../base/Formatting.xsl" />
<xsl:template match="/">
<xsl:text>TO/</xsl:text>
<xsl:call-template name="Destinations"/>
<xsl:apply-templates select="Params"/>
</xsl:template>
<xsl:template name="Destinations" />
<xsl:template name="Params"/>
<xsl:template match="Params">
<xsl:call-template name="Params"/>
</xsl:template>
</xsl:stylesheet>
编辑:我只是通过调用Destinations对Params模板进行了更改。现在没有终端或关注字段出现,所以可能是倒退了一步。
答案 0 :(得分:0)
在XPath中,|
实际上是一个set-union操作,并不保证结果的任何特定顺序。您可以通过向for-each循环添加显式<xsl:sort>
来确保文档顺序扫描。 How to do an XSL:for-each in reverse order显示了如何向后扫描结果集;将“降序”改为“升序”应该做你想做的事。
或者你可以摆脱xsl:for-each
并将其替换为xsl:apply-templates
,将for-each的主体移动到合适的模板中。申请操作processes the selected nodes in document order unless overridden by an <xsl:sort>
。
通常情况下,如果您认为自己需要xsl:for-each
,那么您可能应该查看xsl:apply-templates
(可能使用mode
),除非您特别希望详细控制结果的顺序。 XSLT是一种非过程语言,如果你以这种方式使用它,效果最好 - “处理这些”而不是“循环这些”。
答案 1 :(得分:0)
我能够使用keshlam提供的一些建议来解决这个问题。在我的情况下,我无法访问另一个用户询问的XML输入。我认为它是在应用程序中以编程方式生成的。我的解决方案可能是XSLT的憎恶,但鉴于我的限制,它的工作原理。
我稍微修改了xsl:variable目的地:
<xsl:variable name="Destinations">
<xsl:for-each select="/StatelinkQuery/Arguments/Destination1 |
/StatelinkQuery/Arguments/Destination2 |
/StatelinkQuery/Arguments/Destination3 |
/StatelinkQuery/Arguments/Destination4 |
/StatelinkQuery/Arguments/Destination5">
<xsl:sort select="name()" order="ascending"/>
<xsl:apply-templates select="."/>
<xsl:if test="not(position() = last())">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
每个目的地的模板已更改为:
<xsl:template match="Destination1">
<xsl:value-of select="." />
<xsl:apply-templates select="/StatelinkQuery/Arguments/Terminal1"/>
<xsl:apply-templates select="/StatelinkQuery/Arguments/Attention1"/>
</xsl:template>