2009-11-02 47 views
1

的解決方案我的XML看起來像這樣的:XSL找不到我的數據轉換

<ROW ref="0005631" type="04" line="1" value="Australia"/> 
<ROW ref="0005631" type="00" line="1" value="John"/> 
<ROW ref="0005631" type="02" line="1" value="Builder"/> 
<ROW ref="0005631" type="01" line="1" value="Smith"/> 

我需要在XSL解決格式化一下這本:

John Smith Builder Australia 

任何幫助都會很棒。我有很多很多不同的數據,許多不同的類型和行都混在一起,所以我不想對它們進行任何硬編碼。

+1

所以你要求一個XSLT文檔?你能告訴我們你到目前爲止嘗試過什麼嗎? –

回答

0

在XSLT 1.0:

<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
> 
    <xsl:output method="text" encoding="utf-8" /> 

    <!-- index ROWs by their @ref --> 
    <xsl:key name="kRowByRef"  match="ROW" use="@ref" /> 
    <!-- index ROWs by their @ref and @line --> 
    <xsl:key name="kRowByRefAndLine" match="ROW" use="concat(@ref, ',', @line)" /> 

    <xsl:template match="/*"> 
    <!-- 1) rows are processed with "ORDER BY @ref" --> 
    <xsl:apply-templates select="ROW" mode="ref-group"> 
     <xsl:sort select="@ref" data-type="number" /> 
    </xsl:apply-templates> 
    </xsl:template> 

    <xsl:template match="ROW" mode="ref-group"> 
    <!-- 2) rows are grouped by @ref --> 
    <xsl:variable name="thisGroup" select=" 
     key('kRowByRef', @ref) 
    " /> 

    <xsl:if test="generate-id() = generate-id($thisGroup[1])"> 
     <!-- 2.1) for the first item in the group, 
       nodes are processed with "ORDER BY @line" --> 
     <xsl:apply-templates select="$thisGroup" mode="line-group"> 
     <xsl:sort select="@line" data-type="number" /> 
     </xsl:apply-templates> 
     <!-- use a line as record separator --> 
     <xsl:text>----------------------------&#10;</xsl:text> 
    </xsl:if> 
    </xsl:template> 

    <xsl:template match="ROW" mode="line-group"> 
    <!-- 3) rows are grouped by @ref, @line --> 
    <xsl:variable name="thisGroup" select=" 
     key('kRowByRefAndLine', concat(@ref, ',', @line)) 
    " /> 

    <xsl:if test="generate-id() = generate-id($thisGroup[1])"> 
     <!-- 3.1) for the first item in the group, 
       nodes are processed with "ORDER BY @type" --> 
     <xsl:apply-templates select="$thisGroup" mode="line"> 
     <xsl:sort select="@type" data-type="number" /> 
     </xsl:apply-templates> 
    </xsl:if> 
    </xsl:template> 

    <xsl:template match="ROW" mode="line"> 
    <!-- 4) rows are printed out & appended with space or newline --> 
    <xsl:value-of select="@value" /> 
    <xsl:choose> 
     <xsl:when test="position() = last()"> 
     <xsl:text>&#10;</xsl:text> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:text> </xsl:text> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:template> 

</xsl:stylesheet> 

對於這種完全無序的輸入:

<data> 
    <ROW ref="0005631" type="04" line="1" value="Australia"/> 
    <ROW ref="0005632" type="00" line="1" value="Jack"/> 
    <ROW ref="0005631" type="00" line="1" value="John"/> 
    <ROW ref="0005631" type="01" line="1" value="Smith"/> 
    <ROW ref="0005632" type="04" line="2" value="Whiskey"/> 
    <ROW ref="0005632" type="02" line="1" value="Tennessee"/> 
    <ROW ref="0005631" type="02" line="1" value="Builder"/> 
    <ROW ref="0005632" type="01" line="1" value="Daniel's"/> 
</data> 

我得到:

 
John Smith Builder Australia 
---------------------------- 
Jack Daniel's Tennessee 
Whiskey 
---------------------------- 

說明

此處發生的是分階段分組和排序,以便最終結果按@ref@line@type進行分組和排序。所有分組均爲Muenchian分組。模板#1處理所有<ROW>元素@ref順序:

<ROW ref="0005631" type="04" line="1" value="Australia"/> 
<ROW ref="0005631" type="00" line="1" value="John"/> 
<ROW ref="0005631" type="01" line="1" value="Smith"/> 
<ROW ref="0005631" type="02" line="1" value="Builder"/> 
<ROW ref="0005632" type="00" line="1" value="Jack"/> 
<ROW ref="0005632" type="04" line="2" value="Whiskey"/> 
<ROW ref="0005632" type="02" line="1" value="Tennessee"/> 
<ROW ref="0005632" type="01" line="1" value="Daniel's"/> 

模板#2處理第一隻各@ref組:

<ROW ref="0005631" type="04" line="1" value="Australia"/> 
<ROW ref="0005632" type="00" line="1" value="Jack"/> 

遞過整個組($thisGroup)到模板#3分兩步,在@line order:

<ROW ref="0005631" type="04" line="1" value="Australia"/> 
<ROW ref="0005631" type="00" line="1" value="John"/> 
<ROW ref="0005631" type="01" line="1" value="Smith"/> 
<ROW ref="0005631" type="02" line="1" value="Builder"/> 

<ROW ref="0005632" type="00" line="1" value="Jack"/> 
<ROW ref="0005632" type="02" line="1" value="Tennessee"/> 
<ROW ref="0005632" type="01" line="1" value="Daniel's"/> 
<ROW ref="0005632" type="04" line="2" value="Whiskey"/> 

模板#3取第一個eac ħ@line組:

<ROW ref="0005631" type="04" line="1" value="Australia"/> 
<ROW ref="0005632" type="00" line="1" value="Jack"/> 
<ROW ref="0005632" type="04" line="2" value="Whiskey"/> 

並處理它們,在三個步驟中發放整個組到模板#4,在@type順序:

<ROW ref="0005631" type="00" line="1" value="John"/> 
<ROW ref="0005631" type="01" line="1" value="Smith"/> 
<ROW ref="0005631" type="02" line="1" value="Builder"/> 
<ROW ref="0005631" type="04" line="1" value="Australia"/> 

<ROW ref="0005632" type="00" line="1" value="Jack"/> 
<ROW ref="0005632" type="01" line="1" value="Daniel's"/> 
<ROW ref="0005632" type="02" line="1" value="Tennessee"/> 

<ROW ref="0005632" type="04" line="2" value="Whiskey"/> 

模板#4打印出來,附加空格或換行符在適當情況下。

+0

非常好,謝謝。 我能夠修改你的代碼來完成我所需要的。 – Ben

0

你的意思是,你想從同一行獲得元素,然後根據類型號顯示它?我認爲xsl:sort是你需要的

+0

我不認爲它就像排序一樣簡單。我有數百個參考文獻,並且參考文獻有很多行。所以我需要能夠以某種方式將行號鏈接到參考,並輸出所有物品都屬於該行。所有的數據也是隨機的,所以我不能遍歷數據。答案: – Ben

+0

@Ben,那麼也許你應該: A.給你一個更大的XML樣本; B.更清楚地解釋你的要求是什麼; C.給出一個預期產出的更大例子;和 D.顯示你的xsl到目前爲止的樣子。 –

2

要在你的數據上使用xsl:sort你需要有一個父節點,你沒有在你的示例代碼中提供,但必須有一個爲了使XML文檔有效。假設您的輸入是父節點<TABLE />

<TABLE> 
    <ROW ref="0005631" type="04" line="1" value="Australia"/> 
    <ROW ref="0005631" type="00" line="1" value="John"/> 
    <ROW ref="0005631" type="02" line="1" value="Builder"/> 
    <ROW ref="0005631" type="01" line="1" value="Smith"/> 
</TABLE> 

假設您僅基於類型列的值進行排序,那麼您將能夠使用以下XSLT實現所需的結果。

<?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:template match="TABLE"> 
    <xsl:apply-templates> 
     <xsl:sort select="@type" data-type="number"/> 
    </xsl:apply-templates> 
    </xsl:template> 

    <xsl:template match="ROW"> 
    <xsl:apply-templates select="@value"/> 
    <xsl:text>&#x20;</xsl:text> 
    </xsl:template> 

</xsl:stylesheet> 

如果您想根據裁判,類型,而不是簡單地鍵入您可以使用該模板TABLE以下行進行排序。

<xsl:template match="TABLE"> 
    <xsl:apply-templates> 
     <xsl:sort select="@ref" data-type="number"/> 
     <xsl:sort select="@type" data-type="number"/> 
     <xsl:sort select="@line" data-type="number"/> 
    </xsl:apply-templates> 
    </xsl:template> 

我不能確定到底什麼樣命令你從你的問題想,但是任何的替代品應該是直截了當給出這兩個例子。