2014-07-11 3 views
0

당신은 내가 강타하고 내 XSLT 좀 도와 주시겠습니까 속성,XSLT 정렬 및 요소에 따라 중복을 제거하고

요구 사항 : 내 XML에서 제공의 모든 레코드/SKU가 동일하고, 제공/고객 -attributes/custom-attribute/Feed_SKU가 강하면 그 레코드를 유지해야합니다 (이것은 최신 레코드이고 다른 하나는 무시합니다).

내 케이스 Feed_SKU = 09/07/2014 23:21:20이 최신 기록입니다.

저는 xsl : key를 사용하여 비교하고 속성 값 (Feed_SKU)을 분석하는 데 약간의 어려움을 겪었습니다. 여기 좀 도와주세요.

입력 XML : 내가 일하고

<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<enfinity xmlns="http://www.intershop.com/xml/ns/enfinity/6.5/xcs/impex" xsi:schemaLocation="http://www.intershop.com/xml/ns/enfinity/6.5/xcs/impex catalog.xsd http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt dt.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" family="enfinity" major="6" minor="1"> 
<offer import-mode="UPDATE" sku="36-5149574"> 
<sku>36-5149574</sku> 
<custom-attributes> 
<custom-attribute name="OriginalFileName" dt:dt="string" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt">Message_20140709_2321130190_BP71794596.dat_SKU</custom-attribute> 
<custom-attribute name="FacilityId" dt:dt="string" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt">385</custom-attribute> 
<custom-attribute name="GII" dt:dt="string" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt">6661116</custom-attribute> 
<custom-attribute name="CountryOrigin" dt:dt="string" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt">US</custom-attribute> 
<custom-attribute name="UOMSystem" dt:dt="string" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt">I</custom-attribute> 
<custom-attribute name="CartonType" dt:dt="string" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt">AF</custom-attribute> 
<custom-attribute name="Catalog" dt:dt="string" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt">36</custom-attribute> 
<custom-attribute name="Height" dt:dt="quantity" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt">3 in</custom-attribute> 
<custom-attribute name="Length" dt:dt="quantity" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt">14 in</custom-attribute> 
<custom-attribute name="Width" dt:dt="quantity" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt">10.5 in</custom-attribute> 
<custom-attribute name="Weight" dt:dt="quantity" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt">9.7 lb</custom-attribute> 
<custom-attribute name="Feed_SKU" dt:dt="string" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt">09/07/2014 23:21:14</custom-attribute> 
</custom-attributes> 
</offer> 
<offer import-mode="UPDATE" sku="36-5149574"> 
<sku>36-5149574</sku> 
<custom-attributes> 
<custom-attribute name="OriginalFileName" dt:dt="string" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt">Message_20140709_2321130190_BP71794596.dat_SKU</custom-attribute> 
<custom-attribute name="FacilityId" dt:dt="string" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt">385</custom-attribute> 
<custom-attribute name="GII" dt:dt="string" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt">6661116</custom-attribute> 
<custom-attribute name="CountryOrigin" dt:dt="string" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt">US</custom-attribute> 
<custom-attribute name="UOMSystem" dt:dt="string" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt">I</custom-attribute> 
<custom-attribute name="CartonType" dt:dt="string" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt">AF</custom-attribute> 
<custom-attribute name="Catalog" dt:dt="string" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt">36</custom-attribute> 
<custom-attribute name="Height" dt:dt="quantity" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt">3 in</custom-attribute> 
<custom-attribute name="Length" dt:dt="quantity" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt">14 in</custom-attribute> 
<custom-attribute name="Width" dt:dt="quantity" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt">10.5 in</custom-attribute> 
<custom-attribute name="Weight" dt:dt="quantity" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt">9.7 lb</custom-attribute> 
<custom-attribute name="Feed_SKU" dt:dt="string" xmlns:dt="http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt">09/07/2014 23:23:23</custom-attribute> 
</custom-attributes> 
</offer> 
</enfinity> 

XLST : 첫째,

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
         version="1.0" 
         xmlns:impex="http://www.intershop.com/xml/ns/enfinity/6.5/xcs/impex" 
         xsi:schemaLocation="http://www.intershop.com/xml/ns/enfinity/6.5/xcs/impex catalog.xsd http://www.intershop.com/xml/ns/enfinity/6.5/core/impex-dt dt.xsd" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <xsl:output omit-xml-declaration="no" indent="yes" method="xml"/> 
    <!-- key for grouping --> 
    <xsl:key name="offerBySku" match="impex:offer" use="impex:sku"/> 
    <xsl:template match="/*"> 
     <xsl:copy> 
      <!-- transfer attributes of the document element --> 
      <xsl:copy-of select="@*"/> 
      <!-- Muenchian method to get one iteration per sku --> 
      <xsl:for-each select="impex:offer[generate-id() = generate-id(key('offerBySku', impex:sku)[1])]"> 
       <!-- sort the group by descending timestamp --> 
       <xsl:for-each select="key('offerBySku', impex:sku)"> 
        <!-- rearrange the timestamp to year, month, day, time --> 
        <xsl:sort order="descending" select="concat(
          substring(impex:custom-attributes/impex:custom-attribute[@name='Feed_SKU'], 7, 4), 
          substring(impex:custom-attributes/impex:custom-attribute[@name='Feed_SKU'], 4, 2), 
          substring(impex:custom-attributes/impex:custom-attribute[@name='Feed_SKU'], 1, 2), 
          substring(impex:custom-attributes/impex:custom-attribute[@name='Feed_SKU'], 11))"/> 
        <!-- copy just the first element in sorted order, i.e. the one with the latest date--> 
        <xsl:copy-of select="."/> 
        <xsl:if test="position() = 1"> 
         <xsl:copy-of select="."/> 
        </xsl:if> 
       </xsl:for-each> 
      </xsl:for-each> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 
+0

XSLT 1.0 또는 2.0을 사용하고 있습니까? –

+0

XSLT 1.0 - 내 제한 사항입니다. 고맙습니다. – GSR

+0

필자는 필요한 읽기를 시작하는 것이 좋습니다. http://www.jenitennison.com/xslt/grouping/muenchian.html 그런 다음 구현에 어려움이있는 경우 질문을 편집하십시오. –

답변

1

은이 문제에 대한 두 부분이 있습니다 (작동하지 않음) 함께 같은 sku을 공유하는 이벤트를 그룹화하고 두 번째로 각 그룹 내의 최신 날짜를 찾습니다. 첫 번째 부분에서는 Muenchian 그룹화를 사용할 수 있습니다. 두 번째로 문자열 조작을 통해 창의력을 발휘해야합니다. XSLT 1.0에는 날짜와 시간에 대한 특별한 지원이 없으므로 타임 스탬프 값을 연대순으로 일치하는 형식으로 마사지해야합니다 사전 편집 순서.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" 
     xmlns:impex="http://www.intershop.com/xml/ns/enfinity/6.5/xcs/impex"> 

    <!-- key for grouping --> 
    <xsl:key name="offerBySku" match="impex:offer" use="impex:sku" /> 

    <xsl:template match="/*"> 
    <xsl:copy> 
     <!-- transfer attributes of the document element --> 
     <xsl:copy-of select="@*"/> 
     <!-- Muenchian method to get one iteration per sku --> 
     <xsl:for-each select="impex:offer[ 
      generate-id() = generate-id(key('offerBySku', impex:sku)[1])]"> 
     <!-- sort the group by descending timestamp --> 
     <xsl:for-each select="key('offerBySku', impex:sku)"> 
      <!-- rearrange the timestamp to year, month, day, time --> 
      <xsl:sort order="descending" select="concat(
       substring(impex:custom-attributes/impex:custom-attribute[ 
          @name='Feed_SKU'], 7, 4), 
       substring(impex:custom-attributes/impex:custom-attribute[ 
          @name='Feed_SKU'], 4, 2), 
       substring(impex:custom-attributes/impex:custom-attribute[ 
          @name='Feed_SKU'], 1, 2), 
       substring(impex:custom-attributes/impex:custom-attribute[ 
          @name='Feed_SKU'], 11))" /> 
      <!-- copy just the first element in sorted order, i.e. the one with 
       the latest date --> 
      <xsl:if test="position() = 1"> 
      <xsl:copy-of select="." /> 
      </xsl:if> 
     </xsl:for-each> 
     </xsl:for-each> 
    </xsl:copy> 
    </xsl:template> 

내가 타임 스탬프가이 질문에 질문을 받았다 9 월, 2014 년 7 날짜 이후가 될 것이기 때문이다/월/년을 dd는되지만 가정 한 그들이 실제로 있다면 mm/DD/YYYY 다음 ' 두 번째 및 세 번째 substring 호출을 바꿔 주문해야합니다.

+0

고마워요. 이안. 그것은 완벽하게 작동합니다. 이것을 다른 데이터로 구현하면 네임 스페이스에 문제가 있습니다. 내 루트 요소 Store에는 xmlns, xsi : schemaLocation, xmlns : xsi 및 someother stuff와 같은 일부 네임 스페이스가 있습니다. 나는 단지 내 결과물 그대로 복사하고 싶었다. 내가 그들을 제거하면 xslt가 완벽하게 작동합니다. 어쨌든이 유효성 검사를 무시하고 출력을 그대로 복사 할 수 있습니까? – GSR

+0

@Developer Stack Overflow에서 XSLT의 네임 스페이스를 다루는 다른 많은 질문이 있습니다. 기본적으로 소스 문서에'xmlns = "xxxx"가 있으면 스타일 시트의 접두어와 동일한 네임 스페이스 URI를 바인딩해야합니다 (xsl : stylesheet)에'xmlns : ns0 = "xxxx"를 추가하십시오.) 그리고 XPath 표현식과 일치 패턴에서 그 접두어를 일관되게 사용하십시오 (예 :'') –

+0

'xsi : schemaLocation' 속성과 네임 스페이스 선언을 보존하고 싶다고 말했기 때문에 내 대답을 편집하여 문서 요소의 속성을 복사 할 라인을 추가했습니다. –

관련 문제