2009-07-13 59 views
9

Trong CMS của tôi, bạn có thể tạo một bài viết mới và chọn một hình ảnh sẽ được hiển thị trên bài viết đó. Khi một hình ảnh được chọn, hình thu nhỏ của hình ảnh cũng sẽ tự động được tạo.Xóa các ký tự cuối cùng trong chuỗi XSLT

Nếu hình ảnh được tải lên được gọi là image.jpg, sau đó hình thu nhỏ tương ứng sẽ tự động được đặt tên image_thumbnail.jpg.

Tôi muốn sử dụng hình ảnh thu nhỏ, ở mọi nơi trên trang web nơi bài viết được đề cập, ngoại trừ chính bài viết (nơi hình ảnh lớn gốc sẽ được hiển thị).

Nhưng làm cách nào tôi có thể làm điều đó?

Tôi tưởng tượng nếu tôi có thể có được tên gốc của hình ảnh, và sau đó chia nó lên trước hậu tố (.jpg, .png, .jpeg vv) và hardcode _thumbnail sau tên, thì đó sẽ là đủ.

Nói cách khác, tôi muốn lấy tên tệp hoàn chỉnh và cắt thành hai phần, để tôi có thể chèn chuỗi _thumbnail giữa hai phần.

Có thể điều đó sẽ hiệu quả, nhưng nếu hình ảnh được gọi là image.2horses.jpg (tệp có nhiều hơn một dấu chấm trong tên tệp) được tải lên? Một cắt ngây thơ trước khi '.' sẽ không hoạt động ở đây.

Có cách nào để giải quyết vấn đề này không? Có lẽ bằng cách cắt tên tệp trước 4 ký tự cuối cùng (.jpg, .png) hoặc 5 (.jpeg)?

Trả lời

9

Với tên tập tin của hình ảnh trong $ filename,

Nếu bạn có thể giả định rằng tất cả các hình ảnh sẽ kết thúc bằng ".jpg" và sẽ không có ".jpg" ở nơi khác trong tên tệp, sau đó điều này sẽ hoạt động:

<img src="{substring-before($filename, '.jpg')}_thumbnail.jpg" ... /> 

Nếu bạn không biết loại hình ảnh (như bạn muốn xử lý gif và png), hoặc nếu bạn cho rằng tiện ích có thể xảy ra nhiều lần tên tệp ("ima ge.jpg.jpg "), sau đó bạn sẽ muốn có một mẫu để giúp bạn:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/"> 
     <p> 
      <xsl:call-template name="image_thumbnail"> 
      <xsl:with-param name="filename" select="'image.jpg'"/> 
      </xsl:call-template> 
     </p> 

     <p> 
      <xsl:call-template name="image_thumbnail"> 
      <xsl:with-param name="filename" select="'image.09.07.11.jpg'"/> 
      </xsl:call-template> 
     </p> 

     <p> 
      <xsl:call-template name="image_thumbnail"> 
      <xsl:with-param name="filename" select="'image.gif'"/> 
      </xsl:call-template> 
     </p> 

     <p> 
      <xsl:call-template name="image_thumbnail"> 
      <xsl:with-param name="filename" select="'image with spaces.jpg'"/> 
      </xsl:call-template> 
     </p> 

     <p> 
      <xsl:call-template name="image_thumbnail"> 
      <xsl:with-param name="filename" select="'image with irregular spaces.jpg'"/> 
      </xsl:call-template> 
     </p> 

     <p> 
      <xsl:call-template name="image_thumbnail"> 
      <xsl:with-param name="filename" select="'image.jpg.again.jpg'"/> 
      </xsl:call-template> 
     </p> 

    </xsl:template> 

    <xsl:template name="image_thumbnail"> 
    <xsl:param name="filename"/> 
     <xsl:choose> 
     <xsl:when test="contains($filename, '.')"> 
      <xsl:variable name="before" select="substring-before($filename, '.')"/> 
      <xsl:variable name="after" select="substring-after($filename, '.')"/> 
      <xsl:choose> 
      <xsl:when test="contains($after, '.')"> 
       <xsl:variable name="recursive"> 
        <xsl:call-template name="image_thumbnail"> 
        <xsl:with-param name="filename" select="$after"/> 
        </xsl:call-template> 
       </xsl:variable> 
       <xsl:value-of select="concat($before, '.', $recursive)"/> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="concat($before, '_thumbnail.', $after)"/> 
      </xsl:otherwise> 
      </xsl:choose> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:value-of select="$filename"/> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 

</xsl:stylesheet> 
+0

Giải pháp của bạn gần như bằng với tôi, tôi có thể trả lại +1 một cách dễ dàng. ;-) – Tomalak

+0

Xin lỗi, -1 từ tôi, giả định như thế này dẫn đến mã lỗi. Tôi làm việc với các công cụ thực hiện nhiều chuyển đổi và họ chỉ thêm tiện ích mở rộng mới vào cuối, vì vậy tôi có thể dễ dàng trải nghiệm một cái gì đó gọi là image.jpg.tif.jpg –

1

Hãy xem XPath functions overview at W3Schools, cụ thể là phương pháp substring-before.

+0

Điều gì xảy ra nếu có tên tệp có nhiều hơn một dấu chấm đó. Ví dụ. Image.09.07.11.jpg và tôi đã tạo chuỗi con trước ('Image.09.07.11.jpg', '.')? Tôi sẽ không nhận được "Hình ảnh" và không có gì khác? –

+0

Bạn có thể nhận được dấu chấm cuối cùng trong chuỗi bằng đệ quy hoặc vòng lặp. Xem http://www.biglist.com/lists/xsl-list/archives/200102/msg00838.html – Scoregraphic

2

Giải pháp chung chỉ liên quan đến XSLT chuẩn là hơi khó vì bạn phải tìm chuỗi từ cuối. Bạn có thể chia nhỏ tên tệp của mình bằng cách sử dụng hai hàm, chuỗi con trước và cuối chuỗi con sau cùng. Thật không may, các chức năng này không phải là một phần của XSLT. Bạn có thể Google và cố gắng tìm kiếm implementations.Giả sử bạn có hai chức năng này thực hiện như mẫu XSLT sau đó bạn có thể sử dụng mẫu sau đây để tạo ra tên thumbnail:

<xsl:template name="thumbnail-name"> 
    <xsl:param name="file-name"/> 
    <xsl:call-template name="substring-before-last"> 
    <xsl:with-param name="text" select="$file-name"/> 
    <xsl:with-param name="chars" select="'.'"/> 
    </xsl:call-template> 
    <xsl:text>_thumbnail.</xsl:text> 
    <xsl:call-template name="substring-after-last"> 
    <xsl:with-param name="text" select="$file-name"/> 
    <xsl:with-param name="chars" select="'.'"/> 
    </xsl:call-template> 
</xsl:template> 

Bạn có thể sử dụng mẫu như thế này (giả sử biến $ file-name chứa tên của hình ảnh):

<img> 
    <xsl:attribute name="src"> 
    <xsl:call-template name="thumbnail-name"> 
     <xsl:with-param name="file-name" select="$file-name"/> 
    </xsl:call-template> 
    </xsl:attribute> 
</img> 
19

Off đỉnh đầu của tôi:

<xsl:template name="substring-before-last"> 
    <xsl:param name="string1" select="''" /> 
    <xsl:param name="string2" select="''" /> 

    <xsl:if test="$string1 != '' and $string2 != ''"> 
    <xsl:variable name="head" select="substring-before($string1, $string2)" /> 
    <xsl:variable name="tail" select="substring-after($string1, $string2)" /> 
    <xsl:value-of select="$head" /> 
    <xsl:if test="contains($tail, $string2)"> 
     <xsl:value-of select="$string2" /> 
     <xsl:call-template name="substring-before-last"> 
     <xsl:with-param name="string1" select="$tail" /> 
     <xsl:with-param name="string2" select="$string2" /> 
     </xsl:call-template> 
    </xsl:if> 
    </xsl:if> 
</xsl:template> 

gọi như:

<xsl:template match="/"> 

    <xsl:variable name="filename" select="'image.2horses.jpg'" /> 

    <xsl:variable name="basename"> 
    <xsl:call-template name="substring-before-last"> 
     <xsl:with-param name="string1" select="$filename" /> 
     <xsl:with-param name="string2" select="'.'" /> 
    </xsl:call-template> 
    </xsl:variable> 

    <xsl:value-of select="$basename" /> 

</xsl:template> 

Sản lượng:

image.2horses 
+0

Mã của bạn cũng hoạt động tốt như Tomalak, nhưng tôi phải đánh dấu câu trả lời của Chris Nielsen là câu trả lời đúng, vì nó đã giải quyết được vấn đề với đầy đủ nhất. Nếu tôi có thể, tôi sẽ đánh dấu của bạn là chính xác quá :) –

+0

+1; Tôi thích giải pháp tổng quát của bạn tốt hơn so với tôi. –

0

XSLT giải pháp 2 sử dụng regexp:

replace($filename, '(\.[^\.]*)$', concat('_thumbnail', '$1')) 

Original câu trả lời (cũng XSLT 2): này loại bỏ tất cả sau dấu phân cách cuối cùng (bao gồm dấu tách). Vì vậy, bên dưới $ separatorRegexp có thể là '\ .jpg' hoặc chỉ '\.' và $ separator '.jpg' hoặc '.' trong trường hợp khác.

string-join(reverse(remove(reverse(tokenize($filename, $separatorRegexp)),1)),$separator) 

Cuối cùng, '_thumbnail.jpg' có thể được nối với concat.

+0

Khi tôi thử điều này với 'image.2horses.jpg' (từ câu hỏi) Tôi nhận được 'image.2horses'. (Có lẽ vì chỉ có một mục trong chuỗi nên không có gì để nối chuỗi.) Một cách tiếp cận XPath 2.0 khác sẽ là 'thay thế ($ filename, $ separatorRegexp, concat ($ separator, '$ 1'))' trong đó $ separatorRegexp = '(\. [^ \.] *) $' và $ separator = '_thumbnail'. Điều này sẽ cung cấp cho bạn 'image.2horses_thumbnail.jpg' làm đầu ra. –

+0

Đây là thay thế không có biến: 'replace ($ filename, '(\. [^ \.] *) $', Concat ('_ thumbnail', '$ 1'))' –

+0

Daniel Haley: Đó là những gì tôi dự định. Việc thêm _thumbnail.jpg đã trở nên tầm thường. Và như giải pháp của tôi liên quan đến một regexp anyway, vì vậy bạn có vẻ tốt hơn. –

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