2015-12-10 56 views
2

如何在XSLT中使用for循環?如何在XSLT中使用for循環並根據迭代獲取節點值

我有這個要求,我想將下面顯示的xml轉換成一個逗號分隔文件。 CSV文件中的行數將等於員工報告條目的計數COBRA_Records_within_Range節點。除了COBRA_Records_within_Range節點的子元素值之外,3行中的所有值將相同。我能夠創建3行,但無法檢索COBRA_Records_within_Range的子元素的值。我想在特定節點的計數上運行for循環,然後根據迭代檢索其子元素。在下面的例子中,有3個COBRA_Records_within_Range nodes。所以循環應運行計數(COBRA_Records_within_Range)`,然後在每次迭代中我需要它的子節點的值。例如,如果是第二次迭代,那麼Eligibility_Reason應該在CSV輸出中顯示爲「依賴的子項 - 在計劃規則下失去依賴的子級狀態」。

有人可以幫助我嗎?

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <wd:Report_Entry xmlns:wd="urn:com.workday/bsvc"> 
     <wd:Employee_ID>111111</wd:Employee_ID> 
     <wd:Worker>John Smith</wd:Worker> 
     <wd:Employee_Last_Name>Smith</wd:Employee_Last_Name> 
     <wd:Employee_First_Name>John</wd:Employee_First_Name> 
     <wd:COBRA_Records_within_Range> 
      <wd:Qualifying_Event_Date>2015-10-04</wd:Qualifying_Event_Date> 
      <wd:Eligibility_Reason>Dependent Children - Loss of dependent child status under the 
       plan rules</wd:Eligibility_Reason> 
      <wd:Benefit_Plan1>Dental-US - Delta Dental PPO BREG</wd:Benefit_Plan1> 
     </wd:COBRA_Records_within_Range> 
     <wd:COBRA_Records_within_Range> 
      <wd:Qualifying_Event_Date>2015-10-05</wd:Qualifying_Event_Date> 
      <wd:Eligibility_Reason>Dependent Children - Loss of dependent child status under the 
       plan rules</wd:Eligibility_Reason> 
      <wd:Benefit_Plan1>Healthcare FSA - Tri-Ad FSA Residential US</wd:Benefit_Plan1> 
     </wd:COBRA_Records_within_Range> 
     <wd:COBRA_Records_within_Range> 
      <wd:Qualifying_Event_Date>2015-10-05</wd:Qualifying_Event_Date> 
      <wd:Eligibility_Reason>Spouse - Divorce or legal separation of the covered 
       employee</wd:Eligibility_Reason> 
      <wd:Test>0</wd:Test> 
      <wd:Benefit_Plan1>Medical/Vision-US - Empire Blue Cross &amp; Blue Shield 
       EPO</wd:Benefit_Plan1> 
     </wd:COBRA_Records_within_Range> 
    </wd:Report_Entry> 
</root> 

這裏的預期輸出 -

111111, John Smith, Smith, John, 2015-10-04, Dependent Children - Loss of dependent child status under the plan rules, Dental-US - Delta Dental PPO BREG 
111111, John Smith, Smith, John, 2015-10-05, Dependent Children - Loss of dependent child status under the plan rules, Healthcare FSA - Tri-Ad FSA Residential US 
111111, John Smith, Smith, John, 2015-10-05, Spouse - Divorce or legal separation of the covered employee, Medical/Vision-US - Empire Blue Cross &amp; Blue Shield EPO 

這是我所創建的XSLT -

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:op="http://www.w3.org/2005/xpath-functions" 
    xmlns:wd="urn:com.workday/bsvc" 
    exclude-result-prefixes="xsd op wd"  
    version="2.0"> 

    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/">  
     <File>    
      <Header separator=","> 
       <xsl:call-template name="printHeader"/> 
      </Header>    

      <xsl:for-each select="root/wd:Report_Entry"> 
       <xsl:variable name="cobrarecordcount" as="xsd:integer" select="count(wd:COBRA_Records_within_Range)"/> 
       <xsl:variable name="record" select="."/> 

       <xsl:for-each select="1 to $cobrarecordcount"> 
        <xsl:call-template name="printRecord"> 
         <xsl:with-param name="record" select="$record"></xsl:with-param> 
        </xsl:call-template> 
       </xsl:for-each>               
      </xsl:for-each>    
     </File>   

    </xsl:template> 

    <xsl:template name="printHeader"> 
     <xsd:element><xsl:text>Employee ID</xsl:text></xsd:element> 
     <xsd:element><xsl:text>Employee Last Name</xsl:text></xsd:element> 
     <xsd:element><xsl:text>Employee First Name </xsl:text></xsd:element>   
     <xsd:element><xsl:text>Qualifying Event Date</xsl:text></xsd:element> 
     <xsd:element><xsl:text>Qualifying Event Type</xsl:text></xsd:element>   
     <xsd:element><xsl:text>Benefit Plan 1</xsl:text></xsd:element> 
    </xsl:template> 

    <xsl:template name="printRecord"> 
     <xsl:param name="record"/> 

       <Line separator="," quoteStyle="double" quoteWhenMatches=".*[a-zA-Z].*"> 
        <!--Employee Id--> 
        <xsd:element> 
         <xsl:value-of select="$record/wd:Employee_ID"/> 
        </xsd:element>  
        <!--Employee Last Name--> 
        <xsd:element> 
         <xsl:value-of select="$record/wd:Employee_Last_Name"/> 
        </xsd:element>  
        <!--Employee First Name--> 
        <xsd:element> 
         <xsl:value-of select="$record/wd:Employee_First_Name"/> 
        </xsd:element> 
        <!--Qualifying Event Date--> 
        <xsd:element> 
         <xsl:value-of select="($record/wd:COBRA_Records_within_Range[position()]/wd:Qualifying_Event_Date)"/> 
        </xsd:element> 
        <!--Qualifying Event Type--> 
        <xsd:element> 
         <xsl:value-of select="($record/wd:COBRA_Records_within_Range[position()]/wd:Eligibility_Reason)"/> 
        </xsd:element> 
        <!--Benefit--> 
        <xsd:element> 
         <xsl:value-of select="$record/wd:COBRA_Records_within_Range[position()]/wd:Benefit_Plan1"/> 
        </xsd:element> 
       </Line> 
    </xsl:template>  
</xsl:stylesheet> 
+0

代替(或除了)長的解釋,表明你希望看到的輸出文檔,給這個文件作爲輸入。另外,請顯示您迄今爲止的XSLT代碼。 –

+0

@MathiasMüller - 感謝您的及時回覆。我已經添加了基於輸入xml和XSLT的預期輸出,我已將count(COBRA_Records_within_Range)存儲在一個變量中,並使用了xsl:for-each循環( )打印三行,但我無法檢索子元素值 – vverma2149

+0

謝謝,現在請顯示您當前擁有的XSLT代碼。如果有人能指出你出錯的地方,你將從答案中獲得更多的好處。 –

回答

1

我找不到你試圖XSLT任何韻或理由。預期的結果可以很簡單地實現:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:wd="urn:com.workday/bsvc"> 
<xsl:output method="text" encoding="UTF-8"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="wd:Report_Entry"> 
    <xsl:variable name="common"> 
     <xsl:value-of select="wd:Employee_ID" /> 
     <xsl:text>, </xsl:text> 
     <xsl:value-of select="wd:Worker" /> 
     <xsl:text>, </xsl:text> 
     <xsl:value-of select="wd:Employee_Last_Name" /> 
     <xsl:text>, </xsl:text> 
     <xsl:value-of select="wd:Employee_First_Name" /> 
     <xsl:text>, </xsl:text> 
    </xsl:variable> 
    <xsl:for-each select="wd:COBRA_Records_within_Range"> 
     <xsl:copy-of select="$common"/> 
     <xsl:value-of select="wd:Qualifying_Event_Date" /> 
     <xsl:text>, </xsl:text> 
     <xsl:value-of select="wd:Eligibility_Reason" /> 
     <xsl:text>, </xsl:text> 
     <xsl:value-of select="wd:Benefit_Plan1" /> 
     <xsl:text>&#10;</xsl:text> 
    </xsl:for-each> 
</xsl:template> 

</xsl:stylesheet> 
+0

感謝您的回答......這將是最簡單的解決方案。 – vverma2149

0

在斷言對於wd:COBRA_Records_within_Range元素,您指定position(),但就是不給你從你的xsl:for-each序列中的當前值。 position()是上下文節點的位置。

您只想篩選那些position()等於您的xsl:for-each中的當前編號。

爲了做到這一點,其他參數添加到您的模板,並通過電流值時,你怎麼稱呼它:

在下面的例子中,我創建了一個名爲rangeIndex參數和所使用的速記謂詞[$rangeIndex],但可以還使用[position() = $rangeIndex]

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:op="http://www.w3.org/2005/xpath-functions" 
    xmlns:wd="urn:com.workday/bsvc" 
    exclude-result-prefixes="xsd op wd"  
    version="2.0"> 

    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/">  
     <File>    
      <Header separator=","> 
       <xsl:call-template name="printHeader"/> 
      </Header>    

      <xsl:for-each select="root/wd:Report_Entry"> 
       <xsl:variable name="cobrarecordcount" as="xsd:integer" select="count(wd:COBRA_Records_within_Range)"/> 
       <xsl:variable name="record" select="."/> 

       <xsl:for-each select="1 to $cobrarecordcount"> 
        <xsl:call-template name="printRecord"> 
         <xsl:with-param name="record" select="$record"></xsl:with-param> 
         <xsl:with-param name="rangeIndex" select="."/> 
        </xsl:call-template> 
       </xsl:for-each>               
      </xsl:for-each>    
     </File>   

    </xsl:template> 

    <xsl:template name="printHeader"> 
     <xsd:element><xsl:text>Employee ID</xsl:text></xsd:element> 
     <xsd:element><xsl:text>Employee Last Name</xsl:text></xsd:element> 
     <xsd:element><xsl:text>Employee First Name </xsl:text></xsd:element>   
     <xsd:element><xsl:text>Qualifying Event Date</xsl:text></xsd:element> 
     <xsd:element><xsl:text>Qualifying Event Type</xsl:text></xsd:element>   
     <xsd:element><xsl:text>Benefit Plan 1</xsl:text></xsd:element> 
    </xsl:template> 

    <xsl:template name="printRecord"> 
     <xsl:param name="record"/> 
     <xsl:param name="rangeIndex"/> 
     <Line separator="," quoteStyle="double" quoteWhenMatches=".*[a-zA-Z].*"> 
      <!--Employee Id--> 
      <xsd:element> 
       <xsl:value-of select="$record/wd:Employee_ID"/> 
      </xsd:element>  
      <!--Employee Last Name--> 
      <xsd:element> 
       <xsl:value-of select="$record/wd:Employee_Last_Name"/> 
      </xsd:element>  
      <!--Employee First Name--> 
      <xsd:element> 
       <xsl:value-of select="$record/wd:Employee_First_Name"/> 
      </xsd:element> 
      <!--Qualifying Event Date--> 
      <xsd:element> 
       <xsl:value-of select="($record/wd:COBRA_Records_within_Range[$rangeIndex]/wd:Qualifying_Event_Date)"/> 
      </xsd:element> 
      <!--Qualifying Event Type--> 
      <xsd:element> 
       <xsl:value-of select="($record/wd:COBRA_Records_within_Range[$rangeIndex]/wd:Eligibility_Reason)"/> 
      </xsd:element> 
      <!--Benefit--> 
      <xsd:element> 
       <xsl:value-of select="$record/wd:COBRA_Records_within_Range[$rangeIndex]/wd:Benefit_Plan1"/> 
      </xsd:element> 
     </Line> 
    </xsl:template>  
</xsl:stylesheet> 
+0

非常感謝您的詳細解釋。我現在明白如果我再次遇到這種情況應該怎麼做......謝謝! :) – vverma2149

0

這裏是一個更簡單和更短的解決方案,使用<xsl:for-each>可言:

I. XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:wd="urn:com.workday/bsvc"> 
<xsl:output method="text"/> 
<xsl:strip-space elements="*"/> 

<xsl:variable name="vHeader" 
     select="string-join(/*/*/*[not(self::wd:COBRA_Records_within_Range)], ', ')"/> 

    <xsl:template match="wd:COBRA_Records_within_Range"> 
    <xsl:value-of select="string-join(($vHeader, *), ', '), '&#xA;'"/> 
    </xsl:template> 
    <xsl:template match="text()"/> 
</xsl:stylesheet> 

II。 XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:wd="urn:com.workday/bsvc"> 
<xsl:output method="text"/> 
<xsl:strip-space elements="*"/> 

<xsl:variable name="vHeader"> 
    <xsl:apply-templates 
     select="/*/*/*[not(self::wd:COBRA_Records_within_Range)]" mode="header"/> 
</xsl:variable> 

    <xsl:template match="wd:COBRA_Records_within_Range"> 
    <xsl:value-of select="$vHeader"/><xsl:text>, </xsl:text> 
    <xsl:apply-templates mode="header"/> 
    <xsl:value-of select="'&#xA;'"/> 
    </xsl:template> 

    <xsl:template match="*[text()]" mode="header"> 
    <xsl:if test="not(position() = 1)">, </xsl:if> 
    <xsl:value-of select="."/> 
    </xsl:template> 
    <xsl:template match="text()"/> 
</xsl:stylesheet> 
相關問題