2015-12-10 131 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> 
相关问题