2014-07-14 44 views
0

我有很多類似的操作,例如,檢查一個標籤是兩個其他標籤的總和。 要編寫一次,接下來我做的:XSLT-1.0數組禁用排序

<xsl:variable name="psumArray" select="//AAA/SUM1 | //AAA/SUM2"/> 
    <xsl:variable name="psummandArray1" select="//AAA/A1 | //AAA/A2"/> 
    <xsl:variable name="psummandArray2" select="//AAA/B1 | //AAA/B2"/> 

    <xsl:for-each select="$psumArray"> 
     <xsl:variable name="temppos" select="position()"></xsl:variable> 
     <xsl:if test=" format-number((text()), '#.##') != format-number(number($psummandArray1[$temppos]/text()) + number($psummandArray2[$temppos]/text())), '#.##')"> 
      <ERROR>error!</ERROR> 
     </xsl:if> 
    </xsl:for-each> 

而且我可以把我的數組變量任意數量的「選擇」的。但是我發現每個數組都按名稱排序。數組中成員的順序不是由我編寫的順序定義的,而是由選擇的文本比較定義的。

即:

<xsl:variable name="psummandArray2" select="//AAA/B3 | //AAA/B2"/> 

會變成:

<xsl:variable name="psummandArray2" select="//AAA/B2 | //AAA/B3"/> 

排序後。 如何避免它?或者如何以另一種方式實現我想要的,如果這種方式不是最好的?

UPD: 開關輸入XML類似於:

<XML> 
    <A1>50</A1> 
    <A2>20</A2> 
    <A3>70</A3> 
    <A4>90</A4> 
    <A5>5</A5> 
    <A6>45</A6> 
    <A7>35</A7> 
    <A8>25</A8> 
    <A9>80</A9> 
    <A10>110</A10> 
    <A11>100</A11> 
    <A12>30</A12> 
    <A13>70</A13> 
    ... 
    <A120>33</A120> 
</XML> 

且存在規則,如:

A3 = A6 + A8 
A13 = A1 + A2 

等更多的則百條規則。我必須編寫能夠檢查所有這些規則的XSLT,並且如果某些節點的規則錯誤,我必須打印<ERROR>Error!</ERROR>

我認爲最好的方法是編寫XSLT,在這裏我只需添加sum節點的名稱和summand節點的名稱。

這就是爲什麼我寫了如上所述的xslt來檢查它。現在我只是想把所有的規則都放到數組中。然後我發現它排序陣列,打破了我的計劃:-)

+1

XML/XSL中沒有數組。你有什麼是節點集。如果您不對它們進行排序,它們將按照文檔順序進行處理(不按名稱,如您所想)。 - P.S.如果您使用XSLT 1.0或2.0,請指出(總是!)。 –

+0

謝謝,解決了。 – Arkady

+0

我會考慮使用類似用於實現Schematron的方法,有一種語言來編寫規則,然後有一個樣式表處理規則文檔以生成相應的XSLT樣式表,檢查規則並輸出錯誤或斷言。 –

回答

1

我〜100個任務,以檢查是否一個節點在兩個節點的另一個的總和。 我不想寫比較 - 100倍

那麼,你必須把它寫了至少一次,因爲它似乎並沒有遵循任何一種邏輯的,可以實現自動化。這裏是你可以做的一種方式:

<?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" version="1.0" encoding="UTF-8" indent="yes" /> 

<xsl:template match="/XML"> 
    <xsl:variable name="tests"> 
     <xsl:call-template name="test-sum"> 
      <xsl:with-param name="sum" select="A3"/> 
      <xsl:with-param name="summands" select="A6 | A8"/> 
     </xsl:call-template>  
     <xsl:call-template name="test-sum"> 
      <xsl:with-param name="sum" select="A13"/> 
      <xsl:with-param name="summands" select="A1 | A2"/> 
     </xsl:call-template>  
     <!-- ... --> 
    </xsl:variable> 
    <xsl:if test="contains($tests, 'error')"> 
     <ERROR>Error!</ERROR> 
    </xsl:if> 
</xsl:template> 

<xsl:template name="test-sum"> 
    <xsl:param name="sum"/> 
    <xsl:param name="summands"/> 
    <xsl:if test="$sum!=sum($summands)"> 
     <xsl:text>error</xsl:text> 
    </xsl:if> 
</xsl:template> 

</xsl:stylesheet> 

或者,你可以表達你的規則爲XML - 無論是外部文件中,或者在樣式表本身,然後將模板應用到這一點。

+0

太棒了,那有效! – Arkady

+0

現在我需要根據錯誤得到輸出(對於A3 = A6 + A8,錯誤文本應該是:「abrakadabra」,對於A13 = A1 + A2,它應該是「Winter is coming」),並且如果有5個錯誤 - 我必須輸出5次不同的文字。 我想爲模板「測試總和」添加額外的參數 - 用那個文本,用其他參數給它。然後以某種方式打印它。 – Arkady

+0

您可以(1)將錯誤消息作爲附加參數傳遞,並(2)直接輸出結果 - 最好(恕我直言)作爲XML - 而不先通過變量。 –

1

使用XSLT 2.0和XSLT 2.0處理器,您可以使用例如, <xsl:variable name="psumArray" select="//AAA/SUM1 , //AAA/SUM2"/>以獲得SUM1元素的序列,然後是SUM2元素。

+0

哇,謝謝,但我害怕我使用XSLT 1.0,那麼我該怎麼辦? – Arkady

+0

@Arkady也許你應該使用一個命名模板;沒有看到示例輸入和理解任務的範圍,很難看到「節省」是什麼。 –

+0

@Arkady,我同意邁克爾的觀點,很難告訴你如何在沒有看到描述性輸入樣本和你想要的樣本結果的情況下解決這個問題。您可能想編輯您的問題並提供更多詳細信息。 –