2010-08-08 34 views
7

Tôi muốn sử dụng một tập tin xmlLàm thế nào để có được đường dẫn hình ảnh cho <img src="?"> tag từ tập tin XML

<pics> 
<pic no="1">c:\pic1.jpg</pic> 
<pic no="2">c:\pic2.jpg</pic> 
<pic no="3">c:\pic3.jpg</pic> 
<pic no="4">c:\pic4.jpg</pic> 
<pic no="5">c:\pic5.jpg</pic> 
.... 
</pics> 

trong một bảng html:

<table cellspacing="2" cellpadding="2" border="0">    
    <tr> 
    <td><img src="" width="150" height="120" /></td> 
    <td><img src="" width="150" height="120" /></td> 
    <td><img src="" width="150" height="120" /></td> 

    </tr> 
    <tr> 
    <td><img src="from xml" width="150" height="120" /></td> 
    <td><img src="from xml" width="150" height="120" /></td> 
    <td><img src="from xml" width="150" height="120" /></td> 
    </tr> 
    <tr> 
    <td><img src="from xml" width="150" height="120" /></td> 
    <td><img src="from xml" width="150" height="120" /></td> 
    <td><img src="from xml" width="150" height="120" /></td> 
    </tr>      
</table> 

Whats cách tốt nhất để làm điều này?

+0

Câu hỏi hay (+1). Xem câu trả lời của tôi cho một giải pháp hoàn chỉnh có trong tinh thần của XSLT và để giải thích về tất cả những khoảnh khắc quan trọng trong giải pháp. :) –

Trả lời

3

XML:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<?xml-stylesheet type="text/xsl" href="web_page.xsl"?> 
<pics> 
    <pic> 
    <td> 
    <no src="http://farm1.static.flickr.com/160/387667598_ea86c93d81.jpg" width="150" height="120">1</no> 
    </td> 
    <td> 
    <no src="http://farm1.static.flickr.com/160/387667598_ea86c93d81.jpg" width="150" height="120">2</no> 
    </td> 
    <td> 
    <no src="http://farm1.static.flickr.com/160/387667598_ea86c93d81.jpg" width="150" height="120">3</no> 
    </td> 
    </pic> 
    <pic> 
    <td> 
    <no src="http://motherjones.com/files/legacy/mojoblog/funny-cats-a10.jpg" width="150" height="120">4</no> 
    </td> 
    <td> 
    <no src="http://motherjones.com/files/legacy/mojoblog/funny-cats-a10.jpg" width="150" height="120">5</no> 
    </td> 
    <td> 
    <no src="http://motherjones.com/files/legacy/mojoblog/funny-cats-a10.jpg" width="150" height="120">6</no> 
    </td> 
    </pic> 
</pics> 

XSLT:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:template match="/"> 
<html> 
<body> 
    <table> 
    <xsl:for-each select="pics/pic"> 
    <tr> 
     <xsl:for-each select="td"> 
     <td><img> 
      <xsl:attribute name="src"> 
      <xsl:value-of select="no//@src"/> 
      </xsl:attribute> 
      <xsl:attribute name="width"> 
      <xsl:value-of select="no//@width"/> 
      </xsl:attribute> 
      <xsl:attribute name="height"> 
      <xsl:value-of select="no//@height"/> 
      </xsl:attribute> 
     </img></td> 
     </xsl:for-each> 
    </tr> 
    </xsl:for-each> 
    </table> 
</body> 
</html> 
</xsl:template> 
</xsl:stylesheet> 

Hãy thử nó cho mình ở đây (sao chép và dán mã của tôi vào hộp thích hợp):

+0

Điều này không đối phó với phần khó nhất (sắp xếp các cột của bảng), là quá chi tiết ('' có cùng kết quả) và là lỗi vì bạn không thể có phần tử hình ảnh mà không có thuộc tính alt và không thể có phần tử hình ảnh làm phần tử con của phần tử nội dung. –

+1

@Jon: hãy để tôi giải quyết các nhận xét của bạn. ** 1. ** sắp xếp bảng html là tầm thường, tôi cho rằng anh ta có thể tìm ra phần đó, nhưng đối với bạn tôi đã cập nhật ví dụ của mình để làm chính xác những gì anh ấy đang cố gắng đạt được (tự kiểm tra) ** 2. ** Ví dụ là cách phức tạp hơn của tôi, đặc biệt là đối với một người nào đó bắt đầu với XSLT, tôi làm những gì nó cần phải làm và đơn giản ** 3. ** Tôi không thấy nó lỗi như thế nào, bạn có thể đặt 'img' ở bất cứ đâu, ví dụ của tôi ** hoạt động! ** Tôi bối rối là tại sao bạn lại bỏ phiếu cho nó. Chúc một ngày tốt lành. – JohnB

+1

Tôi đồng ý với JohnB - đơn giản luôn là giải pháp tốt hơn trong quan điểm của tôi, đặc biệt nếu bạn mới bắt đầu học một công nghệ mới - cố gắng nắm vững khái niệm là đủ khó mà không cần phải lội ngược dòng. đơn giản ngu ngốc " – Doug

1

Sử dụng XSL. Ví dụ here. Btw tại sao bạn có thuộc tính no ở đó?

+1

Tất nhiên, nó thậm chí được gắn thẻ là [xslt] ... – kennytm

2

Có một lỗi trong đầu ra đề nghị, như <img/> yếu tố phải có alt thuộc tính trong mỗi phiên bản của HTML, trong đó họ có mặt.

Dù sao sau đây thực hiện điều này nhưng không có các thuộc tính có thể được thực hiện từ CSS thay thế (chỉ để giữ kích thước xuống). Thêm chúng trở lại trong nếu muốn là tầm thường:

<xsl:template match="pics"> 
    <table> 
     <xsl:apply-templates select="pic[position() mod 3 = 1]"/> 
    </table> 
</xsl:template> 
<xsl:template match="pic[position() mod 3 = 1]"> 
    <tr> 
     <td> 
      <xsl:if test="2 &gt; count(following-sibling::pic)"> 
       <xsl:attribute name="colspan"> 
        <xsl:value-of select="3 - count(following-sibling::pic)"/> 
       </xsl:attribute> 
      </xsl:if> 
      <img src="{.}" alt="" /> 
     </td> 
     <xsl:apply-templates select="following-sibling::pic[3 &gt; position()]" /> 
    </tr> 
</xsl:template> 
<xsl:template match="pic"> 
    <td><img src="{.}" alt=""/></td> 
</xsl:template> 

Trên đây giả sử bạn muốn con đường từ các tập tin sử dụng trực tiếp, thêm mã để biến nó một cách nào đó (nói chỉ mất phần cuối cùng của con đường sử dụng substring-after()) không phải là một phần mở rộng khó khăn, giả sử rằng sự biến đổi không phức tạp.

Chỉnh sửa:

Bản thân tôi và JohnB sẽ đi sâu vào lãnh thổ ở đây, ở trên đủ để trả lời câu hỏi gốc.

Đã thêm để trả lời đầy đủ hơn cho câu hỏi của JohnB. Sau đây là mã tương đương sử dụng cho mỗi thay vì áp dụng các mẫu. Về mặt lý thuyết, việc xử lý cơ sở của một bộ xử lý XSLT tuần tự và xử lý phải giống nhau, mặc dù bạn có thể thấy sự khác biệt trong thực tế (nếu bạn nói với tôi rằng chúng khác với một bộ xử lý đã cho) nhanh hơn một chút với việc xử lý tuần tự và hơi chậm hơn với xử lý trạng thái máy, nhưng tôi chỉ đặt cược một lượng rất nhỏ).

Lưu ý rằng chúng tôi không thể sử dụng lại mẫu mặc định cho pic. Mặt khác, nếu chúng ta có một mẫu mặc định khác cho pic ở nơi khác (nếu đây là một phần của một bản định kiểu phức tạp hơn), chúng ta không cần phải phân biệt giữa chúng, đó là thời gian chính mà cá nhân tôi sẽ nghiêng về phía mỗi người.

<xsl:template match="pics"> 
    <table> 
    <xsl:for-each select="pic[position() mod 3 = 1]"> 
      <tr> 
       <td> 
        <xsl:if test="2 &gt; count(following-sibling::pic)"> 
         <xsl:attribute name="colspan"> 
          <xsl:value-of select="3 - count(following-sibling::pic)"/> 
        </xsl:attribute> 
        </xsl:if> 
        <img src="{.}" alt="" /> 
       </td> 
       <xsl:for-each select="following-sibling::pic[3 &gt; position()]"> 
        <td><img src="{.}" alt=""/></td> 
       </xsl:for-each> 
      </tr> 
     </xsl:for-each> 
    </table> 
</xsl:template> 
+0

+1 cách rất thông minh để tạo các cột! Tôi chưa bao giờ làm bất cứ điều gì lạ mắt với XSLT. Nhưng bạn không cần một vòng quanh ''? – JohnB

+0

Chúng ta không cần vòng lặp, bởi vì các mẫu áp dụng trong bảng sẽ lấy mọi pic thứ ba theo thứ tự và sau đó mẫu thích hợp được chạy trên nó, mà lần lượt đề cập đến hai mẫu tiếp theo. Hoặc để xem xét nó theo cách khác, áp dụng mẫu là một vòng lặp, mặc dù đôi khi một vòng lặp trên chỉ một mục. Có rất ít (nếu có) bạn có thể thực hiện với mỗi cái mà bạn không thể làm với các mẫu áp dụng và ngược lại. Sự khác biệt là bình thường về mà dường như tự nhiên hơn vào thời điểm đó, mà phụ thuộc vào phong cách coder đến một mức độ nào đó. Tôi dựa vào áp dụng các mẫu như được cho là khai báo nhiều hơn, và có lợi hơn để tái sử dụng –

+0

@JohnB Tôi đã thêm một thực hiện cho mỗi và giải thích về sự khác biệt để trả lời đầy đủ hơn câu hỏi đó. –

0

Dưới đây là một giải pháp điển hình mà tuân thủ tinh thần của XSLT (không <xsl:for-each>), càng ngắn càng tốt, và tham số về số lượng mong muốn của các cột trong bảng.

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 

    <xsl:param name="pNumCols" select="3"/> 

<xsl:template match="pics"> 
    <table cellspacing="2" cellpadding="2" border="0"> 
    <xsl:apply-templates select="pic[position() mod $pNumCols = 1]"/> 
    </table> 
</xsl:template> 

<xsl:template match="pic"> 
    <tr> 
    <xsl:apply-templates mode="process" select= 
    "(. | following-sibling::pic)[not(position() > $pNumCols)]"/> 
    </tr> 
</xsl:template> 

<xsl:template match="pic" mode="process"> 
    <td><img src="{.}" width="150" height="120" /></td> 
</xsl:template> 
</xsl:stylesheet> 

Khi chuyển đổi này được áp dụng trên các tài liệu XML sau (dựa trên tài liệu XML được cung cấp, nhưng với nhiều hình ảnh có thực sự đầy màu sắc và thú vị):

<pics> 
<pic no="1">http://col.stb.s-msn.com/i/D7/6A19748C9AA58B938F42099543D2E.jpg</pic> 
<pic no="2">http://col.stb.s-msn.com/i/1F/35A8478AC24EEF95933B5F0E4E394.jpg</pic> 
<pic no="3">http://col.stb.s-msn.com/i/76/3ADA01320CEC8B31D53FACC0C11E.jpg</pic> 
<pic no="4">http://col.stb.s-msn.com/i/92/51BF117987A3279571F06BEB4AE39D.jpg</pic> 
<pic no="5">http://col.stb.s-msn.com/i/9B/9A6E876BA2F7EAE82392C7E7F6C1C.jpg</pic> 
<pic no="6">http://col.stb.s-msn.com/i/50/8CC964E5503A7F61F8AD22A12024.jpg</pic> 
<pic no="7">http://col.stb.s-msn.com/i/C4/F7EF634B7084DA69AAB5AAD05C8922.jpg</pic> 
<pic no="8">http://col.stb.s-msn.com/i/FB/C8367425D67FA391A5E0F8A3E0276B.jpg</pic> 
</pics> 

kết quả mong muốn được sản xuất (xem trong trình duyệt :)):

<table cellspacing="2" cellpadding="2" border="0"> 
    <tr> 
     <td> 
     <img src="http://col.stb.s-msn.com/i/D7/6A19748C9AA58B938F42099543D2E.jpg" width="150" height="120"/> 
     </td> 
     <td> 
     <img src="http://col.stb.s-msn.com/i/1F/35A8478AC24EEF95933B5F0E4E394.jpg" width="150" height="120"/> 
     </td> 
     <td> 
     <img src="http://col.stb.s-msn.com/i/76/3ADA01320CEC8B31D53FACC0C11E.jpg" width="150" height="120"/> 
     </td> 
    </tr> 
    <tr> 
     <td> 
     <img src="http://col.stb.s-msn.com/i/92/51BF117987A3279571F06BEB4AE39D.jpg" width="150" height="120"/> 
     </td> 
     <td> 
     <img src="http://col.stb.s-msn.com/i/9B/9A6E876BA2F7EAE82392C7E7F6C1C.jpg" width="150" height="120"/> 
     </td> 
     <td> 
     <img src="http://col.stb.s-msn.com/i/50/8CC964E5503A7F61F8AD22A12024.jpg" width="150" height="120"/> 
     </td> 
    </tr> 
    <tr> 
     <td> 
     <img src="http://col.stb.s-msn.com/i/C4/F7EF634B7084DA69AAB5AAD05C8922.jpg" width="150" height="120"/> 
     </td> 
     <td> 
     <img src="http://col.stb.s-msn.com/i/FB/C8367425D67FA391A5E0F8A3E0276B.jpg" width="150" height="120"/> 
     </td> 
    </tr> 
</table> 

Do lưu ý:

  1. Việc sử dụng các nhà điều hành XPath mod để xác định các mục của mỗi hàng.

  2. Sử dụng các chế độ để xử lý cùng một loại phần tử (<pic>) theo hai cách khác nhau.

  3. Sử dụng AVT (thuộc tính-giá trị-mẫu) để làm cho mã ngắn hơn và dễ hiểu hơn.

+0

Có vẻ như rất thanh lịch ... nhưng tôi ít hơn người mới bắt đầu - tôi chưa bao giờ thực sự có thời gian để hiểu được phép thuật của xslt. Tôi đã cố gắng sao chép và dán mã của bạn thay đổi các url của bức ảnh và thậm chí thêm ... Tôi bị lạc ... nhưng vẫn cảm ơn bạn :) – Asaf

+0

+1 cho câu trả lời duy nhất không thay đổi đầu vào hoặc sử dụng một mẫu gạch. @Asaf: Tất nhiên đây là một giải pháp thanh lịch, nhưng không có "ma thuật" liên quan. Ngoài ra, ưu tiên cho các lệnh 'xsl: for-each' trên' xsl: apply-templates' không phải là đặc quyền của người mới bắt đầu XSLT, đó là vì có một số sai lầm về mô hình khai báo. –

+0

@Alejandro: Cảm ơn, ý kiến ​​của bạn được đánh giá cao nhất. @Asaf: bạn có nguy cơ vẫn là người mới bắt đầu cho một thời gian looooong nếu bạn không cố gắng để tìm hiểu. –

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