2011-11-09 35 views
0

因此,這是過去幾天一直困擾着我的問題。這應該相當容易,但XSLT調試起來非常痛苦。我們使用的Xalan 1.0的Java 1.6嘗試使用可變元素名稱在XSLT中打印出節點值

輸入XML

<?xml version="1.0" encoding="UTF-8"?> 
<rfb2> 
    <rfb2_item> 
     <VALDATE>2011-10-23</VALDATE> 
     <FUND_ID>300</FUND_ID> 
     <SEC_ID>34567</SEC_ID> 
    </rfb2_item> 
    <rfb2_item> 
     <VALDATE>2011-1-09</VALDATE> 
     <FUND_ID>700</FUND_ID> 
     <SEC_ID>13587</SEC_ID> 
    </rfb2_item> 
    <rfb2_item> 
     <VALDATE>2011-3-09</VALDATE> 
     <FUND_ID>200</FUND_ID> 
     <SEC_ID>999334</SEC_ID> 
    </rfb2_item> 
<rfb2> 

我們需要將XML轉換成一個逗號分隔每個rfb2_item值的列表,所以樣式表總是迭代的rfb2_item節點。我們使用的是參數在樣式表來控制其rfb2_item(valdate,fund_id,sec_id),將被輸出,以及以什麼順序的元素,例如

<xsl:param name="$outputElements" select="'VALDATE,FUND_ID'"/> 
..outputs... 

2011-10-23,300 
2011-1-09,700 
2011-3-09,200 



<xsl:param name="$outputElements" select="'SEC_ID'"/>  
..outputs... 

34567 
13587 
999334 

特殊情況下,如果$ outputElements爲「* 」,只輸出在它們出現在輸入XML

<xsl:param name="$outputElements" select="'*'"/> 

..outputs... 

2011-10-23,300,34567 
2011-1-09,700,13587 
2011-3-09,200,999334 

所以順序的元素,我的問題是我們如何寫一個模板來創建基於$ outputElements參數所需的輸出?一個工作的例子將是偉大的...

+0

你忘了問這個問題。除非你想讓某人爲你寫完整的xslt - 他們會這樣做。 – FailedDev

回答

1

是的,FailedDev是正確的。有人會爲你寫:

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

    <xsl:output method="text" /> 

    <xsl:param name="outputElements" select=" 'FUND_ID,SEC_ID,VALDATE' " /> 

    <xsl:template match="rfb2_item"> 

     <xsl:for-each select="*[contains($outputElements, local-name()) or $outputElements = '*']"> 
      <xsl:sort select="string-length(substring-before($outputElements, local-name(.)))" /> 
      <xsl:value-of select="text()" /> 
      <xsl:if test="position() != last()"> 
       <xsl:text>,</xsl:text> 
      </xsl:if> 
     </xsl:for-each> 
     <xsl:text>&#13;&#10;</xsl:text> 

    </xsl:template> 

</xsl:stylesheet> 

比特的解釋。 xsl:for-each將選擇當前名稱爲outputElements參數中包含本地名稱或outputElements參數爲*(如果情況如此,它總會產生錯誤)的當前名稱爲rfb2_item中的每個元素。然後它會根據outputElements中的本地名稱前的子字符串的長度對它們進行排序。由於該名稱稍後在該參數中出現時此值會變高,因此會根據您的參數進行排序。

示例:對於substring-before函數,元素VALDATE將產生FUND_ID,SEC_ID,而函數將返回字符串長度爲14的值。這比你在SEC_ID得到的8高,這意味着VALDATE的值是在SEC_ID之後訂購的。

xsl:sort之後,我們只是使用xsl:value-of來輸出元素值。您可能想要在那裏修剪無關的空白。最後,我們正在測試該位置是否與當前上下文中的最後一個節點的位置不相等(這是xsl:for-each排序後的),如果是,則輸出逗號。這避免了在最後一個值之後輸出逗號。

我使用xsl:text插入的換行符假定爲Windows/DOS約定。如果該文件只能使用換行符換行符而不是回車+換行符,則刪除&#13;

請注意,這不會在CSV輸出中轉義逗號!我會留給你的。使用extension functions將此任務委託給Java,如果在XSLT/XPath中證明太困難,可能會很有趣。

+0

嘿G_H,這很棒,它很有效。你只是釋放了很大的壓力,謝謝。我在樣式表頂部添加了以刪除所有空白區域。我確實有幾個問題。排序是否必要?你提出的關於字符串長度的註釋讓我擔憂,我需要考慮如果2個或更多元素具有相同的長度,就像在rfb2_item/E1和rfb2_item/E2中那樣? – raffian

+0

@RaffiM排序的目的是確保輸出字段按照您的參數確定的順序,因爲我認爲這是需求之一。檢查的字符串長度是一個子字符串,如果**參數**,而不是輸出的元素的內容。確保以參數中指定的順序輸出元素是一種技巧。基本上,必須輸出的每個元素的名稱('FUND_ID','VALDATE' ...)將產生不同的數字。這些數字根據給定的參數建立排序。 –

+0

@G_H ......這是有道理的......最後一個問題,我們試圖將你的代碼集成到一個更大的樣式表中,並且它產生了奇怪的結果。我們知道它是獨立的,但問題在於我們稱之爲問題。如果我們使用另一個已經在「/ *」上匹配的模板來調用模板(使用xsl:call-template),那麼模板代碼中會產生什麼變化以產生相同的輸出? – raffian

0

有時在這種情況下,值得考慮使用XSLT生成或修改XSLT代碼的可能性。您可以通過這種方式進一步參數化 - 例如控制輸出哪些字段,如何對它們進行排序,它們是否被分組,選擇哪些行的選擇標準等。