2016-12-07 83 views
0

我想使用逐項列表,而不是硬中斷,見例如:計數前面的節點返回意外的結果

<para>line1<?linebreak?> 
line2<?linebreak?> 
line3</para> 

不過,我遇到我這樣可防止處理第二行遞歸模板怪異的行爲正確。我創建了簡化的測試用例 - 不再遞歸。如果count(preceding::processing-instruction('linebreak')) = 0表達式以這種方式使用,則不返回任何內容,但我期望第二行。

<line>line1</line><node> 
line2<?linebreak?> 
line3</node> 
line2 

<node>這個元件是用於調試的。它證實了我處理預期數據。

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

    <xsl:template match="para[processing-instruction('linebreak')]"> 
     <xsl:call-template name="getLine"> 
      <xsl:with-param name="node" select="./node()"/> 
     </xsl:call-template> 
    </xsl:template> 

    <xsl:template name="getLine"> 
     <xsl:param name="node"/> 

     <line> 
      <xsl:copy-of 
       select="$node/self::processing-instruction('linebreak')[not(preceding::processing-instruction('linebreak'))]/preceding::node()" 
      /> 
     </line> 

     <xsl:call-template name="getSecondLine"> 
      <xsl:with-param name="node" 
       select="$node/self::processing-instruction('linebreak')[not(preceding::processing-instruction('linebreak'))]/following::node()" 
      /> 
     </xsl:call-template> 

    </xsl:template> 

    <xsl:template name="getSecondLine"> 
     <xsl:param name="node"/> 

     <node> 
      <xsl:copy-of select="$node"/> 
     </node> 

     <xsl:copy-of 
      select="$node/self::processing-instruction('linebreak')[count(preceding::processing-instruction('linebreak')) = 0]/preceding::node()" 
     /> 
    </xsl:template> 

</xsl:stylesheet> 

在Saxon HE/EE 9.6.0.7(在Oxygen XML Editor 18中)測試。

+0

獨立於您當前的XSLT代碼,請提供您期望的輸入示例的參考輸出。 – Tomalak

+0

那麼你想實現什麼?在XSLT/XPath 2.0世界中,我會考慮一個分項列表,它只是一個值序列,例如'('line1','line2','line3')'。你想把你輸入的樣本變換成一系列字符串還是一系列'line'元素?爲什麼該段落包含處理指令以指示文本中的換行符和換行符?有沒有比純文本節點和''para''元素內的''處理指令更復雜的東西? –

+0

@MartinHonnen行是混合內容,而不是純文本。我試圖在PI之前複製所有節點,並將其餘節點傳遞給下一次迭代。然而,這個「休息」的行爲與第一次迭代不同。 –

回答

2

第一斷行的處理正常工作:

<line> 
    <xsl:copy-of 
    select="$node/self::processing-instruction('linebreak') 
       [not(preceding::processing-instruction('linebreak'))] 
       /preceding::node()"/> 
</line> 

雖然只對這個樣品;對於更復雜的數據,您將得到錯誤的結果,因爲您應該使用軸,而不是軸使用preceding-sibling軸。

select="$node[self::processing-instruction('linebreak')][1] 
     /preceding-sibling::node()" 

第二斷行的處理似乎很困惑:

但代碼可以大大簡化,因爲我會寫select表達。要傳遞的參數

$node/self::processing-instruction('linebreak') 
    [not(preceding::processing-instruction('linebreak'))] 
    /following::node()" 

其有效地是

select="$node[self::processing-instruction('linebreak')][1] 
      /following-sibling::node()" 

其選擇三個節點

line2<?linebreak?>line3 

(加空白),其要在<node>元件內輸出,產生

<node>line2<?linebreak?>line3</node> 

(再次忽略空格)

,然後這樣做

select="$node/self::processing-instruction('linebreak') 
    [count(preceding::processing-instruction('linebreak'))=0] 
    /preceding::node()" 

這裏$node/self::processing-instruction('linebreak')選擇這些三個節點的第二,這是第二斷行處理指令。前面(或前面兄弟)處理指令的計數是1,因爲你正在處理的是第二個。

我不太確定你在想什麼,但我懷疑你的錯誤是認爲「之前」和「跟隨」選擇相對於$node序列內節點的位置,而不是相對於原始源樹中的其他節點。我建議閱讀描述各種軸的XPath參考書。

+0

這裏我最大的錯誤是使用斜槓'$ node/self :: processing-instruction('linebreak')'而不是方括號'$ node [self :: processing-instruction('linebreak')]' - 之所以簡單[ 1]沒有選擇任何東西,所以我讓事情變得更加複雜。 –

+0

我仍然不明白爲什麼在getSecondLine(使用Michael的提議修改)中選擇'$ node [self :: processing-instruction('linebreak')] [1]/preceding-sibling :: node()'返回'line1 line2'當'line1'沒有出現在傳遞的'$ node'參數中的任何地方。 –

+1

因爲$ node是一個節點列表,並且這些節點之前的兄弟節點不在$ node中,並且通過使用前面的兄弟節點(或前面的節點),您可以找到這些節點。 –