2016-05-05 16 views
5

Tôi đang phải vật lộn với các khái niệm về nhóm (trên nhiều phím) của bảng dựa trên XML để hệ thống phân cấp với XSLTnhóm trên các yếu tố trong chuyển đổi XML với XSLT

Các nhóm được dựa trên bốn yếu tố đầu tiên, tuy nhiên nhóm phải ngắt nếu có một phần tử khác nằm giữa tập hợp.

Nguồn XML:

<RECORDS> 
<RECORD> 
    <E1>MICKEY</E1> 
    <E2>TEST</E2> 
    <E4>14</E4> 
    <E5>196</E5> 
    <F1>A1</F1> 
</RECORD> 
<RECORD> 
    <E1>MICKEY</E1> 
    <E2>TEST</E2> 
    <E4>14</E4> 
    <E5>196</E5> 
    <F1>A2</F1> 
</RECORD> 
<RECORD> 
    <E1>MICKEY</E1> 
    <E2>TEST</E2> 
    <E4>14</E4> 
    <E5>195</E5> 
    <F1>A3</F1> 
    </RECORD> 
<RECORD> 
    <E1>MICKEY</E1> 
    <E2>TEST</E2> 
    <E4>14</E4> 
    <E5>196</E5> 
    <F1>A4</F1> 
    </RECORD> 
<RECORD> 
    <E1>MICKEY</E1> 
    <E2>TEST</E2> 
    <E4>14</E4> 
    <E5>196</E5> 
    <F1>A5</F1> 
    </RECORD> 
    <RECORD> 
    <E1>DONALD</E1> 
    <E2>TEST</E2> 
    <E4>14</E4> 
    <E5>196</E5> 
    <F1>A6</F1> 
    </RECORD> 
<RECORD> 
    <E1>DONALD</E1> 
    <E2>TEST</E2> 
    <E4>14</E4> 
    <E5>196</E5> 
    <F1>A7</F1> 
    </RECORD> 
</RECORDS> 

Output XML

<RECORDS> 
<RECORD> 
    <E1>MICKEY</E1> 
    <E2>TEST</E2> 
    <E4>14</E4> 
    <E5>196</E5> 
    <F> 
    <F1>A1</F1> 
    <F1>A2</F1> 
    </F> 
    </RECORD> 
    <RECORD> 
    <E1>MICKEY</E1> 
    <E2>TEST</E2> 
    <E4>14</E4> 
    <E5>195</E5> 
    <F> 
    <F1>A3</F1> 
    <F1>A4</F1> 
    </F> 
    </RECORD> 
    <RECORD> 
    <E1>MICKEY</E1> <!--Must break and not merge in first group --> 
    <E2>TEST</E2> 
    <E4>14</E4> 
    <E5>196</E5> 
    <F> 
    <F1>A5</F1> 
    </F> 
    </RECORD> 
    <RECORD> 
    <E1>DONALD</E1> 
    <E2>TEST</E2> 
    <E4>14</E4> 
    <E5>196</E5> 
    <F> 
    <F1>A6</F1> 
    <F1>A7</F1> 
    </F> 
    </RECORD> 
</RECORDS> 

Đây là XSL tôi đã đưa ra cho đến nay ...

<?xml version="1.0"?> 
<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:output method="xml" indent="yes"/> 
<xsl:key name="grouped" match="RECORD" 
    use="concat(E1, '+', E2, '+', E4 , '+', E5)"/> 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 
<xsl:template match="/*"> 
    <RECORDS> 
    <xsl:apply-templates select= 
    "RECORD[generate-id() 
      = 
      generate-id(key('grouped', 
         concat(E1, '+', E2, '+', E4 , '+', E5) 
         ) 
          [1] 
        ) 
      ] 
    "/> 
    </RECORDS> 
</xsl:template> 
<xsl:template match="RECORD"> 
    <RECORD> 
    <E1><xsl:value-of select="E1"/></E1> 
<E2><xsl:value-of select="E2"/></E2> 
<E4><xsl:value-of select="E4"/></E4> 
<F> 
<xsl:for select="F1"> 
<F1><xsl:value-of select="F1"/></F1> 
</xsl:for> 

</F> 
    </RECORD> 

</xsl:template> 
</xsl:stylesheet> 

Vấn đề là tôi không thể tạo ra gãi trong thẻ cho mỗi f1. Ngoài ra tôi sẽ nhận được 4 bộ HỒ SƠ, không phải 3 mà tôi nhận được với điều này.

<RECORDS> 
    <RECORD> 
    <E1>MICKEY</E1> 
    <E2>TEST</E2> 
    <E4>14</E4> 
    <F></F> 
    </RECORD> 
    <RECORD> 
    <E1>MICKEY</E1> 
    <E2>TEST</E2> 
    <E4>14</E4> 
    <F></F> 
    </RECORD> 
    <RECORD> 
    <E1>DONALD</E1> 
    <E2>TEST</E2> 
    <E4>14</E4> 
    <F></F> 
    </RECORD> 
</RECORDS> 
+0

Vui lòng xác định độ khó của bạn - tốt nhất là đăng nỗ lực của bạn để chúng tôi có thể khắc phục. –

Trả lời

3

Dường như bạn muốn thực hiện trong XSLT 1.0 tương đương với số group-adjacent của XSLT 2.0. Điều này có thể đạt được bằng cách sử dụng kỹ thuật gọi là "anh chị em đệ quy":

XSLT 1,0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 

<xsl:template match="/RECORDS"> 
    <xsl:copy> 
     <!-- start the first group --> 
     <xsl:apply-templates select="RECORD[1]"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="RECORD"> 
    <xsl:variable name="key" select="concat(E1, '+', E2, '+', E4 , '+', E5)" /> 
    <xsl:copy> 
     <xsl:copy-of select="E1 | E2 | E4 | E5"/> 
     <F> 
      <xsl:copy-of select="F1"/> 
      <!-- immediate sibling in the same group --> 
      <xsl:apply-templates select="following-sibling::RECORD[1][concat(E1, '+', E2, '+', E4 , '+', E5) = $key]" mode="collect"/> 
     </F> 
    </xsl:copy> 
    <!-- start the next group --> 
    <xsl:apply-templates select="following-sibling::RECORD[not(concat(E1, '+', E2, '+', E4 , '+', E5)=$key)][1]"/> 
</xsl:template> 

<xsl:template match="RECORD" mode="collect"> 
    <xsl:variable name="key" select="concat(E1, '+', E2, '+', E4 , '+', E5)" /> 
    <xsl:copy-of select="F1"/> 
    <!-- immediate sibling in the same group --> 
    <xsl:apply-templates select="following-sibling::RECORD[1][concat(E1, '+', E2, '+', E4 , '+', E5) = $key]" mode="collect" /> 
</xsl:template> 

</xsl:stylesheet> 
+0

Giải pháp tuyệt vời! Đã cho tôi một thời gian để hiểu, nhưng cuối cùng đã hiểu – ggonsalv

4

Đây là một giải pháp sử dụng phím. Ngắn hơn (ít hơn 28% dòng mã và không yêu cầu cuộn ngang). Mạnh mẽ hơn (xem phần cuối của câu trả lời này để biết chi tiết)

Tổng quát hơn, vì nó sẽ hoạt động ngay cả trong trường hợp giữa các phần tử chúng tôi muốn nhóm, có các yếu tố khác phải bỏ qua (có nghĩa là nơi preceding-sibling::*[1] có thể là một yếu tố chúng ta muốn loại trừ khỏi nhóm - trong vấn đề hiện tại - không phải là một yếu tố RECORD):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 

    <xsl:key name="kStartGroup" match="/*/*" use= 
    "generate-id(preceding-sibling::* 
     [not(concat(E1, '|', E2, '|', E4, '|', E5) 
      = concat(current()/E1, '|', current()/E2, '|', current()/E4, '|', current()/E5) 
     ) 
     ][1])"/> 
    <xsl:template match="*[not(concat(E1, '|', E2, '|', E4, '|', E5) 
          = 
           concat(preceding-sibling::*[1]/E1, '|', 
            preceding-sibling::*[1]/E2, '|', 
            preceding-sibling::*[1]/E4, '|', 
            preceding-sibling::*[1]/E5) 
          )]"> 
    <xsl:copy> 
     <xsl:copy-of select="E1 | E2 | E4 | E5"/> 
     <F><xsl:copy-of select= 
         "key('kStartGroup', generate-id(preceding-sibling::*[1]))/F1"/></F> 
    </xsl:copy> 
    </xsl:template> 
    <xsl:template match="/*"><xsl:copy><xsl:apply-templates/></xsl:copy></xsl:template>  
    <xsl:template match="text()"/> 
</xsl:stylesheet> 

Mạnh mẽ/Khả năng mở rộng

Vì transf này ormation không chứa đệ quy (các cuộc gọi lồng nhau đến <xsl:apply-templates), nó mạnh mẽ và có thể mở rộng khi được áp dụng trên các tệp XML lớn.

Ở phía bên kia, giải pháp được cung cấp trong câu trả lời khác "truy vấn anh chị em" do sự cố tràn ngăn khi chuyển đổi được áp dụng trên tài liệu XML đủ lớn. Trong trường hợp của tôi vụ tai nạn này đã được quan sát với tài liệu XML nguồn khoảng 13 000 (13 nghìn dòng) - điều này có thể khác nhau tùy thuộc vào RAM có sẵn, bộ xử lý XSLT, v.v.

Phép biến đổi hiện hành thực hiện thành công ngay cả trên các tài liệu XML cực lớn - chẳng hạn như có 1 200 000 (một triệu và 200 nghìn dòng).

Các vấn đề liên quan