Câu trả lời:
<xsl:call-template>
gần tương đương với việc gọi một hàm trong ngôn ngữ lập trình truyền thống.
Bạn có thể xác định các hàm trong XSLT, như hàm đơn giản này xuất ra một chuỗi.
<xsl:template name="dosomething">
<xsl:text>A function that does something</xsl:text>
</xsl:template>
Chức năng này có thể được gọi thông qua <xsl:call-template name="dosomething">
.
<xsl:apply-templates>
hơi khác một chút và trong đó là sức mạnh thực sự của XSLT: Nó lấy bất kỳ số lượng nút XML nào (bất kỳ thứ gì bạn xác định trong select
thuộc tính), lặp lại chúng ( điều này quan trọng: các mẫu áp dụng hoạt động giống như một vòng lặp! ) và tìm thấy các mẫu phù hợp cho họ:
<!-- sample XML snippet -->
<xml>
<foo /><bar /><baz />
</xml>
<!-- sample XSLT snippet -->
<xsl:template match="xml">
<xsl:apply-templates select="*" /> <!-- three nodes selected here -->
</xsl:template>
<xsl:template match="foo"> <!-- will be called once -->
<xsl:text>foo element encountered</xsl:text>
</xsl:template>
<xsl:template match="*"> <!-- will be called twice -->
<xsl:text>other element countered</xsl:text>
</xsl:template>
Bằng cách này, bạn từ bỏ một chút quyền kiểm soát đối với bộ xử lý XSLT - không phải bạn quyết định luồng chương trình đi đâu, nhưng bộ xử lý sẽ thực hiện bằng cách tìm kết quả phù hợp nhất cho nút mà nó hiện đang xử lý.
Nếu nhiều mẫu có thể khớp với một nút, thì nút có biểu thức đối sánh cụ thể hơn sẽ thắng. Nếu tồn tại nhiều hơn một mẫu phù hợp có cùng tính đặc hiệu, mẫu được tuyên bố cuối cùng sẽ thắng.
Bạn có thể tập trung nhiều hơn vào việc phát triển các mẫu và cần ít thời gian hơn để làm "hệ thống ống nước". Các chương trình của bạn sẽ trở nên mạnh mẽ hơn và được mô-đun hóa, ít lồng ghép sâu hơn và nhanh hơn (vì bộ xử lý XSLT được tối ưu hóa để đối sánh mẫu).
Một khái niệm cần hiểu với XSLT là "nút hiện tại". Với <xsl:apply-templates>
nút hiện tại sẽ tiếp tục với mỗi lần lặp, trong khi <xsl:call-template>
nút hiện tại không thay đổi. Tức là .
bên trong một khuôn mẫu được gọi đề cập đến cùng một nút như .
trong khuôn mẫu đang gọi. Đây không phải là trường hợp của các mẫu áp dụng.
Đây là sự khác biệt cơ bản. Có một số khía cạnh khác của khuôn mẫu ảnh hưởng đến hành vi của chúng: mode
Và priority
thực tế là các mẫu có thể có cả a name
và a match
. Nó cũng có tác động đến việc mẫu đã được nhập ( <xsl:import>
) hay chưa. Đây là những cách sử dụng nâng cao và bạn có thể xử lý chúng khi đến đó.
<xsl:apply-templates>
hoạt động giống như một vòng lặp. Sự khác biệt về triển khai trên đầu cuối của bộ xử lý XSLT sẽ không ảnh hưởng đến tôi với tư cách là một lập trình viên XSLT, kết quả là hoàn toàn giống nhau đối với việc triển khai song song và lặp đi lặp lại. Nhưng đối với một người mới sử dụng XSLT có nền tảng bắt buộc, nó sẽ giúp hình dung <xsl:apply-templates>
như một loại vòng lặp cho từng thứ, ngay cả khi - về mặt kỹ thuật - nó không phải vậy.
Để thêm vào câu trả lời hay của @Tomalak:
Dưới đây là một số khác biệt quan trọng và chưa được đề cập :
xsl:apply-templates
phong phú và sâu sắc hơn nhiều so với xsl:call-templates
và thậm chí là từ xsl:for-each
, đơn giản vì chúng ta không biết mã nào sẽ được áp dụng trên các nút của vùng chọn - trong trường hợp chung, mã này sẽ khác đối với các nút khác nhau của danh sách nút.
Mã sẽ được áp dụng có thể được viết theo cách sau khi xsl:apply template
s được viết và bởi những người không biết tác giả gốc.
Việc triển khai các hàm bậc cao (HOF) của thư viện FXSL trong XSLT sẽ không thể thực hiện được nếu XSLT không có <xsl:apply-templates>
hướng dẫn.
Tóm tắt : Các mẫu và <xsl:apply-templates>
hướng dẫn là cách XSLT triển khai và xử lý tính đa hình.
Tham khảo : Xem toàn bộ chủ đề này: http://www.biglist.com/lists/lists.mulberrytech.com/xsl-list/archives/200411/msg00546.html
xsl:apply-templates
thường (nhưng không nhất thiết) được sử dụng để xử lý tất cả hoặc một tập hợp con của nút con hiện tại với tất cả các mẫu có thể áp dụng. Điều này hỗ trợ tính đệ quy của ứng dụng XSLT phù hợp với tính đệ quy (có thể) của XML đã xử lý.
xsl:call-template
mặt khác giống như một cuộc gọi hàm thông thường. Bạn thực thi chính xác một mẫu (được đặt tên), thường với một hoặc nhiều tham số.
Vì vậy, tôi sử dụng xsl:apply-templates
nếu tôi muốn chặn quá trình xử lý của một nút thú vị và (thường là) đưa thứ gì đó vào luồng đầu ra. Một ví dụ điển hình (đơn giản hóa) sẽ là
<xsl:template match="foo">
<bar>
<xsl:apply-templates/>
</bar>
</xsl:template>
trong khi với xsl:call-template
tôi thường giải quyết các vấn đề như thêm văn bản của một số nút con lại với nhau, chuyển đổi các tập hợp nút được chọn thành văn bản hoặc các tập hợp nút khác và những thứ tương tự - bất cứ thứ gì bạn muốn viết một hàm chuyên biệt, có thể tái sử dụng.
Như một nhận xét bổ sung cho văn bản câu hỏi cụ thể của bạn:
<xsl:call-template name="nodes"/>
Điều này gọi một mẫu có tên là 'các nút':
<xsl:template name="nodes">...</xsl:template>
Đây là một ngữ nghĩa khác với:
<xsl:apply-templates select="nodes"/>
... áp dụng tất cả các mẫu cho tất cả các nút con của nút XML hiện tại của bạn có tên là 'các nút'.
Chức năng thực sự tương tự (ngoài ngữ nghĩa gọi, nơi call-template
yêu cầu một name
thuộc tính và một mẫu tên tương ứng).
Tuy nhiên, trình phân tích cú pháp sẽ không thực thi theo cùng một cách.
Từ MSDN :
Không giống như
<xsl:apply-templates>
,<xsl:call-template>
không thay đổi nút hiện tại hoặc danh sách nút hiện tại.
<xsl:apply-templates>
phải được triển khai dưới dạng vòng lặp - ngược lại, nó có thể được thực hiện song song, bởi vì các ứng dụng khác nhau trên các nút khác nhau của danh sách nút hoàn toàn độc lập với nhau.