2012-06-07 22 views
1

我的輸入XML由以下部分組成,XSLT顯示序號

<root> 
    <entry> 
     <type>U</type> 
     <value>111</value> 
    </entry> 
    <entry> 
     <type>X</type> 
     <value>222</value> 
    </entry> 
    <entry> 
     <type>E</type> 
     <value>333</value> 
    </entry> 
    <entry> 
     <type>Q</type> 
     <value>444</value> 
    </entry> 
</root> 

輸出I需要, <ROOT> <ENTRY> <SLNO>1</SLNO> <VALUE>111</VALUE> </ENTRY> <ENTRY> <VALUE>222</VALUE> </ENTRY> <ENTRY> <VALUE>333</VALUE> </ENTRY> <ENTRY> <SLNO>2</SLNO> <VALUE>444</VALUE> </ENTRY> </ROOT>

我需要解析的所有記錄,但需要把序列號,其格式的記錄不是X和E.

我已經寫了一對 - 每個爲相同和使用'position()'顯示一個序列號的條件爲E和X型。 因此,我得到的序列號爲1,4,而不是1,2,因爲'postion()' 。

我想創建一個全局變量並在我的if塊中增加它,但XSLT 1.0將不允許增加變量值。

我該如何做到這一點?

我的樣本XSL代碼如下海拔,

<xsl:for-each select="/ROOT/ENTRY"> 
    <xsl:if test="(TYPE != 'X') and (TYPE != 'E')">    
     <xsl:text><![CDATA[<SLNO>]]></xsl:text> 
     <xsl:number value="position()"/> 
     <xsl:text><![CDATA[</SLNO>]]></xsl:text> 
    </xsl:if> 
    <!-- Printing remaining values --> 
</xsl:for-each> 

請幫助。

+0

您可能會感興趣的一個解決方案,更快(O(N) - 線性),比目前公認的一個(二次 - O(N^2) –

回答

0

代替使用位置()的,則可以指望在XML前述型元件的數量

<xsl:value-of select="count(preceding::type[. != 'X' and . != 'E']) + 1" /> 

此外,還可以通過類型元件直接匹配簡化當前的XSLT,而而不是條目元素,然後將其替換爲新元素slno元素。

<xsl:template match="type[. != 'X' and . != 'E']"> 

例如,試試下面的XSLT

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

    <xsl:template match="type[. != 'X' and . != 'E']"> 
     <slno><xsl:value-of select="count(preceding::type[. != 'X' and . != 'E']) + 1" /></slno> 
    </xsl:template> 

    <xsl:template match="type" /> 

    <xsl:template match="@*|node()"> 
     <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

當適用於您的示例XML,下面是輸出

<root> 
    <entry> 
     <slno>1</slno> 
     <value>111</value> 
    </entry> 
    <entry> 
     <value>222</value> 
    </entry> 
    <entry> 
     <value>333</value> 
    </entry> 
    <entry> 
     <slno>2</slno> 
     <value>444</value> 
    </entry> 
</root> 

注意,我使用所有小寫的元素名稱這裏。我不確定你的問題,如果你想把它們翻譯成大寫或不是。

+0

喜添,你的解決方案是正確的,但我在for-each循環內打印了很多字段,所以我需要保留for-each。可以提供另一個使用現有for-each循環的解決方案,而不是我需要的值'。 – Wilz

+0

Tim,我在for-each中使用了以下內容,並發現它的工作原理是''非常感謝 – Wilz

+0

TimC:這是一個很好的答案,但可能很慢(O(N^2) - 二次時間複雜度) Ë lements。您可能對線性時間複雜度(O(N))的解決方案感興趣。 –

0

除了實現的算法具有O(N^2)(二次)時間複雜度並且在大輸入上執行速度非常慢()之外,接受的答案是一個很好的答案。

這裏是線性時間複雜性爲O(N)變換:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="node()|@*"> 
    <xsl:param name="pCount" select="0"/> 
    <xsl:copy> 
    <xsl:apply-templates select="node()[1]|@*"> 
    <xsl:with-param name="pCount" select="$pCount"/> 
    </xsl:apply-templates> 
    </xsl:copy> 
    <xsl:apply-templates select="following-sibling::node()[1]"> 
    <xsl:with-param name="pCount" select="$pCount"/> 
    </xsl:apply-templates> 
</xsl:template> 

<xsl:template match="entry[not(contains('EX', type))]"> 
    <xsl:param name="pCount" select="0"/> 

    <xsl:copy> 
    <slno><xsl:value-of select="$pCount+1"/></slno> 
    <xsl:apply-templates select="node()[1]|@*"> 
    <xsl:with-param name="pCount" select="$pCount+1"/> 
    </xsl:apply-templates> 
    </xsl:copy> 
    <xsl:apply-templates select="following-sibling::node()[1]"> 
    <xsl:with-param name="pCount" select="$pCount+1"/> 
    </xsl:apply-templates> 
</xsl:template> 

<xsl:template match="type"> 
    <xsl:param name="pCount" select="0"/> 
    <xsl:apply-templates select="following-sibling::node()[1]"> 
    <xsl:with-param name="pCount" select="$pCount+1"/> 
    </xsl:apply-templates> 
</xsl:template> 
</xsl:stylesheet> 

當所提供的XML文檔應用:

<root> 
    <entry> 
     <type>U</type> 
     <value>111</value> 
    </entry> 
    <entry> 
     <type>X</type> 
     <value>222</value> 
    </entry> 
    <entry> 
     <type>E</type> 
     <value>333</value> 
    </entry> 
    <entry> 
     <type>Q</type> 
     <value>444</value> 
    </entry> 
</root> 

有用,正確的結果產生:

<root> 
    <entry> 
     <slno>1</slno> 
     <value>111</value> 
    </entry> 
    <entry> 
     <value>222</value> 
    </entry> 
    <entry> 
     <value>333</value> 
    </entry> 
    <entry> 
     <slno>2</slno> 
     <value>444</value> 
    </entry> 
</root> 

說明

  1. 使用並重寫"fine-grained identity rule"。它的名字是由於模板一次只應用於一個節點(按文檔順序)。

  2. 「細粒度身份規則」被修改爲包含並傳遞參數$pCount,該參數包含迄今爲止達到的最大當前「序列號」。

  3. 此工作原理無需返回當前序列號,因爲所有entry元素都是同級元素。

  4. 時間複雜度是線性的,因爲在其他答案中沒有計算每個節點上所有前面的兄弟節點。