Sự khác biệt giữa 'mẫu cuộc gọi' và 'mẫu áp dụng' trong XSL là gì?


119

Tôi là người mới trong XSLT nên tôi hơi bối rối về hai thẻ,

<xsl:apply-templates name="nodes">

<xsl:call-template select="nodes"> 

Vì vậy, bạn có thể liệt kê ra sự khác biệt giữa chúng?

Câu trả lời:


167

<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 selectthuộ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: modeprioritythực tế là các mẫu có thể có cả a namevà 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 đó.


5
@Tomalak: Câu trả lời hay! Tuy nhiên, câu lệnh: "xsl: apply-Template is a loop" không đúng. Không có dấu hiệu nào trong bất kỳ thông số kỹ thuật W3C chính thức nào <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.
Dimitre Novatchev

8
@Dimitre: Ý tôi muốn nói: Từ quan điểm của người dùng cuối, <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.
Tomalak

@Tomalak: Mặc dù điều này có thể hữu ích cho các lập trình viên XSLT mới làm quen, nhưng tôi nghĩ rằng nó thường gây hiểu lầm cho họ vì họ nghĩ rằng họ có thể sử dụng lại thông tin trạng thái được tích lũy trong quá trình "thực thi vòng lặp".
Dimitre Novatchev

@Tomalak: Vì những thực tế này, tôi nghĩ rằng sẽ phù hợp để sửa đổi "xsl: apply-Template is a loop" với somethinkg như: "xsl: apply-Template giống như một vòng lặp"
Dimitre Novatchev

@Tomalak: Vòng lặp là sự lặp lại, một cái gì đó apply-templatescall-templatehướng dẫn không dành cho. Chúng là cơ chế đệ quy trong XSLT. Và như Dimitre đã trả lời, áp dụng mẫu là cơ chế đa hình hoặc cơ chế hướng dữ liệu.

15

Để 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 :

  1. xsl:apply-templatesphong phú và sâu sắc hơn nhiều so với xsl:call-templatesvà 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.

  2. Mã sẽ được áp dụng có thể được viết theo cách sau khi xsl:apply templates đượ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


8

xsl:apply-templatesthườ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-templatemặ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-templatesnế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-templatetô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.

Biên tập:

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'.


2

Chức năng thực sự tương tự (ngoài ngữ nghĩa gọi, nơi call-templateyêu cầu một namethuộ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.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.