2012-01-24 29 views
6

Tôi muốn thực hiện một điều kiện bao gồm trong XSLT, nhưng xsl: include là một yếu tố cấp cao nhất. Bạn chỉ có thể sử dụng xsl: if hoặc xsl: chọn bên trong mẫu. Có bất kỳ loại hack hoặc làm việc xung quanh cho phép một bao gồm có điều kiện của một tập tin bên ngoài? Tôi đã cố gắng sử dụng hàm document(), nhưng nó không tải được tệp bên ngoài của tôi (có lẽ vì nó không phù hợp với một số quy tắc mà sẽ làm cho nó "hợp lệ").XSLT có điều kiện bao gồm các tập tin bên ngoài

Tệp xml bên ngoài của tôi là một loạt các đoạn mã xslt. tùy thuộc vào giá trị của một biến trong tệp XSLT chính, mã corisponding từ tệp bên ngoài phải được "sao chép/dán" tại chỗ (như điều kiện bao gồm trong C hoặc PHP).

Dòng chảy của tập tin XSLT chính của tôi nên tiến hành theo cách sau đây:

$configurationMode 
if ($configurationMode = Standard) { xsl:include="standard.xml" } else { xsl:include="alt.xml" } 

Rõ ràng là tôi không thể làm điều đó một cách đơn giản như trên, do vậy tại sao tôi yêu cầu nếu có một hack hay workaround.

Trả lời

3

Khi tôi hiểu mọi thứ, 'bao gồm' xảy ra khi trình phân tích cú pháp xml phân tích cú pháp và biên dịch biểu định kiểu. Điều này có nghĩa là không có sự đánh giá logic hoặc biểu thức nào có thể xảy ra trước khi bao gồm được xử lý và do đó không có cách nào để làm cho nó có điều kiện như vậy. Bạn cần phải thực hiện hành vi có điều kiện xảy ra bên ngoài bảng định kiểu.

Có xem xét này http://www.dpawson.co.uk/xsl/sect2/N4760.html#d6065e100

Đặc biệt không nhận xét này bởi Mike Kay giúp đỡ:

này đã được nêu ra một số lần. Trên một chủ đề trước, chúng tôi đã đến để kết luận rằng người dùng đang cố gắng viết một tờ định kiểu mục đích chung G và sau đó chuyên nó theo điều kiện bao gồm bản định kiểu mục đích đặc biệt A hoặc B. Cách đáp ứng yêu cầu này là có A và B bao gồm G, không phải là cách khác xung quanh, và sau đó bạn có điều kiện chọn A hoặc B làm biểu định kiểu chính khi bắt đầu phép chuyển đổi.

6

này không thể được thực hiện với XSLT 1.0 và có thể được thực hiện (đến một mức độ rất hạn chế) trong XSLT 2.0 bằng cách sử dụng thuộc tính use-when.

Có các cách không xslt để đạt được thay đổi động mong muốn của một chỉ thị xsl:include hoặc xsl:import.

Một phương pháp như vậy là tải biểu định kiểu XSLT dưới dạng XmlDocument và sử dụng các phương thức DOM có sẵn để truy cập và sửa đổi thuộc tính, để đặt thuộc tính href cho giá trị mong muốn. Sau đó, bắt đầu chuyển đổi từ bảng định kiểu XSLT có chứa XMLDocument đã sửa đổi trong bộ nhớ này.

3

Hãy thử đảo ngược cấu trúc: nếu bạn có hai mô đun mục đích đặc biệt là pink.xsl và blue.xsl và mô-đun có mục đích chung là baby.xsl, thì thay vì cố gắng nhập/bao gồm một trong các tệp pink.xsl hoặc màu xanh dương. xsl vào baby.xsl, thay vào đó sử dụng tệp pink.xsl hoặc blue.xsl làm biểu định kiểu mục nhập cấp cao nhất và có hai tệp nhập baby.xsl này. Đó là cách nó được thiết kế để được sử dụng, nó là một hack hoặc một workaround.Ngoài ra, với mô tả về kịch bản của bạn "Tệp xml bên ngoài của tôi là một loạt các đoạn mã xslt", cách tiếp cận tốt hơn trong trường hợp của bạn có thể là tập hợp biểu định kiểu từ các đoạn này thành một bước riêng biệt, sử dụng biến dạng XSLT thay vì sử dụng xsl: include/xsl: import.

0

Ngoài những gì đã được nói, một giải pháp có thể sẽ làm cho các tệp bổ sung trở nên đơn giản, cung cấp các tệp XML (thay vì tệp XSLT). Bằng cách đó, bạn có thể bao gồm chúng với hàm document() của XPath (sẽ được đánh giá tại thời gian chạy thay vì biên dịch).

Sau đó, bạn có thể thay đổi hành vi chuyển đổi của mình dựa trên nội dung của tài liệu XML được tải; tuy nhiên, bạn không thể cung cấp các đoạn XSLT thực thi trong các tài liệu được bao gồm.

Tùy thuộc vào trường hợp sử dụng của bạn cho dù đây là giải pháp - nếu các tài liệu bổ sung có tác động mạnh đến luồng điều khiển của chuyển đổi của bạn, bạn không muốn định nghĩa chúng bằng XML đơn giản -Thực hiện một cái gì đó như XSLT. Tuy nhiên, khi các tài liệu của bạn đóng vai trò như các tệp cấu hình, bạn có thể muốn suy nghĩ về việc cung cấp cho chúng một cách thuần túy XML.

Khi bạn gặp sự cố với document(), hãy sử dụng trình xác thực XML trên tệp của mình. Một lỗi ngụ ý rằng các tệp của bạn không phải là XML hợp lệ.

0
<xsl:variable name="CONDITIONAL" select="ELEMENT/CONDITION"/> 
<xsl:variable name="DOCUMENTNAME" select="document(concat($CONDITIONAL,'-DOCUMENT.xml'))/ELEMENT"/> 

Ví dụ này là cách tôi đã sử dụng có điều kiện tệp bên ngoài. Tôi đã có cờ trong XML cơ sở mà XSL sử dụng như một biến để giúp chỉ định tên của tệp khác để kéo vào khuôn mẫu. Khi biến đó được định nghĩa như trong trường hợp của tôi, tôi sử dụng nó để kéo dữ liệu XML khác vào đầu ra được tạo ra. Lệnh concat buộc dữ liệu lại với nhau để đặt tên tệp.

Vì vậy, khi tôi muốn thông tin từ tệp XML bên ngoài, tôi sử dụng '$ DOCUMENTNAME' để tham chiếu dữ liệu ngoài.

1

Không chắc chắn điều này có áp dụng cho trường hợp của bạn hay không, nhưng tôi sẽ giải thích điều này.

Tôi đã thực hiện những việc tương tự trong quá khứ, nhưng thay vì thực hiện điều kiện, tôi gọi một mẫu trong một trong hai tệp dựa trên những gì xsl: khi đánh giá. Nếu bạn không muốn sử dụng các mẫu trong trường hợp của mình, hãy bỏ qua câu trả lời này.

Ví dụ, nói rằng "cha mẹ" tập tin XSLT được gọi root.xslt, và hai người có điều kiện được sử dụng là child1.xsltchild2.xslt. Giả sử tôi muốn chạy logic có điều kiện so với giá trị của một nút được gọi là trạng thái . Nếu giá trị là "CURRENT", tôi muốn gọi mẫu có tên là isCurrent trong child1.xslt, nếu không hãy gọi mẫu có tên isNotCurrent trong child2.xslt. Vì lợi ích của ngắn gọn, trong mỗi trường hợp tôi chỉ đơn giản là đi qua các mẫu nút gốc và tất cả trẻ em.

Nó muốn tìm một cái gì đó như thế này:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"> 
    <xsl:import href="child1.xslt"/> 
    <xsl:import href="child2.xslt"/> 

    <xsl:template match="/"> 
     <xsl:choose> 
     <xsl:when test="rootNode/status = 'CURRENT'"> 
      <!-- template isCurrent defined in child1.xslt --> 
      <xsl:apply-templates select="rootNode" mode="isCurrent" /> 
     </xsl:when> 
     <xsl:otherwise> 
      <!-- template isNotCurrent defined in child2.xslt --> 
      <xsl:apply-templates select="rootNode" mode="isNotCurrent" /> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet> 

Hy vọng điều này ít nhất giúp một chút.

0

Với việc bổ sung static parameters, điều này hiện có thể thực hiện được trong XSLT 3.0.Các thông số tĩnh có thể được sử dụng trong thuộc tính use-when của xsl:include.

Bây giờ chúng ta có thể khai báo các thông số với giá trị mặc định của false() và sau đó ghi đè lên những cái chúng ta cần ít thời gian chạy ...

<xsl:param name="someparam" as="xs:boolean" select="false()" 
    static="yes" required="no"/> 
<xsl:include href="include_me.xsl" use-when="$someparam"/> 

Dưới đây là một ví dụ làm việc toàn thử nghiệm với Saxon-HE 9.7 (cũng đã thử nghiệm với Saxon-PE 9.5).

XML Input (test.xml)

<doc> 
    <foo/> 
</doc> 

chính XSLT 3.0 (test_main.xsl)

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs"> 
    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:param name="inc1" as="xs:boolean" select="false()" 
    static="yes" required="no"/> 
    <xsl:param name="inc2" as="xs:boolean" select="false()" 
    static="yes" required="no"/> 

    <xsl:include href="test_inc1.xsl" use-when="$inc1"/> 
    <xsl:include href="test_inc2.xsl" use-when="$inc2"/> 

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

</xsl:stylesheet> 

Đầu tiên có thể bao gồm XSLT 3.0 (test_inc1.xsl)

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:template match="foo"> 
    <xsl:copy>INCLUDE FILE 1!!!</xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

Thứ hai có thể bao gồm XSLT 3.0 (test_inc2.xsl)

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:template match="foo"> 
    <xsl:copy>INCLUDE FILE 2!!!</xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

dòng lệnh (thiết inc2 true)

java -cp "saxon9he.jar" net.sf.saxon.Transform -s:"test.xml" -xsl:"test_main.xsl" inc2="true" 

Output

<doc> 
    <foo>INCLUDE FILE 2!!!</foo> 
</doc> 
0

Có một cách tiếp cận mà tôi đã tìm thấy có điều kiện bao gồm các tệp sử dụng tính năng sử dụng khi trong XSLT 2.0.

Bạn phải tạo một hệ thống tài sản đó được truyền thông qua các ứng dụng trong thời gian chạy, như trong trường hợp của tôi, tôi đang sử dụng Java vì vậy tôi đã tạo ra "Debug" bất động sản sử dụng lệnh để chạy ứng dụng của tôi:

java -DDebug=yes myAppPath 

sau đó trong XSLT, sử dụng thuộc tính này để bao gồm các tệp có điều kiện. Ví dụ:

<xsl:include href="file1.xslt" use-when="system-property('DEBUG') = 'yes'"/> 
<xsl:include href="file2.xslt" use-when="system-property('DEBUG') != 'yes'"/> 

như thế.

Không biết nếu nó phù hợp với kịch bản được hỏi nhưng CÓ có cách để thực hiện điều đó trong XSLT 2.0. Trong XSLT 3.0, hỗ trợ cho biến cục bộ cũng được thêm vào. Vì vậy, điều này có thể dễ dàng thực hiện ở đó bằng cách sử dụng các biến cục bộ.

Cảm ơn, Chúc mừng Mã hóa

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