2017-03-28 8 views
1

こんにちは、次のXMLの2つの連続した項目を比較しようとしています。XSLTを使用して連続する2行のXMLを比較する

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"" 

しかし、私は期待しています::

<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> 
       </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> 
       </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> 

出力がある

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

ための同じ組み合わせを持つ別の連続したエントリがある場合は、 "社員| RegionCode"、そのエントリがすべき含まれない。 私は主キーを使用して重複したエントリがないことを確認しました。

私は、次のXSLTを使用しています:

<?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> 

ここでの問題 「社員のための同じ組み合わせを持つ別の連続したエントリがある場合、私は

+0

** 1 **「連続」部分の重要度はどれくらいですか?隣接していない重複を保持しますか? ** 2。** "EmployeeID | RegionCode" * "の" *同じ組み合わせ "として重複を定義する場合、なぜテストにStartDateを含めるのですか? ** 3。** XSLT 2.0を使用している場合は、XSLT 2.0のネイティブなグループ化方法を使用してください。 –

+0

1.連続部分は本当に重要です。連続する重複のみを削除する必要があり、隣接する重複を保持する必要があります。 2.同じEmployeeID | RegionCodeがいくつかの異なるエントリの後に出現する可能性があるので、StartDateがキーに必要です。 3.注文は同じである必要があります。それを変更することはできません。 –

+0

あなたは一つのことを言っており、あなたの期待される出力は別のことを言います。 –

答えて

1

連続重複を削除することはできませんよです| RegionCode "の場合、その項目は含まれません。

私は何かが欠けていない限り、あなたは(wd:EmployeeIDwd:RegionCodeに基づいて)隣接wd:Report_Entryをグループ化し、ちょうどグループ内の最後のエントリを処理することにより、プロセスを簡素化することができるはずです。

注:あなたのコメントに記載されているものとは異なり、隣接する「隣」は「」という連続した重複のみを削除し、隣接する重複を保持する必要があります。 "。

XML入力

<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> 

XSLT 2.0

<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> 

出力

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

ありがとうダニエル:) –

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> 
+0

ありがとうございました:) 期待通りに動作します –

+0

私はそれを聞いてうれしいです。 – Bluewood66

関連する問題