2012-03-29 122 views
3

我正在转换以下XML以生成HTML。XSLT for each each complex condition

XML

<clause code="section6"> 
     <variable col="1" name="R1C1" row="1">Water</variable> 
     <variable col="2" name="R1C2" row="1">true</variable> 
     <variable col="1" name="R2C1" row="2">Gas</variable> 
     <variable col="2" name="R2C2" row="2"></variable> 
     <variable col="1" name="R3C1" row="3">Petrol</variable> 
     <variable col="2" name="R3C2" row="3">true</variable> 
<clause> 

XSLT

1: <xsl:for-each select="$clause/variable[@col='1']"> 
2: <xsl:sort select="@row" data-type="number"/> 
3: <xsl:variable name="row-id" select="@row"/> 
4: <xsl:variable name="row" select="$clause/variable[@row=$row-id]"/> 
5: <xsl:if test="$clause/variable[@col='2' and @row=$row-id]='true'"> 
6:  <xsl:value-of name="row-no" select="concat(position(), ') ')"/> 
7:  <xsl:value-of select="$clause/variable[@col='1' and @row=$row-id]"/> 
8: </xsl:if> 
9: </xsl:for-each> 

改造工作正常,结果显示的1)水3)汽油

的问题是序列号。您可以在第5行筛选行上看到条件,该行只有'true'col 2和position()用于显示序号。我不能在XLST运行计数器。

我想知道是否可以在行1中添加第5行的条件。以上例子的结果应该是1)水2)巡逻有什么建议吗?

+0

这是一个很好的问题和令人惊讶的事实是它有一个解决方案,它是一个XPath 2.0表达式。在XSLT 1.0中,使用密钥可以实现简短,优雅且*高效*的解决方案。 +1。 – 2012-03-29 04:28:08

回答

3

这是做你想做的吗?

我推动了第2栏上的每个选择都是正确的。这样的位置,这等于我们是在选定节点集合将等于2不3

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0"> 

    <xsl:template match="/"> 
     <xsl:for-each select="clause/variable[@col='2' and text()='true']"> 
      <xsl:sort select="@row" data-type="number"/> 
      <xsl:variable name="row-id" select="@row"/> 
      <xsl:value-of select="concat(position(), ') ')"/> 
      <xsl:value-of select="/clause/variable[@col='1' and @row=$row-id]"/> 
     </xsl:for-each>   
    </xsl:template> 

</xsl:stylesheet> 

虽然我可能会使用的模板优先于对,每使用电流()让我们不要不需要row-id变量:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0"> 

    <xsl:template match="/"> 
     <xsl:apply-templates select="clause/variable[@col='2' and text()='true']"> 
      <xsl:sort select="@row" data-type="number"/>    
     </xsl:apply-templates>   
    </xsl:template> 

    <xsl:template match="clause/variable[@col='2' and text()='true']"> 
     <xsl:value-of select="concat(position(), ') ')"/> 
     <xsl:value-of select="/clause/variable[@col='1' and @row=current()/@row]"/> 
    </xsl:template> 

</xsl:stylesheet> 
+0

完美的作品。谢谢 – Matt 2012-03-29 04:10:25

2

我不认为你可以使用单个XPath 1.0表达式来表达它。

在XSLT 1.0我将使用密钥,并将该溶液变短,优雅高效

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text"/> 
<xsl:key name="kVarCol2" match="variable[@col=2]" use="@row"/> 

<xsl:template match="/*"> 
    <xsl:for-each select="variable[@col='1'][key('kVarCol2', @row)='true']"> 
    <xsl:sort select="@row" data-type="number"/> 
     <xsl:value-of select="concat('&#xA;', position(), ') ', .)"/> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

当这个变换所提供的XML文档应用(校正为进行良好的形成) :

<clause code="section6"> 
    <variable col="1" name="R1C1" row="1">Water</variable> 
    <variable col="2" name="R1C2" row="1">true</variable> 
    <variable col="1" name="R2C1" row="2">Gas</variable> 
    <variable col="2" name="R2C2" row="2"></variable> 
    <variable col="1" name="R3C1" row="3">Petrol</variable> 
    <variable col="2" name="R3C2" row="3">true</variable> 
</clause> 

想要的,正确的结果产生

1) Water 
2) Petrol 

II。的XPath 2.0(单一表达)溶液:

for $i in 1 to max(/*/*/@row/xs:integer(.)) 
    return 
     /*/variable[@row eq string($i)] 
      [@col eq '1' 
      and 
      ../variable 
       [@row eq string($i) 
       and 
        @col eq '2' 
       and 
        . eq 'true' 
       ] 
      ] 
      /concat('&#xA;', position(), ') ', .) 

当这个XPath 2.0表达在相同的XML文档(上文)进行评价,结果是相同的期望字符串

1) Water 
2) Petrol 
+0

我仍然没有掌握XSLT 2.我维护的代码库都使用XSLT 1,即使我们使用的是Saxon 9.我还没有找到一个好的资源,在1中说过你曾经这么做过 - 在2不要这样做 - 你知道吗? – Kevan 2012-03-29 04:50:59

+0

@Kevan:我记得最近在xslt标签中有这样一个问题,Michael Kay和我都回答了​​。 – 2012-03-29 05:12:34