2013-05-28 47 views
1

我試圖從前面的元素檢索值。但是,我嘗試檢索的值需要在某個位置之後並在其他節點位置之前。我怎樣才能做到這一點?檢索XML節點位置之間的值

例XML:

<?xml version="1.0" encoding="UTF-8"?> 
<actions> 
    <action> 
     <code>tr</code> 
     <value>503</value> 
    </action> 
    <action> 
     <code>co</code> 
     <value>0</value> 
    </action> 
    <action> 
     <code>cou</code> 
     <value>0</value> 
    </action> 
    <action> 
     <code>tr</code> 
     <value>87</value> 
    </action> 
    <action> 
     <code>st</code> 
     <value>0</value> 
    </action> 
    <action> 
     <code>wta</code> 
     <value>0</value> 
    </action> 
    <action> 
     <code>pi</code> 
     <value>0</value> 
    </action> 
    <action> 
     <code>tr</code> 
     <value>64</value> 
    </action> 
    <action> 
     <code>st</code> 
     <value>0</value> 
    </action> 
    <action> 
     <code>del</code> 
     <value>0</value> 
    </action> 
    <action> 
     <code>tr</code> 
     <value>27</value> 
    </action> 
    <action> 
     <code>wa</code> 
     <value>0</value> 
    </action> 
    <action> 
     <code>dec</code> 
     <value>0</value> 
    </action> 
</actions> 

電流XSLT:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="xs fn"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 

    <xsl:template match="/actions"> 
     <result> 
      <!-- Loop through all action elements --> 
      <xsl:for-each select="action"> 
       <!-- Display only the needed action in the result file --> 
       <xsl:if test="code = 'co' or code = 'st' or code = 'dec' or code = 'pi' or code = 'del'"> 
        <action> 
         <code> 
          <xsl:choose> 
           <xsl:when test="code = 'co'">1</xsl:when> 
           <xsl:when test="code = 'st'">5</xsl:when> 
           <xsl:when test="code = 'dec'">2</xsl:when> 
           <xsl:when test="code = 'pi'">3</xsl:when> 
           <xsl:when test="code = 'del'">4</xsl:when> 
          </xsl:choose> 
         </code> 
         <!-- Get some positions in variables --> 
         <xsl:variable name="previousPosition"><xsl:value-of select="position() - 1" /></xsl:variable> 
         <xsl:variable name="lastTRPosition"><xsl:value-of select="count((preceding::action[code = 'tr'])[last()]/preceding::action)+1" /></xsl:variable> 
         <xsl:variable name="currentPosition"><xsl:value-of select="position()" /></xsl:variable> 
         <!-- Should be the value of the preceding action element with code 'tr' (last occurence). But only use when between the last preceding action element with code 'tr' and the current node position NO known code is used ('co', 'st', 'dec', 'pi' or 'del') --> 
         <value> 
            <xsl:choose> 
             <xsl:when test="(preceding::action[code = 'tr']/value)[last()] != ''"> <!-- some work to do here --> 
              <xsl:value-of select="round((preceding::action[code = 'tr']/value)[last()])" /> 
             </xsl:when> 
             <xsl:otherwise>0</xsl:otherwise> 
            </xsl:choose> 
         </value> 
        </action> 
       </xsl:if> 
      </xsl:for-each> 
     </result> 
    </xsl:template> 
</xsl:stylesheet> 

當前結果:

<?xml version="1.0" encoding="UTF-8"?> 
<result> 
    <action> 
     <code>1</code> 
     <value>503</value> 
    </action> 
    <action> 
     <code>5</code> 
     <value>87</value> 
    </action> 
    <action> 
     <code>3</code> 
     <value>87</value> 
    </action> 
    <action> 
     <code>5</code> 
     <value>64</value> 
    </action> 
    <action> 
     <code>4</code> 
     <value>64</value> 
    </action> 
    <action> 
     <code>2</code> 
     <value>27</value> 
    </action> 
</result> 

通緝的結果:

<?xml version="1.0" encoding="UTF-8"?> 
<result> 
    <action> 
     <code>1</code> 
     <value>503</value> 
    </action> 
    <action> 
     <code>5</code> 
     <value>87</value> 
    </action> 
    <action> 
     <code>3</code> 
     <value>0</value> 
    </action> 
    <action> 
     <code>5</code> 
     <value>64</value> 
    </action> 
    <action> 
     <code>4</code> 
     <value>0</value> 
    </action> 
    <action> 
     <code>2</code> 
     <value>27</value> 
    </action> 
</result> 

的變化,爲什麼?

<action> 
    <code>3</code> 
    <value>87</value> <!-- should be 0 --> 
</action> 

這應該是0。因爲最後action/code = 'tr'的位置和該節點的當前位置()中的結果寫是之間的已知代碼「ST」,其具有已經此值。

<action> 
    <code>4</code> 
    <value>64</value> 
</action> 

這應該是0。因爲最後action/code = 'tr'的位置和該節點的當前位置()中的結果寫是之間的已知代碼「ST」,其具有已經此值。

我有點卡在xsl:when中獲得正確的測試。有人可以協助嗎?

回答

1

我建議與group-starting-with分組,然後使用>>運算符進行過濾。我也做了映射參數,並使用一鍵有效地映射,所以乾脆我得到

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="xs fn"> 

    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 

    <xsl:key name="code" match="code" use="@from"/> 

    <xsl:param name="code-map"> 
     <code from="co" to="1"/> 
     <code from="st" to="5"/> 
     <code from="dec" to="2"/> 
     <code from="pi" to="3"/> 
     <code from="del" to="4"/> 
    </xsl:param> 

    <xsl:template match="/actions"> 
     <result> 
      <xsl:for-each-group select="action" group-starting-with="action[code = 'tr']"> 
       <xsl:variable name="tr-head" select="."/> 
       <xsl:apply-templates select="current-group()[self::action[code = $code-map/code/@from]]"> 
       <xsl:with-param name="tr" select="$tr-head"/> 
       </xsl:apply-templates> 
      </xsl:for-each-group> 
     </result> 
    </xsl:template> 

    <xsl:template match="action"> 
     <xsl:param name="tr"/> 
     <xsl:copy> 
     <code> 
      <xsl:value-of select="key('code', code, $code-map)/@to"/> 
     </code> 
     <value> 
      <xsl:value-of 
      select="if (not(exists((current-group() except $tr) 
            [current() >> . and code = $code-map/code/@from]))) 
        then $tr/value else 0"/> 
     </value> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

當我使用撒克遜9.5變換輸入

<?xml version="1.0" encoding="UTF-8"?> 
<actions> 
    <action> 
     <code>tr</code> 
     <value>503</value> 
    </action> 
    <action> 
     <code>co</code> 
     <value>0</value> 
    </action> 
    <action> 
     <code>cou</code> 
     <value>0</value> 
    </action> 
    <action> 
     <code>tr</code> 
     <value>87</value> 
    </action> 
    <action> 
     <code>st</code> 
     <value>0</value> 
    </action> 
    <action> 
     <code>wta</code> 
     <value>0</value> 
    </action> 
    <action> 
     <code>pi</code> 
     <value>0</value> 
    </action> 
    <action> 
     <code>tr</code> 
     <value>64</value> 
    </action> 
    <action> 
     <code>st</code> 
     <value>0</value> 
    </action> 
    <action> 
     <code>del</code> 
     <value>0</value> 
    </action> 
    <action> 
     <code>tr</code> 
     <value>27</value> 
    </action> 
    <action> 
     <code>wa</code> 
     <value>0</value> 
    </action> 
    <action> 
     <code>dec</code> 
     <value>0</value> 
    </action> 
</actions> 

我得到了想要的結果

<result> 
    <action> 
     <code>1</code> 
     <value>503</value> 
    </action> 
    <action> 
     <code>5</code> 
     <value>87</value> 
    </action> 
    <action> 
     <code>3</code> 
     <value>0</value> 
    </action> 
    <action> 
     <code>5</code> 
     <value>64</value> 
    </action> 
    <action> 
     <code>4</code> 
     <value>0</value> 
    </action> 
    <action> 
     <code>2</code> 
     <value>27</value> 
    </action> 
</result> 
+0

馬丁,你能解釋該行'的' ,因爲我嘗試將解決方案插入到總體樣式表中,但我無法正常工作。看起來這行不給任何輸出。請在此處查看完整的源XML和XSLT:http://pastebin.com/JC9Gqdgb –

+0

由於文檔「xmlns =」中的默認命名空間,因此出現此問題。http://www.company.com/log/lk/pl 「'。我不明白爲什麼 –

+0

@MarkVeenstra,因爲你的XSLT爲元素定義了一個默認名稱空間,所以我設置的'param'中的元素最終也在這個名字空間中,並且這樣就成爲$ code-map/code/@ from'不會選擇它們。你需要在參數上加上' ...'來避免這個問題。 –

0

只因爲我說明了,這裏是一個xslt-1.0解決方案。

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

    <xsl:template match="action" /> 

    <xsl:template match="action [code = 'co' or code = 'st' or code = 'dec' or code = 'pi' or code = 'del']" > 
     <result> 
      <xsl:copy> 
       <code> 
        <xsl:choose> 
         <xsl:when test="code = 'co'">1</xsl:when> 
         <xsl:when test="code = 'st'">5</xsl:when> 
         <xsl:when test="code = 'dec'">2</xsl:when> 
         <xsl:when test="code = 'pi'">3</xsl:when> 
         <xsl:when test="code = 'del'">4</xsl:when> 
        </xsl:choose> 
       </code> 
      <value> 
       <xsl:variable name="ptr" select="preceding-sibling::action[code='tr'][1]"/> 
       <xsl:variable name="trpos" select="count($ptr/preceding-sibling::action)"/> 
       <xsl:variable name="pcode" select="preceding-sibling::action[code = 'co' or code = 'st' or code = 'dec' or code = 'pi' or code = 'del'][1]"/> 
       <xsl:variable name="codepos" select="count($pcode/preceding-sibling::action)"/> 
       <xsl:choose> 
        <xsl:when test="$trpos >= $codepos"> 
         <xsl:value-of select="round($ptr/value)" /> 
        </xsl:when> 
        <xsl:otherwise>0</xsl:otherwise> 
       </xsl:choose> 

      </value> 
      </xsl:copy> 
     </result> 

    </xsl:template> 
    <xsl:template match="/actions"> 
     <result> 
      <xsl:apply-templates select="action" /> 
     </result> 

    </xsl:template> 
</xsl:stylesheet>