2012-09-18 21 views
5

Tôi đã tạo XSLT và tôi đã tự hỏi làm thế nào có thể sao chép tất cả các nút giữa một bộ thẻ và thêm thẻ khác ở dưới cùng. Tôi đã tạo XSLT có tất cả các logic để xác định thẻ cần thêm và cái gì cần được gọi. Tuy nhiên vấn đề bây giờ tôi nhận được là tôi không thể sao chép tất cả các thẻ khác trên. Dưới đây là các tập tin trong câu hỏi:XSLT - Sao chép tất cả các nút khác, thêm 1 nút mới

XSLT

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

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

    <xsl:template match="/csvImportSchema"> 
     <csvImportSchema> 
      <xsl:for-each select="payload"> 
       <payload> 
        <xsl:copy-of select="@*"/> 
        <xsl:variable name="ean"> 
         <xsl:value-of select="ean"/> 
        </xsl:variable> 
        <xsl:for-each select="../product"> 
         <xsl:if test="ean = $ean"> 
          <productId><xsl:value-of select="article"/></productId> 
         </xsl:if> 
        </xsl:for-each> 
       </payload> 
      </xsl:for-each> 
     </csvImportSchema> 
    </xsl:template> 

</xsl:stylesheet> 

ĐẦU VÀO

<?xml version="1.0" encoding="UTF-8"?> 
<csvImportSchema> 
    <payload> 
     <test>1</test> 
     <test2>2</test2> 
     <test3>3</test3> 
     <ean>1111111111</ean> 
     <productId/> 
    </payload> 
    <product> 
     <article>722619</article> 
     <ean>1111111111</ean> 
    </product> 
</csvImportSchema> 

HIỆN OUTPUT

<?xml version="1.0" encoding="utf-8"?> 
<csvImportSchema> 
    <payload> 
     <productId>722619</productId> 
    </payload> 
</csvImportSchema> 

MONG MUỐN OUTPUT

<?xml version="1.0" encoding="UTF-8"?> 
<csvImportSchema> 
    <payload> 
     <test>1</test> 
     <test2>2</test2> 
     <test3>3</test3> 
     <ean>1111111111</ean> 
     <productId>722619</productId> 
    </payload> 
</csvImportSchema> 

Trả lời

7

ngắn và đơn giản chuyển đổi này:

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

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

<xsl:template match="productId"> 
    <productId> 
    <xsl:value-of select="../../product/article"/> 
    </productId> 
</xsl:template> 
<xsl:template match="product"/> 
</xsl:stylesheet> 

khi áp dụng trên tài liệu XML cung cấp:

<csvImportSchema> 
    <payload> 
     <test>1</test> 
     <test2>2</test2> 
     <test3>3</test3> 
     <ean>1111111111</ean> 
     <productId/> 
    </payload> 
    <product> 
     <article>722619</article> 
     <ean>1111111111</ean> 
    </product> 
</csvImportSchema> 

tạo ra truy nã, chính xác kết quả:

<csvImportSchema> 
    <payload> 
     <test>1</test> 
     <test2>2</test2> 
     <test3>3</test3> 
     <ean>1111111111</ean> 
     <productId>722619</productId> 
    </payload> 
</csvImportSchema> 

Giải thích:

  1. Các identity rule bản sao "như-là" mỗi nút mà nó được chọn để thực hiện.

  2. Mẫu ghi đè khớp với product "xóa" phần tử này khỏi đầu ra (bởi phần trống của phần tử này).

  3. Mẫu ghi đè khác khớp với productId và tạo phần tử này với nút con văn bản được lấy từ product/article.

1

Nó nên càng đơn giản như thay đổi tải trọng của bạn xsl:copy-of select="@*"/ để

<xsl:copy-of select="*[local-name() != 'productId'] | @*"/> 

ví dụ: sao chép tất cả mọi thứ, trừ productId, bởi vì bạn xây dựng này lên bằng tay.

này cung cấp cho các đầu ra bạn đã yêu cầu

<?xml version="1.0" encoding="utf-8"?> 
<csvImportSchema> 
    <payload> 
    <test>1</test> 
    <test2>2</test2> 
    <test3>3</test3> 
    <ean>1111111111</ean> 
    <productId>722619</productId> 
    </payload> 
</csvImportSchema> 
1

XSLT này nên thực hiện công việc và sử dụng cách nhiều thẻ COPY và các mẫu. Có lẽ không làm mọi thứ trong một xsl: template (ý kiến ​​của tôi).

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

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

    <xsl:template match="/csvImportSchema"> 
     <xsl:copy> 
      <xsl:apply-templates select="*"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="csvImportSchema/payload/productId"> 
     <xsl:variable name="ean"> 
      <xsl:value-of select="../ean"/> 
     </xsl:variable> 
     <xsl:for-each select="../../product"> 
      <xsl:if test="ean = $ean"> 
       <productId><xsl:value-of select="article"/></productId> 
      </xsl:if> 
     </xsl:for-each> 
    </xsl:template> 

    <xsl:template match="csvImportSchema/product"> 
     <!-- do not copy --> 
    </xsl:template> 

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

Một quan sát trên mã của bạn. Không sử dụng này:

<xsl:variable name="ean"> 
    <xsl:value-of select="../ean"/> 
</xsl:variable> 

khi bạn có thể viết này:

<xsl:variable name="ean" select="../ean"/> 

Không chỉ là nó tiết, nó cũng vô cùng hiệu quả: thay vì ràng buộc $ EAN đến một nút hiện tại, bạn đang giải nén giá trị chuỗi của một nút hiện có, tạo thành một nút văn bản có giá trị chuỗi đó, tạo một cây tài liệu XML mới và thêm nút văn bản này vào nội dung của tài liệu mới này. (Tôi đã từng có một bản định kiểu để chạy nhanh gấp 3 lần bằng cách loại bỏ cấu trúc khủng khiếp này.)

+0

Cảm ơn bạn. Tôi sẽ giữ cho rằng trong tâm trí. – MMKD

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