使用XSLT将XML节点与相同的子节点值合并

时间:2017-10-18 04:26:57

标签: xml xslt xslt-2.0

我的xml输入是:

<?xml version="1.0" encoding="UTF-8"?>
<Root>
    <Row>
        <EmployeeID>21001</EmployeeID>
        <FMLAStartDate>2017-10-10</FMLAStartDate>
        <FMLAEndDate></FMLAEndDate>
        <FMLACorrectDate></FMLACorrectDate>
        <LTDStartDate></LTDStartDate>
        <LTDEndDate></LTDEndDate>       
        <LTDCorrectdate></LTDCorrectdate>
    </Row>

    <Row>
        <EmployeeID>21002</EmployeeID>
        <FMLAStartDate>2017-10-10</FMLAStartDate>
        <FMLAEndDate></FMLAEndDate>
        <FMLACorrectDate></FMLACorrectDate>
        <LTDStartDate></LTDStartDate>
        <LTDEndDate></LTDEndDate>       
        <LTDCorrectdate></LTDCorrectdate>
    </Row>

    <Row>
        <EmployeeID>21002</EmployeeID>
        <FMLAStartDate></FMLAStartDate>
        <FMLAEndDate></FMLAEndDate>
        <FMLACorrectDate></FMLACorrectDate>
        <LTDStartDate></LTDStartDate>
        <LTDEndDate>2017-10-08</LTDEndDate>     
        <LTDCorrectdate></LTDCorrectdate>
    </Row>

    <Row>
        <EmployeeID>21003</EmployeeID>
        <FMLAStartDate></FMLAStartDate>
        <FMLAEndDate></FMLAEndDate>
        <FMLACorrectDate></FMLACorrectDate>
        <LTDStartDate>2017-05-01</LTDStartDate>
        <LTDEndDate></LTDEndDate>       
        <LTDCorrectdate></LTDCorrectdate>
    </Row>

    <Row>
        <EmployeeID>21004</EmployeeID>
        <FMLAStartDate></FMLAStartDate>
        <FMLAEndDate></FMLAEndDate>
        <FMLACorrectDate>2017-01-10</FMLACorrectDate>
        <LTDStartDate></LTDStartDate>
        <LTDEndDate></LTDEndDate>       
        <LTDCorrectdate></LTDCorrectdate>
    </Row>
</Root>

请注意,员工21002有两个节点,一个持有FMLA开始日期,另一个持有LTD结束日期。 Post XSLT转换期望是每个员工ID具有一个行节点,并且该行节点应该保存该雇员ID的全部信息。因此预期的产出是:

<?xml version="1.0" encoding="UTF-8"?>
<Root>
   <Row>
    <EmployeeID>21001</EmployeeID>
    <FMLAStartDate>2017-10-10</FMLAStartDate>
    <FMLAEndDate></FMLAEndDate>
    <FMLACorrectDate></FMLACorrectDate>
    <LTDStartDate></LTDStartDate>
    <LTDEndDate></LTDEndDate>       
    <LTDCorrectdate></LTDCorrectdate>
   </Row>

   <Row>
    <EmployeeID>21002</EmployeeID>
    <FMLAStartDate>2017-10-10</FMLAStartDate>
    <FMLAEndDate></FMLAEndDate>
    <FMLACorrectDate></FMLACorrectDate>
    <LTDStartDate></LTDStartDate>
    <LTDEndDate>2017-10-08</LTDEndDate>     
    <LTDCorrectdate></LTDCorrectdate>
   </Row>

   <Row>
    <EmployeeID>21003</EmployeeID>
    <FMLAStartDate></FMLAStartDate>
    <FMLAEndDate></FMLAEndDate>
    <FMLACorrectDate></FMLACorrectDate>
    <LTDStartDate>2017-05-01</LTDStartDate>
    <LTDEndDate></LTDEndDate>       
    <LTDCorrectdate></LTDCorrectdate>
   </Row>

   <Row>
    <EmployeeID>21004</EmployeeID>
    <FMLAStartDate></FMLAStartDate>
    <FMLAEndDate></FMLAEndDate>
    <FMLACorrectDate>2017-01-10</FMLACorrectDate>
    <LTDStartDate></LTDStartDate>
    <LTDEndDate></LTDEndDate>       
    <LTDCorrectdate></LTDCorrectdate>
   </Row>
</Root>

我已尝试for-each-group进行基于员工ID的分组,但它没有提供正确的输出。有人可以帮我这个吗?我有XSLT的基本知识,但没有使用高级XSLT功能。

谢谢!

2 个答案:

答案 0 :(得分:0)

您可以对行进行分组并连接每个字段的所有值:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:template match="/Root">
    <xsl:for-each-group select="Row" group-by="EmployeeID">
      <Row>
        <EmployeeID>
          <xsl:value-of select="current-grouping-key()"/>
        </EmployeeID>
        <FMLAStartDate>
          <xsl:value-of select="current-group()/FMLAStartDate"/>
        </FMLAStartDate>
        <FMLAEndDate>
          <xsl:value-of select="current-group()/FMLAEndDate"/>
        </FMLAEndDate>
        <FMLACorrectDate>
          <xsl:value-of select="current-group()/FMLACorrectDate"/>
        </FMLACorrectDate>
        <LTDStartDate>
          <xsl:value-of select="current-group()/LTDStartDate"/>
        </LTDStartDate>
        <LTDEndDate>
          <xsl:value-of select="current-group()/LTDEndDate"/>
        </LTDEndDate>
        <LTDCorrectdate>
          <xsl:value-of select="current-group()/LTDCorrectdate"/>
        </LTDCorrectdate>
      </Row>
    </xsl:for-each-group>
  </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:0)

我愿意

  <xsl:template match="/Root">
    <xsl:for-each-group select="Row" group-by="EmployeeID">
      <Row>
        <xsl:for-each-group select="current-group()/*" 
                            group-by="node-name()">
          <xsl:copy-of select="(current-group()[normalize-space()], 
                                current-group()[not(normalize-space()])[1]"/>
      </Row>
    </xsl:for-each-group>
  </xsl:template>

即:对于同一员工ID的每组员工记录,输出一行,并且对于组中任何或所有员工元素中存在的每个元素,输出其中一个的副本,给出偏好那些非空内容的人。