2012-09-25 35 views
5

Input xmlXSLT sáp nhập/concatenating giá trị của anh chị em các nút của cùng tên vào nút đơn

<catalog> 
    <product id="1"> 
     <name>abc</name> 
     <category>aaa</category> 
     <category>bbb</category> 
     <category>ccc</category> 
    </product> 
    <product id="2"> 
     <name>cde</name> 
     <category>aaa</category> 
     <category>bbb</category> 
    </product> 
</catalog> 

Dự kiến ​​Output xml

<products> 
    <product> 
     <id>1</id> 
     <name>abc</name> 
     <category>aaa,bbb,ccc</category> 
    </product> 
    <product> 
     <id>2</id> 
     <name>cde</name> 
     <category>aaa,bbb</category> 
    </product> 
</products> 

XSLT để chuyển đổi

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:template match="/catalog"> 
     <products> 
      <xsl:for-each select="product"> 
       <product> 
        <id><xsl:value-of select="@id"/></id> 
        <name><xsl:value-of select="name"/></name> 
        <category><xsl:value-of select="category" /></category> 
       </product> 
      </xsl:for-each> 
     </products> 
    </xsl:template> 
</xsl:stylesheet> 

thực tế Output xml: (

<products> 
    <product> 
     <id>1</id> 
     <name>abc</name> 
     <category>aaa</category> 
    </product> 
    <product> 
     <id>2</id> 
     <name>cde</name> 
     <category>aaa</category> 
    </product> 
</products> 

Mã cần thiết trong vòng lặp qua tất cả nút anh chị em bằng tên 'danh mục' trong mỗi 'sản phẩm' và hợp nhất/ghép vào một nút riêng biệt bằng dấu phẩy. Số lượng 'danh mục' khác nhau đối với mỗi sản phẩm và do đó số lượng không xác định.

Trả lời

8

Sử dụng này tiện dụng tham gia cuộc gọi mẫu định nghĩa here, điều này trở nên đơn giản như:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:template match="/catalog"> 
     <products> 
      <xsl:for-each select="product"> 
       <product> 
        <id> 
         <xsl:value-of select="@id"/> 
        </id> 
        <name> 
         <xsl:value-of select="name"/> 
        </name> 
        <category> 
         <xsl:call-template name="join"> 
          <xsl:with-param name="list" select="category" /> 
          <xsl:with-param name="separator" select="','" /> 
         </xsl:call-template> 
        </category> 
       </product> 
      </xsl:for-each> 
     </products> 
    </xsl:template> 

    <xsl:template name="join"> 
     <xsl:param name="list" /> 
     <xsl:param name="separator"/> 

     <xsl:for-each select="$list"> 
      <xsl:value-of select="." /> 
      <xsl:if test="position() != last()"> 
       <xsl:value-of select="$separator" /> 
      </xsl:if> 
     </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 

Output:

<products> 
    <product> 
    <id>1</id> 
    <name>abc</name> 
    <category>aaa,bbb,ccc</category> 
    </product> 
    <product> 
    <id>2</id> 
    <name>cde</name> 
    <category>aaa,bbb</category> 
    </product> 
</products> 
6

Trong XSLT 2.0, bạn chỉ cần thực hiện một thay đổi nhỏ cho mã của bạn :

<category><xsl:value-of select="category" separator=","/></category> 

Lưu ý rằng nếu bạn yêu cầu giải pháp XSLT 1.0, đó là ý tưởng tốt để nói như vậy. Một số người trong một số môi trường bị mắc kẹt trên 1.0, nhưng nhiều người thì không.

+0

Ah có, phiên bản 1.0 và phiên bản biểu định kiểu xslt của nó nói như vậy. – user1677271

+1

Số phiên bản trên biểu định kiểu cho chúng tôi biết về khả năng của bộ xử lý XSLT bạn đang sử dụng hoặc khả năng của dự án để chuyển sang bộ xử lý cập nhật hơn. –

3

Đây là một giải pháp XSLT 1.0 khác.

Khi XSLT này:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
version="1.0"> 
    <xsl:output omit-xml-declaration="no" indent="yes" /> 
    <xsl:strip-space elements="*" /> 

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

    <xsl:template match="product"> 
    <xsl:copy> 
     <xsl:apply-templates select="*[not(self::category)]" /> 
     <category> 
     <xsl:apply-templates select="category/text()" /> 
     </category> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="category/text()"> 
    <xsl:if test="position() &gt; 1">,</xsl:if> 
    <xsl:value-of select="."/> 
    </xsl:template> 
</xsl:stylesheet> 

... được áp dụng cho XML của OP gốc:

<catalog> 
    <product id="1"> 
    <name>abc</name> 
    <category>aaa</category> 
    <category>bbb</category> 
    <category>ccc</category> 
    </product> 
    <product id="2"> 
    <name>cde</name> 
    <category>aaa</category> 
    <category>bbb</category> 
    </product> 
</catalog> 

... kết quả mong muốn được sản xuất:

<?xml version="1.0"?> 
<catalog> 
    <product> 
    <name>abc</name> 
    <category>aaa,bbb,ccc</category> 
    </product> 
    <product> 
    <name>cde</name> 
    <category>aaa,bbb</category> 
    </product> 
</catalog> 

Giải thích:

  • Mẫu đầu tiên - các Identity Template - phù hợp với tất cả các nút và các thuộc tính và sao chép chúng vào tài liệu kết quả như nó vốn có.
  • Mẫu thứ hai ghi đè Mẫu danh tính bằng cách tạo thành phần <category> mới và xử lý các phần tử văn bản của mỗi phần tử <category> ở vị trí hiện tại của tài liệu.
  • Mẫu cuối cùng xuất ra các giá trị văn bản và dấu phẩy khi cần thiết.
+0

Chưa thử nhưng đánh giá cao các giải pháp khác nhau ABach :) – user1677271

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