2013-01-16 34 views
28

Tôi biết câu hỏi sau đây là một chút của người mới bắt đầu nhưng tôi cần sự giúp đỡ của bạn để hiểu một khái niệm cơ bản.XSLT xsl: chuỗi. Nó tốt cho cái gì..?

Tôi muốn nói đầu tiên rằng tôi là một lập trình viên XSLT trong 3 năm và có một số điều mới và khá cơ bản mà tôi đã học ở đây mà tôi chưa bao giờ biết (Trong công việc của tôi, ai cũng biết cách lập trình một mình, không có khóa học nào liên quan).

Câu hỏi của tôi là: Cách sử dụng xsl:sequence là gì?

Tôi đã sử dụng xsl:copy-of để sao chép nút là, xsl:apply-templates để sửa đổi các nút mà tôi đã chọn và value-of cho văn bản đơn giản.

Tôi chưa bao giờ có nhu cầu sử dụng xsl:sequence. Tôi sẽ đánh giá cao nếu ai đó có thể chỉ cho tôi một ví dụ về việc sử dụng xsl:sequence được ưu tiên hoặc không thể đạt được nếu không có những điều tôi đã nói ở trên.

Một điều nữa, tôi đã đọc về định nghĩa xsl:sequence tất nhiên, nhưng tôi không thể phỏng đoán nó hữu ích như thế nào.

Trả lời

6

Vâng để trả lại giá trị của một loại nhất định bạn sử dụng xsl:sequence làm xsl:value-of mặc dù tên của nó luôn tạo nút văn bản (kể từ XSLT 1.0). Vì vậy, trong một cơ quan chức năng bạn sử dụng

<xsl:sequence select="42"/> 

để trả lại một giá trị xs:integer, bạn sẽ sử dụng

<xsl:sequence select="'foo'"/> 

để trả lại một giá trị xs:string

<xsl:sequence select="xs:date('2013-01-16')"/> 

để trả lại một giá trị xs:date và Sớm. Tất nhiên bạn cũng có thể trả về các chuỗi với ví dụ: <xsl:sequence select="1, 2, 3"/>.

Bạn sẽ không muốn tạo nút văn bản hoặc thậm chí là nút phần tử trong các trường hợp này trong chế độ xem của tôi vì nó không hiệu quả. Vì vậy, đó là của tôi, với hệ thống kiểu lược đồ mới dựa trên XSLT và XPath 2.0 một cách là cần thiết để trả về hoặc truyền xung quanh các giá trị của các loại này và một cấu trúc mới là cần thiết.

[sửa] Michael Kay nói trong "tham chiếu của XSLT 2.0 và XPath 2.0" về xsl:sequence: "Hướng dẫn tìm kiếm vô tội được giới thiệu trong XSLT 2.0 này đã đạt đến hiệu quả về khả năng ngôn ngữ XSLT, vì nó có nghĩa là XSLT các lệnh và các hàm tạo trình tự (và do đó các hàm và các khuôn mẫu) có khả năng trả về bất kỳ giá trị nào được mô hình dữ liệu XPath cho phép mà không có nó, các lệnh XSLT chỉ có thể được sử dụng để tạo các nút mới trong cây kết quả, nhưng với nó, chúng cũng có thể trả về giá trị nguyên tử và tham chiếu đến các nút hiện có. ".

38

<xsl:sequence> trên giá trị nguyên tử (hoặc chuỗi giá trị nguyên tử) giống như <xsl:copy-of> cả hai chỉ trả về bản sao đầu vào của chúng. Sự khác biệt xuất hiện khi bạn xem xét các nút.

Nếu $ n là một nút phần tử duy nhất, ví dụ như theo định nghĩa của một cái gì đó giống như

<xsl:variable name="n" select="/html"/> 

Sau đó

<xsl:copy-of select="$n"/> 

Trả về một bản sao của nút, nó có tên và con cùng cấu trúc nhưng đó là một nút mới có nhận dạng mới (và không có cha mẹ).

<xsl:sequence select="$n"/> 

Trả về nút $ n, Nút được trả lại có cùng giá trị gốc là $ n và bằng với toán tử Xpath is.

Sự khác biệt gần như hoàn toàn đeo mặt nạ trong truyền thống (XSLT 1 phong cách) mẫu sử dụng như bạn không bao giờ được tiếp cận với các kết quả của một trong hai hoạt động là kết quả của các nhà xây dựng là ngầm sao chép vào cây đầu ra nên thực tế là xsl:sequence doesn 't làm một bản sao được đeo mặt nạ.

<xsl:template match="a"> 
    <x> 
    <xsl:sequence select="$n"/> 
    </x> 
</xsl:template> 

cũng giống như

<xsl:template match="a"> 
    <x> 
    <xsl:copy-of select="$n"/> 
    </x> 
</xsl:template> 

Cả hai tạo ra một nút phần tử mới và sao chép kết quả của các nội dung như con của nút mới x.

Tuy nhiên, sự khác biệt sẽ nhanh chóng được nhìn thấy nếu bạn sử dụng các chức năng.

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:f="data:,f"> 

    <xsl:variable name="s"> 
     <x>hello</x> 
    </xsl:variable> 

    <xsl:template name="main"> 
     :: 
     :: <xsl:value-of select="$s/x is f:s($s/x)"/> 
     :: <xsl:value-of select="$s/x is f:c($s/x)"/> 
     :: 
     :: <xsl:value-of select="count(f:s($s/x)/..)"/> 
     :: <xsl:value-of select="count(f:c($s/x)/..)"/> 
     :: 
    </xsl:template> 

    <xsl:function name="f:s"> 
     <xsl:param name="x"/> 
     <xsl:sequence select="$x"/> 
    </xsl:function> 

    <xsl:function name="f:c"> 
     <xsl:param name="x"/> 
     <xsl:copy-of select="$x"/> 
    </xsl:function> 

</xsl:stylesheet> 

Tạo

$ saxon9 -it main seq.xsl 
<?xml version="1.0" encoding="UTF-8"?> 
:: 
:: true 
:: false 
:: 
:: 1 
:: 0 
:: 

Đây là kết quả của xsl:sequencexsl:copy-of là hoàn toàn khác nhau.

21

Trường hợp sử dụng phổ biến nhất cho xsl: sequence là trả lại kết quả từ hàm xsl:.

<xsl:function name="f:get-customers"> 
    <xsl:sequence select="$input-doc//customer"/> 
</xsl:function> 

Nhưng nó cũng có thể có ích trong những bối cảnh khác, ví dụ

<xsl:variable name="x" as="element()*"> 
    <xsl:choose> 
    <xsl:when test="$something"> 
     <xsl:sequence select="//customer"/> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:sequence select="//supplier"/> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:variable> 

Điều quan trọng ở đây là nó trả về tham chiếu đến các nút gốc, nó không làm bản sao mới.

+0

trong ví dụ thứ hai, điều đó có nghĩa là xsl: trình tự tốt hơn cho hiệu suất không? Vậy thì, đâu là lợi thế của bản sao trên xsl: sequence? – user3813234

+3

Tôi nghi ngờ có rất ít trường hợp bạn thực sự cần xsl: copy-of. Trừ khi bạn sử dụng validation = strict hoặc copy-namespaces = no, có lẽ. Trong hầu hết trường hợp, việc sử dụng xsl: copy-of thay vì xsl: sequence sẽ vô hại nhưng chắc chắn có một số trường hợp nó có thể gây ra việc sao chép không cần thiết và tốn kém trừ khi trình tối ưu hóa đủ thông minh để ngăn chặn nó. Nhưng trong ví dụ trên, cả hai không tương đương: $ x/.. trả về không có gì nếu bạn tạo bản sao, nhưng trả về cha mẹ của các nút gốc nếu bạn chọn chúng bằng xsl: sequence. –

+0

aah Tôi hiểu rồi. Cảm ơn rất nhiều! – user3813234

0

Sử dụng khác là tạo thẻ chỉ khi thẻ có con. Một ví dụ là cần thiết:

<a> 
    <b>node b</b> 
    <c>node c</c> 
</a> 

Một nơi nào đó trong XSLT của bạn:

<xsl:variable name="foo"> 
    <xsl:if select="b"><d>Got a "b" node</d></xsl:if> 
    <xsl:if select="c"><d>Got a "c" node</d></xsl:if> 
</xsl:variable> 
<xsl:if test="$foo/node()"> 
    <wrapper><xsl:sequence select="$foo"/></wrapper> 
</xsl:if> 

Bạn có thể thấy bản demo ở đây: http://xsltransform.net/eiZQaFz

Đó là cách tốt hơn so với thử nghiệm mỗi thẻ như thế này:

<xsl:if test="a|b">...</xsl:if> 

Bởi vì bạn sẽ kết thúc chỉnh sửa nó ở hai nơi.Ngoài ra tốc độ xử lý sẽ phụ thuộc vào thẻ nào trong imput của bạn. Nếu đó là bài kiểm tra cuối cùng từ bài kiểm tra của bạn, động cơ sẽ kiểm tra sự hiện diện của mọi người trước đây. Vì $ foo/node() là một thành ngữ cho "là có một phần tử con?", Động cơ có thể tối ưu hóa nó. Làm như vậy, bạn làm dịu cuộc sống của mọi người.

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