2014-12-13 128 views
0

我需要使用Xpath1.0遍歷XML中2個層次的嵌套循環。在XPath嵌套迭代中獲取當前索引

迭代時,它應該打印元素值'Y',如果它是第二級別的第一個元素並且當前索引作爲計數器。

我能夠完成其中一件事情,但不能同時完成。 例如如果我在第一個循環上迭代並使用position(),它會給我當前索引,但我無法確定它是否是第二級的第一個元素。同樣,如果我迭代第二循環,我沒有得到實際的指數,但得到它是否是第一個元素使用position()= 1

我附上了一個示例請求和預期響應。

<root> 
    <level1> 
     <level2>name1</level2> 
     <level2>name2</level2> 
    </level1> 
    <level1> 
     <level2>name3</level2> 
     <level2>name4</level2> 
     <level2>name5</level2> 
    </level1> 
    <level1> 
     <level2>name6</level2> 
     <level2>name7</level2> 
    </level1> 
</root> 

結果應該是這樣的:

name1_Y_1 
name2_N_2 
name3_Y_3 
name4_N_4 
name5_N_5 
name6_Y_6 
name7_N_7 

這裏是現有代碼:

<root> 
    <xsl:for-each select="$Map-Data/root/level1/level2"> 
     <xsl:choose> 
      <xsl:when test="position() = 1"> 
       <names> 
        <xsl:value-of select="concat(current(), '_Y_', position())"/> 
       </names> 
      </xsl:when> 
      <xsl:otherwise> 
       <names> 
        <xsl:value-of select="concat(current(), '_N_', position())"/> 
       </names> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:for-each> 
</root> 
+0

請解釋一下其中的語言你正在寫的「嵌套循環」,向我們證明代碼。 – 2014-12-13 17:19:52

+0

它在XPath編輯器中的Tibco BusinessWorks中。 – 2014-12-13 17:32:20

+0

...「並向我們顯示該代碼」。我只能繼續馬丁。 – 2014-12-13 17:49:56

回答

1

在XPath 2.0,你可以做

//level2/concat(., if (not(preceding-sibling::*)) then '_Y' else '_N', '_', position()) 

在XPath 1.0你需要確保你檢查在迭代//level2時使用preceding-sibling::*,並以您的主機語言進行字符串連接。

由於現在你已經顯示的示例使用XSLT我會做

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 

<xsl:output indent="yes"/> 

<xsl:template match="root"> 
    <xsl:copy> 
    <!-- <xsl:apply-templates select="$Map-Data/root/level1/level2"/> --> 
    <xsl:apply-templates select="level1/level2"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="level2[not(preceding-sibling::*)]"> 
    <names> 
    <xsl:value-of select="concat(., '_Y_', position())"/> 
    </names> 
</xsl:template> 

<xsl:template match="level2[preceding-sibling::*]"> 
    <names> 
    <xsl:value-of select="concat(., '_N_', position())"/> 
    </names> 
</xsl:template> 

</xsl:stylesheet> 
+0

感謝Martin的回覆,但我無法在XPath 1.0中使用preceding-sibling :: *,編輯器抱怨說*是意想不到的。 – 2014-12-13 18:32:21

+0

您不能使用我在XSLT/XPath 1.0中發佈的XPath 2.0表達式,但我編輯了我的答案並添加了一個XSLT 1.0樣式表來檢查'preceding-sibling :: *'。 – 2014-12-13 18:46:12

+0

我不能直接使用純XSLT,並且XPath編輯器不允許我使用前同步,是否有任何其他方式來完成此操作。 – 2014-12-13 19:23:14

1

之所以你的方法是行不通的是,在選擇:

<xsl:for-each select="/root/level1/level2"> 

您選擇所有level2元素作爲單個節點集 - 並且只有一個整個集的成員可以位於#1位置。

OTOH,如果你要拆您的選擇是這樣的:

<xsl:for-each select="/root/level1"> 
    <xsl:for-each select="level2"> 
     <xsl:choose> 
      <xsl:when test="position() = 1"> 
       <names> 
        <xsl:value-of select="concat(current(), '_Y_', position())"/> 
       </names> 
      </xsl:when> 
      <xsl:otherwise> 
       <names> 
        <xsl:value-of select="concat(current(), '_N_', position())"/> 
       </names> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:for-each> 
</xsl:for-each> 

你會處理一個單獨的節點,設置每個level1元素,從而實現自己的具有位置#個人level2元素的目標每批1個。

但是,您不能使用相同的position()函數來連續編號所有元素,因爲它會在每個level1更改(這是您如何獲得Y/N函數的工作方式)時重新啓動。爲此,您必須使用另一種編號機制,例如xsl:number

<xsl:for-each select="root/level1"> 
    <xsl:for-each select="level2"> 
     <names> 
      <xsl:value-of select="."/> 
      <xsl:choose> 
       <xsl:when test="position() = 1">_Y_</xsl:when> 
       <xsl:otherwise>_N_</xsl:otherwise> 
      </xsl:choose> 
      <xsl:number level="any"/> 
     </names> 
    </xsl:for-each> 
</xsl:for-each> 
+0

我已經在問題陳述中提到我一次只能完成其中一件事情。是否有任何其他方式,然後使用前兄弟獲得這個結果? – 2014-12-13 19:20:31

+0

@AnkurJain您是否看到過我在評論前幾秒鐘添加的修改? – 2014-12-13 19:23:46

+0

我現在看到它,但我無法添加純粹的XSLT,因爲我正在使用XPath編輯器。它不允許我添加'xsl:number'。 – 2014-12-13 19:37:02