2016-11-29 61 views
0

我被困在一個循環的問題中,需要來自組的一些方向。我能夠通過一個孩子循環,但無法添加第二個孩子。XSLT多個子元素的嵌套循環

這是我的XML:

<wd:Report_Entry> 
    <wd:Beneficiaries_-_All> 
    <wd:EMPLID>00025</wd:EMPLID> 
    <wd:Last>LastName</wd:Last> 
    <wd:First>FirstName</wd:First> 
    <wd:WID>key1234</wd:WID> 
    </wd:Beneficiaries_-_All> 
    <wd:Beneficiaries_-_All> 
    <wd:EMPLID>00025</wd:EMPLID> 
    <wd:Last>LastName</wd:Last> 
    <wd:First>First2</wd:First> 
    <wd:WID>key4567</wd:WID> 
    </wd:Beneficiaries_-_All> 
    <wd:Beneficiaries_-_People> 
    <wd:DOB>Birth1</wd:DOB> 
    <wd:ID>ID1</wd:ID> 
    <wd:WID>key1234</wd:WID> 
    </wd:Beneficiaries_-_People> 
    <wd:Beneficiaries_-_People> 
    <wd:DOB>Birth2</wd:DOB> 
    <wd:ID>ID2</wd:ID> 
    <wd:WID>key4567</wd:WID> 
    </wd:Beneficiaries_-_People> 
</wd:Report_Entry> 

我的XSLT低於

<xsl:output method="text"/> 
<xsl:variable name="linefeed" select="'&#xA;'"></xsl:variable> 

<xsl:template match="/"> 
<xsl:for-each select="/wd:Report_Data/wd:Report_Entry"> 
    <xsl:for-each select="wd:Beneficiaries_-_All"> 
    <xsl:text>"</xsl:text> 
    <xsl:value-of select="wd:EMPLID"/> 
    <xsl:text>","</xsl:text> 
    <xsl:value-of select="wd:Last"/> 
    <xsl:text>","</xsl:text> 
    <xsl:value-of select="wd:First"/> 
    <xsl:text>","</xsl:text> 
    <xsl:value-of select="$linefeed"/> 
    </xsl:for-each> 
    <xsl:for-each select="wd:Beneficiaries_-_People"> 
    <xsl:value-of select="wd:DOB"/> 
    <xsl:text>","</xsl:text> 
    <xsl:value-of select="wd:ID"/> 
    <xsl:text>"</xsl:text> 
    </xsl:for-each> 
    <xsl:value-of select="$linefeed"/> 
</xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

我期望的輸出是CSV這樣的:

「00025」, 「姓氏」,」 First1「,」Birth1「,」ID1「
」00025「,」LastName「,」First2「,」Birth2「,」ID2「
「00026」, 「姓氏」, 「First1」, 「Birth1」, 「ID1」(以這種方式繼續)

但我正在逐漸爲每個報表錄入:

「00025」 , 「姓氏」, 「First1」, 「
」00025「, 」姓氏「, 」First2「,」
Birth1" , 「ID1」 Birth2" , 「ID2」

我對這個網站的研究表示<apply-templates>優於<for-each>。當我嘗試這種方法時,格式給我一個問題。感謝小組!

+0

出生日期與人們有什麼聯繫? –

+0

在生成XML的查詢中,「ALL」和「People」上的受益人元數據共享一個公共標識。 – BWatkins

+0

恐怕我在所提供的例子中看不到這樣的東西。 –

回答

0

如果我理解正確的話,你只需要一個變量,使其工作:

<xsl:for-each select="/wd:Report_Data/wd:Report_Entry"> 
    <xsl:for-each select="wd:Beneficiaries_-_All"> 
     <xsl:text>"</xsl:text> 
     <xsl:value-of select="wd:EMPLID"/> 
     <xsl:text>","</xsl:text> 
     <xsl:value-of select="wd:Last"/> 
     <xsl:text>","</xsl:text> 
     <xsl:value-of select="wd:First"/> 
     <xsl:text>","</xsl:text> 
     <!-- new code starts here --> 
     <xsl:variable name="WID" select="wd:WID"/> 
     <xsl:value-of select="../wd:Beneficiaries_-_People[wd:WID = $WID]/wd:DOB"/> 
     <xsl:text>","</xsl:text> 
     <xsl:value-of select="../wd:Beneficiaries_-_People[wd:WID = $WID]/wd:ID"/> 
     <xsl:text>"</xsl:text> 
     <!-- end new code --> 
     <xsl:value-of select="$linefeed"/> 
    </xsl:for-each> 
</xsl:for-each> 

希望這有助於!

+0

感謝所有偉大的評論!他們是如此有益於學習。變量是否會被聲明爲這樣? BWatkins

+0

它工作正常!感謝您回答我的問題,並向初學者展示如何使用變量。我認爲他們必須在頂部定義。再次感謝,也感謝所有貢獻者。 – BWatkins

1

這裏是展示了一些XSLT的功能的解決方案:

  • 模板匹配(而不是<xsl:for-each>
  • XSL鍵
  • 多種模板模式

(我使用前綴爲wd的僞造名稱空間URI)

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:wd="http://some.namespace/wd" 
> 
    <xsl:output method="text" /> 
    <xsl:key name="kPeople" match="wd:Beneficiaries_-_People" use="wd:WID" /> 

    <xsl:template match="/"> 
    <xsl:apply-templates select="wd:Report_Data/wd:Report_Entry/wd:Beneficiaries_-_All" /> 
    </xsl:template> 

    <xsl:template match="wd:Beneficiaries_-_All"> 
    <xsl:apply-templates select="wd:EMPLID" mode="csv" /> 
    <xsl:apply-templates select="wd:Last" mode="csv" /> 
    <xsl:apply-templates select="wd:First" mode="csv" /> 
    <xsl:apply-templates select="key('kPeople', wd:WID)/wd:DOB" mode="csv" /> 
    <xsl:apply-templates select="key('kPeople', wd:WID)/wd:ID" mode="csv-nl" /> 
    </xsl:template> 

    <xsl:template match="*" mode="csv"> 
    <xsl:value-of select="concat('&quot;', ., '&quot;,')" /> 
    </xsl:template> 

    <xsl:template match="*" mode="csv-nl"> 
    <xsl:value-of select="concat('&quot;', ., '&quot;&#xA;')" /> 
    </xsl:template> 
</xsl:stylesheet> 

爲了您的樣本數據,這導致:

"00025","LastName","FirstName","Birth1","ID1" 
"00025","LastName","First2","Birth2","ID2" 

陷阱:

  • 確保在值雙引號得到妥善處理,否則將CSV將被打破。要麼確保你刪除它們或正確地逃脫它們。做對這可能會很棘手。
  • 如果某些XML元素(例如<wd:DOB>)不存在,則這不起作用。對於統一輸入,元素總是存在但有時是空的,一切都很好。如果元素可能丟失,則需要更改腳本。

在這兩種情況下:瞭解您的數據。


模板匹配是一把雙刃劍。這對輸入驅動的轉換非常有用。輸入XML通過樣式表中的模板進行映射,而管道最少。

另一方面,CSV是一種嚴格的輸出格式,以輸入驅動的方式創建它需要輸入同樣嚴格。由於XML允許缺少元素,因此甚至可能沒有可以變成輸出字段的元素。在這種情況下,命名模板和參數可以幫助:

而不是

<xsl:apply-templates select="wd:EMPLID" mode="csv" /> 

我們可以有

<xsl:call-template name="csv"> 
    <xsl:with-param name="val" value="wd:EMPLID" /> 
</xsl:call-template> 

<xsl:template name="csv"> 
    <xsl:param name="val" /> 
    <xsl:value-of select="concat('&quot;', $val, '&quot;,')" /> 
</xsl:call-template> 

這將確保即使在元素丟失,空字段"",仍將被打印。