2009-03-14 10 views
6

Tôi có một XML như thế nàyXSLT: Merge kịch bản trùng lặp

<ContractInfo ContractNo="12345"> 
       <Details LastName="Goodchild">       
         <Filedata FileName="File1"/> 
       </Details> 
</ContractInfo> 

<ContractInfo ContractNo="12345"> 
       <Details LastName="Goodchild">       
         <Filedata FileName="File2"/> 
       </Details> 
</ContractInfo> 

<ContractInfo ContractNo="123456"> 
       <Details LastName="Goodchild">       
         <Filedata FileName="File2"/> 
       </Details> 
</ContractInfo> 

Tôi muốn đầu ra XML của tôi là như thế này

<ContractInfo ContractNo="12345"> 
       <Details LastName="Goodchild">       
         <Filedata FileName="File1"/> 
         <Filedata FileName="File2"/> 
       </Details> 
</ContractInfo> 

<ContractInfo ContractNo="123456"> 
       <Details LastName="Goodchild">       
         <Filedata FileName="File2"/> 
       </Details> 
</ContractInfo> 

Ở đây, 'fileData' liên quan đến phù hợp với "contractNo" nhu cầu được kết hợp ở đầu ra. Sự chuyển đổi này có thể đạt được với XSLT không?

Xin cảm ơn trước.

Srini

+0

Phiên bản của XSLT và nền tảng có thể hữu ích – AnthonyWJones

Trả lời

7

Các XSLT sau 1.0 chuyển đổi tạo ra kết quả đúng:

<xsl:stylesheet version="1.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output method="xml" indent="yes" /> 

    <xsl:key name="contract" match="ContractInfo" use="@ContractNo" /> 
    <xsl:key name="filedata" match="Filedata" use="../../@ContractNo" /> 

    <xsl:template match="ContractInfo"> 
    <xsl:if test="generate-id() = 
        generate-id(key('contract', @ContractNo)[1])"> 
     <xsl:copy> 
     <xsl:apply-templates select="key('contract', @ContractNo)/Details | @*" /> 
     </xsl:copy> 
    </xsl:if> 
    </xsl:template> 

    <xsl:template match="Details"> 
    <xsl:if test="generate-id(..) = 
        generate-id(key('contract', ../@ContractNo)[1])"> 
     <xsl:copy> 
     <xsl:apply-templates select="key('filedata', ../@ContractNo) | @*" /> 
     </xsl:copy> 
    </xsl:if> 
    </xsl:template> 

    <!-- copy everything else (root node, Filedata nodes and @attributes) --> 
    <xsl:template match="* | @*"> 
    <xsl:copy> 
     <xsl:apply-templates select="* | @*" /> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

Lưu ý việc sử dụng <xsl:key> kết hợp với generate-id() để xác định các nút đầu tiên của một bộ nút phù hợp, nhóm một cách hiệu quả hạch bằng cùng với nhau.

Bạn có thể buộc kết quả theo thứ tự bằng cách sử dụng <xsl:sort> trong số <xsl:apply-templates>. Tôi không bao gồm điều đó vì lợi ích của sự rõ ràng.

đầu ra thử nghiệm của tôi là:

<root> 
    <ContractInfo ContractNo="12345"> 
    <Details LastName="Goodchild"> 
     <Filedata FileName="File1"></Filedata> 
     <Filedata FileName="File2"></Filedata> 
    </Details> 
    </ContractInfo> 
    <ContractInfo ContractNo="123456"> 
    <Details LastName="Goodchild"> 
     <Filedata FileName="File2"></Filedata> 
    </Details> 
    </ContractInfo> 
</root> 
+0

Nó là tương đối dễ dàng để mở rộng việc chuyển đổi để loại trừ trùng lặp nút là tốt. Vì đó không phải là một phần của yêu cầu ban đầu nên tôi để nó như một bài tập cho người đọc. ;-) Gợi ý: Cần thêm một số và một khác. – Tomalak

+0

hi, công cụ tuyệt vời .. có bất kỳ liên kết nào để nghiên cứu các khái niệm này một cách chi tiết không? Bạn có thể đề nghị một trong những bao gồm những chuyển đổi từ những điều cơ bản? –

+0

Có rất nhiều trang web và hướng dẫn liên quan đến XSLT/XPath trên internet. Chỉ cần google những phần bạn không hiểu. Tùy thuộc vào mức độ kiến ​​thức XSLT hiện tại của bạn, tuy nhiên, giải pháp có thể mất một thời gian để trở nên trong suốt. ;-) – Tomalak