使用XSLT比较2个连续的XML行

时间:2017-03-28 10:32:21

标签: xslt xslt-1.0 xslt-2.0

您好我正在尝试比较以下XML的2个连续条目。

    EmployeeID|CountryCode|RegionCode|StartDate    
    "111111"|"US"|"RX"|"2014-07-01"    
    "111111"|"US"|"MD"|"2009-10-14"    
    "111111"|"US"|"MD"|"2009-09-14"    
    "111111"|"US"|"RX"|"2013-07-01""

输出结果为:

    EmployeeID|CountryCode|RegionCode|StartDate    
    "111111"|"US"|"RX"|"2014-07-01"    
    "111111"|"US"|"MD"|"2009-10-14"    
    "111111"|"US"|"RX"|"2013-07-01"

但我期待:

<?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                    xmlns:xs="http://www.w3.org/2001/XMLSchema"
                    xmlns:wd="urn:com.workday.report/Test"
                    exclude-result-prefixes="xs"
                    version="2.0">
        <xsl:output method="text"
                    omit-xml-declaration="yes"/>
        <!-- Variables to hold fillers - pipe, new line, double quotes -->
        <xsl:variable name="delimiter"
                      select="'|'"/>
        <xsl:variable name="linefeed"
                      select="'&#xd;&#xa;'"/>
        <xsl:variable name="dQuote">"</xsl:variable>
        <xsl:variable name="duplicate_key"
                 match="wd:Report_Data/wd:Report_Entry/wd:Location_Changes"
                 select="concat(wd:EmployeeID,'|',wd:RegionCode)" />
        <!--To remove duplicates-->
        <xsl:key name="primary_key"
                 match="wd:Report_Data/wd:Report_Entry/wd:Location_Changes"
         use="concat(wd:EmployeeID,'|',wd:RegionCode,'|',wd:StartDate)" />
        <xsl:template match="/">
            <!-- Header Row Begin -->
            <xsl:text>EmployeeID</xsl:text>
            <xsl:value-of select="$delimiter"/>
            <xsl:text>CountryCode</xsl:text>
            <xsl:value-of select="$delimiter"/>
            <xsl:text>RegionCode</xsl:text>
            <xsl:value-of select="$delimiter"/>
            <xsl:text>StartDate</xsl:text>
            <xsl:value-of select="$linefeed"/>
            <!-- Header Row End -->
            <!-- Data Row Starts -->
            <!-- Parse each and every employee record -->       
            <!--To Reverse the Records and Remove duplicates-->
            <xsl:for-each select="wd:Report_Data/wd:Report_Entry/wd:Location_Changes[generate-id()= generate-id(key('primary_key',concat(wd:EmployeeID,'|',wd:RegionCode,'|',wd:StartDate))[1])]">
                <xsl:sort select="position()"
                          data-type="number"
                          order="descending"/>  
                <xsl:call-template name="output">
                    <xsl:with-param name="unique_code"/>                
                </xsl:call-template>
            </xsl:for-each>
        </xsl:template>
        <xsl:template name="output">
            <xsl:param name="unique_code"/>
            <!-- Data Row Begins -->
            <xsl:if test="$duplicate_key != concat(wd:EmployeeID,'|',wd:RegionCode)">
                <!-- #1 EmployeeID -->
                <xsl:value-of select="$dQuote"/>
                <xsl:value-of select="wd:EmployeeID"/>
                <xsl:value-of select="$dQuote"/>
                <xsl:value-of select="$delimiter"/>
                <!-- #2 CountryCode -->
                <xsl:value-of select="$dQuote"/>
                <xsl:value-of select="wd:CountryCode"/>
                <xsl:value-of select="$dQuote"/>
                <xsl:value-of select="$delimiter"/>
                <!-- #3 RegionCode-->
                <xsl:value-of select="$dQuote"/>
                <xsl:value-of select="wd:RegionCode"/>
                <xsl:value-of select="$dQuote"/>
                <xsl:value-of select="$delimiter"/>
                <!-- #4 StartDate-->
                <xsl:value-of select="$dQuote"/>
                <xsl:value-of select="wd:StartDate"/>
                <xsl:value-of select="$dQuote"/>
                <xsl:value-of select="$linefeed"/>  
            </xsl:if>       
            <!-- To Remove Consecutive Duplicates-->
            <xsl:variable name="duplicate_key"?
                 match="wd:Report_Data/wd:Report_Entry/wd:Location_Changes"
                 select="concat(wd:EmployeeID,'|',wd:RegionCode)" />    
            <!-- Data Row End -->
        </xsl:template>
    </xsl:stylesheet>

如果“EmployeeID | RegionCode”存在另一个具有相同组合的连续条目,则不应包含该条目。         我使用了主键来确保没有重复的条目。

我正在使用以下XSLT:

function sortUL(selector) {
    var $ul = $(selector);
    $ul.find('li').sort(function (a, b) {
    var upA = $(a).text().toUpperCase();
    var upB = $(b).text().toUpperCase();
    return (upA < upB) ? -1 : (upA > upB) ? 1 : 0;
    }).appendTo(selector);
};

$(document).ready(function () {
    sortUL(".dropdown-menu");
});

这里的问题是我无法删除连续重复

2 个答案:

答案 0 :(得分:1)

  

如果有另一个具有相同组合的连续条目   &#34; EmployeeID | RegionCode&#34;,则不应包含该条目。

除非我遗漏了某些内容,否则您应该能够通过对相邻startup.cs(基于wd:Report_Entrywd:EmployeeID)进行分组来简化流程,并且只需处理最后一项基。

注意:相邻意味着&#34;在&#34;旁边,与您在评论中描述的不同; 只需要删除连续的重复项,并且需要保留相邻的重复项。&#34;

XML输入

wd:RegionCode

XSLT 2.0

<wd:Report_Data xmlns:wd="urn:com.workday.report/Test">
    <wd:Report_Entry>
        <wd:Location_Changes>
            <wd:EmployeeID>111111</wd:EmployeeID>
            <wd:CountryCode>US</wd:CountryCode>
            <wd:RegionCode>RX</wd:RegionCode>
            <wd:StartDate>2013-07-01</wd:StartDate>
        </wd:Location_Changes>
        <wd:Location_Changes>
            <wd:EmployeeID>111111</wd:EmployeeID>
            <wd:CountryCode>US</wd:CountryCode>
            <wd:RegionCode>MD</wd:RegionCode>
            <wd:StartDate>2009-09-14</wd:StartDate>
            <!--remove-->
        </wd:Location_Changes>
        <wd:Location_Changes>
            <wd:EmployeeID>111111</wd:EmployeeID>
            <wd:CountryCode>US</wd:CountryCode>
            <wd:RegionCode>MD</wd:RegionCode>
            <wd:StartDate>2009-10-14</wd:StartDate>
            <!--keep-->
        </wd:Location_Changes>
        <wd:Location_Changes>
            <wd:EmployeeID>111111</wd:EmployeeID>
            <wd:CountryCode>US</wd:CountryCode>
            <wd:RegionCode>RX</wd:RegionCode>
            <wd:StartDate>2014-07-01</wd:StartDate>
        </wd:Location_Changes>
    </wd:Report_Entry>
</wd:Report_Data>

<强>输出

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

  <xsl:template match="/*">
    <xsl:text>EmployeeID|CountryCode|RegionCode|StartDate&#xA;</xsl:text>
    <xsl:for-each-group select="Report_Entry/Location_Changes" 
      group-adjacent="concat(EmployeeID,'|',RegionCode)">
      <xsl:sort select="position()" order="descending"/>
      <xsl:apply-templates select="current-group()[last()]"/>
    </xsl:for-each-group>
  </xsl:template>

  <xsl:template match="Location_Changes">
    <xsl:value-of select="concat('&quot;',
      string-join((EmployeeID,CountryCode,RegionCode,StartDate),'&quot;|&quot;'),
      '&quot;&#xA;')"/>
  </xsl:template>

</xsl:stylesheet>

答案 1 :(得分:1)

一些推送编程应该让你到那里。这应该很容易适应2.0。只需根据需要更改样式表和输出声明。

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:wd="urn:com.workday.report/Test"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
    exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

<xsl:template match="wd:Report_Entry">
  <xsl:value-of select="concat('EmployeeID|CountryCode|RegionCode|StartDate','&#xD;&#xA;')"/>
  <xsl:apply-templates select="node()|@*"/>
</xsl:template>  

<xsl:template match="wd:Location_Changes">
  <xsl:if test="not(preceding-sibling::wd:Location_Changes[1]/wd:EmployeeID = wd:EmployeeID and
                    preceding-sibling::wd:Location_Changes[1]/wd:RegionCode = wd:RegionCode)">

    <xsl:value-of select="concat(wd:EmployeeID,'|',wd:CountryCode,'|',wd:RegionCode,'|',wd:StartDate,'&#xD;&#xA;')"/>

  </xsl:if>
</xsl:template>

<xsl:template match="node()|@*">
  <xsl:apply-templates select="node()|@*"/>
</xsl:template>

</xsl:stylesheet>