2012-03-30 67 views
1

我完全不熟悉xslt,所以请原谅我,如果这是一个愚蠢的问题。 我需要声明一个变量,并将它指向xml中2个可能的节点之一,具体取决于它们实际上存在哪个节点。我想以下几点:使用取决于测试的指定节点到xsl:变量

<xsl:variable name="DealNode"> 
    <xsl:choose> 
     <xsl:when test="/AllResponse/Deals/Deal"><xsl:copy-of select="/AllResponse/Deals/Deal"/></xsl:when> 
     <xsl:otherwise><xsl:copy-of select="/AllResponse/BookDeals/BookDeal"/></xsl:otherwise> 
    </xsl:choose> 
</xsl:variable> 

这似乎工作,在DealNode确实出现了我所期望的。但是,如果我现在这样做:

<xsl:variable name="TradeNode" select="$DealNode/Trades/Trade"/> 

TradeNode保持空白。我究竟做错了什么?

示例XML:

<AllResponse> 
    <Deals> 
     <Deal> 
      <Trades> 
       <Trade> 
       </Trade> 
      </Trades> 
     </Deal> 
    </Deals> 
</AllResponse> 
+0

你在使用XSLT 1还是2? – 2012-03-30 17:15:26

+0

对不起,应该说它的xslt 1 .. – StevieG 2012-03-30 17:17:06

+0

@StevieG:注意到目前接受的答案是相当有问题的可能是有用的。欲了解更多信息,请阅读我的答案。 – 2012-03-31 04:14:56

回答

2

一种方法以定义变量如下:

<xsl:variable name="DealNode" select="(/AllResponse/Deals/Deal | /AllResponse/BookDeals/BookDeal)[1]"/> 

形成所选的两个节点集的联合与采取第一如果第一个表达式选择了一个节点,那么如果第一个表达式没有选择任何内容,那么第二个表达式将选择第一个节点。

+0

工程款待,非常感谢! – StevieG 2012-03-30 17:40:12

+0

不好意思,但是这可以在一个序列上工作 - 两个*节点集合*是一个新的节点集合,其中节点(按定义)是按照文档顺序。因此,在一般情况下'($ ns1 | $ ns2)[1]'不会选择'$ ns1'的第一个节点 - 而是选择两个节点集合的第一个节点(按文档顺序) - 这可能是属于'$ ns'的节点或属于'$ ns2'的节点。请改正。 – 2012-03-31 03:03:53

+0

-1,因为答案包含非真实陈述,并且通常是一个错误的解决方案,可能会混淆和误导XPath的学习者。 – 2012-03-31 04:09:06

0

XSLT1不完全支持的结果树片段。做你正在尝试的需要exsl:node-set()

此外,即使在XSLT2,正确的XPath是$DealNode/Deal/Trades/Trade

3

目前接受的答案有一个严重的问题。如果它的XPath表达式对下面的XML文档评价:

<AllResponse> 
    <BookDeals> 
     <BookDeal> 
      <Trades> 
       <Trade> 
       </Trade> 
      </Trades> 
     </BookDeal> 
    </BookDeals> 
    <Deals> 
     <Deal> 
      <Trades> 
       <Trade> 
       </Trade> 
      </Trades> 
     </Deal> 
    </Deals> 
</AllResponse> 

然后,相反的答案索赔,所提供的XPath表达式

(/AllResponse/Deals/Deal | /AllResponse/BookDeals/BookDeal)[1] 

不选择工会的第一个论点,但恰恰相反(第二个参数)。

原因是联合运算的结果总是按其节点的文档顺序排序 - 换句话说,节点集是一个集合而不是一个序列。

这里是一个正确的解决方案

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="/"> 
    <xsl:variable name="vDealNode" select= 
     "/*/Deals/Deal | /*[not(Deals/Deal)]/BookDeals/BookDeal"/> 

    <xsl:copy-of select="$vDealNode"/> 
</xsl:template> 
</xsl:stylesheet> 

当该变换是在上面的XML文档,有用的,正确的结果(即联合操作的第一个参数的节点)施加是选择和该选择的结果被输出:

<Deal> 
    <Trades> 
     <Trade/> 
    </Trades> 
</Deal> 

说明:正确的基因当我们要选择$ns1在条件$condtrue(),并选择$ns2$cond是假拉尔则表达式中使用,方法是:

$ns1[$cond] | $ns2[not($cond)] 

在我们的具体情况:

$ns1/*/Deals/Deal

$ns2/*/BookDeals/BookDeal

$condboolean(/*/Deals/Deal)

在一般表达式代以上这些,并缩短

/*/Deals/Deal[/*/Deals/Deal]

到:

/*/Deals/Deal

我们在表达我们到达在这个答案中回答

/*/Deals/Deal | /*[not(Deals/Deal)]/BookDeals/BookDeal 
+1

我发现这个答案适用于我(使用XSLT 1.0),而接受的答案没有。 – 2015-01-21 20:58:15

+0

@ B.Mo,不客气。 – 2015-01-21 22:19:10