Thực hiện chuỗi chuyển đổi được sử dụng khá thường xuyên trong các ứng dụng XSLT, mặc dù thực hiện điều này hoàn toàn trong XSLT 1.0 yêu cầu sử dụng hàm xxx:node-set()
của nhà cung cấp cụ thể. Trong XSLT 2.0 không cần mở rộng như vậy vì kiểu dữ liệu RTF khét tiếng được loại bỏ ở đó.
Dưới đây là một ví dụ (quá đơn giản để có ý nghĩa, nhưng minh họa hoàn toàn cách này được thực hiện):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="vrtfPass1">
<xsl:apply-templates select="/*/*"/>
</xsl:variable>
<xsl:variable name="vPass1"
select="ext:node-set($vrtfPass1)"/>
<xsl:apply-templates mode="pass2"
select="$vPass1/*"/>
</xsl:template>
<xsl:template match="num[. mod 2 = 1]">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="num" mode="pass2">
<xsl:copy>
<xsl:value-of select=". *2"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
khi chuyển đổi này được áp dụng trên các tài liệu XML sau:
<nums>
<num>01</num>
<num>02</num>
<num>03</num>
<num>04</num>
<num>05</num>
<num>06</num>
<num>07</num>
<num>08</num>
<num>09</num>
<num>10</num>
</nums>
mong muốn, kết quả chính xác được tạo ra:
<num>2</num>
<num>6</num>
<num>10</num>
<num>14</num>
<num>18</num>
Giải thích:
Trong bước đầu tiên trên tài liệu XML được chuyển và kết quả được định nghĩa là giá trị của biến $vrtfPass1
. Điều này chỉ sao chép các phần tử num
có giá trị kỳ lạ (thậm chí không).
Biến $vrtfPass1
, là loại RTF, là không trực tiếp sử dụng cho XPath biểu thức vì vậy chúng tôi chuyển nó sang một cái cây bình thường, sử dụng EXSLT (thực hiện bởi hầu hết XSLT 1.0 vi xử lý) chức năng ext:node-set
và xác định một biến khác - - $vPass1
có giá trị là cây này.
Bây giờ chúng tôi thực hiện phép chuyển đổi thứ hai trong chuỗi biến đổi của chúng tôi - trên kết quả của phép biến đổi đầu tiên, được giữ như giá trị của biến $vPass1
. Không gây rối với mẫu đầu tiên, chúng tôi chỉ định rằng quá trình xử lý mới phải ở chế độ có tên, được gọi là "pass2". Trong chế độ này, giá trị của bất kỳ phần tử num
nào được nhân với hai.
XSLT 2.0 giải pháp (không RTFs):
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="vPass1" >
<xsl:apply-templates select="/*/*"/>
</xsl:variable>
<xsl:apply-templates mode="pass2"
select="$vPass1/*"/>
</xsl:template>
<xsl:template match="num[. mod 2 = 1]">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="num" mode="pass2">
<xsl:copy>
<xsl:value-of select=". *2"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Nguồn
2010-12-31 19:46:21
Câu hỏi hay, +1. Xem câu trả lời của tôi cho lời giải thích và một ví dụ mã hoàn chỉnh. :) –
Có, nó được chấp nhận, nhưng không phải lúc nào cũng cần thiết. Nếu bạn đang sử dụng Java, Transformerfactory có thể được cấu hình để cằm biến đổi liên tiếp và tránh các hoạt động phân tích cú pháp không cần thiết. http://stackoverflow.com/questions/1312406/efficient-xslt-pipeline-in-java-or-redirecting-results-to-sources/1319774#1319774 –