2013-07-11 44 views
5

Giả sử tôi có một chức năng XPath Tôi đang gọi từ một XSL chuyển đổi sử dụng lxml (với libxmllibxslt), ví dụ:Làm thế nào tôi có thể trả về một đoạn văn bản từ một hàm XPath?

<xsl:template match="/"> 
    <xsl:variable name="result" select="myns:my-func(./*)" /> 
    ... 
</xsl:template> 

Từ chức năng này, tôi muốn trả lại một đoạn XML bao gồm các sau:

some sample <em>text</em> 

các python chức năng my_func được thiết lập một cách chính xác bằng lxml có sẵn thông qua XSL stylesheet, và sử dụng lxml.html.fragments_fromstring để có được những kết quả mà là ở định dạng:

012.

['some sample ', <Element em at 0x106c203b0>]

Làm thế nào tôi có thể trở lại danh sách này để nó có thể được sử dụng sau này trong XSL chuyển đổi từ biến như thể nó được thu thập từ một biểu thức XPath trực tiếp trong bối cảnh XSL? Dường như bất cứ khi nào tôi vượt qua một danh sách các chuỗi trở lại bộ vi xử lý XSL lxml ném một ngoại lệ.

+1

Câu hỏi của bạn là gì? Bạn có muốn biết làm thế nào bạn có thể truy cập một hàm Python từ XML? Hoặc bạn đã có Python liên kết với bộ xử lý XSLT của bạn và nó mang lại kết quả khác với những gì bạn cần? Kết quả là những gì, và làm thế nào để bạn mong đợi tehm? Bạn đang sử dụng bộ xử lý XSLT nào? – FrankPl

+0

@unpluggd Phần nào của câu trả lời của tôi không phù hợp với bạn?Nó sẽ giúp đỡ nếu tôi cung cấp một cái gì đó giống như một liên kết pastebin với một ví dụ làm việc đầy đủ? –

+0

@JamesHolderness Nếu bạn có thể cung cấp một ví dụ làm việc sẽ tuyệt vời! Cá nhân tôi đã thử cách tiếp cận của bạn và nó không hiệu quả đối với tôi, điều này đã khiến tôi thử tạo các đối tượng "chuỗi thông minh" và các giải pháp khác không hoạt động. Tôi đã trao cho bạn tiền thưởng dù sao, và sẽ chấp nhận câu trả lời của bạn với một ví dụ làm việc. Cảm ơn! –

Trả lời

3

Điều đầu tiên là xác định chức năng của bạn. Nó cần trả về bộ nút như một danh sách các mục. Các mục có thể bao gồm các phần tử (cũng là các chú thích và các chỉ dẫn xử lý), các chuỗi và các bộ dữ liệu.

Một ví dụ mã hóa cứng có thể trông như thế này:

from lxml import etree 

def myFunc(context, parm): 
    em = etree.Element('em') 
    em.text = 'text' 
    return ['some sample ', em] 

Lưu ý rằng parm tham số là không cần thiết trong trường hợp này, nhưng tôi đã đưa nó vào đây để phù hợp với mã ví dụ của bạn được đi qua một tham số trong cuộc gọi đến số myns: my-func.

Và nếu bạn muốn sử dụng fragments_fromstring để xây dựng bộ nút của bạn, thay vì xây dựng bộ nút theo cách thủ công, định nghĩa chức năng trở nên đơn giản hơn.

def myFunc(context, parm):   
    import lxml.html 
    return lxml.html.fragments_fromstring('some sample <em>text</em>') 

Tiếp theo bạn cần thiết lập không gian tên và đăng ký tên hàm.

myns = etree.FunctionNamespace('http://example.org/myNamespace') 
myns['my-func'] = myFunc 

Và cuối cùng bạn có thể sử dụng nó từ bên trong một kiểu XSLT như thế này:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:myns="http://example.org/myNamespace"> 
    <xsl:template match="/">         
    <xsl:variable name="result" select="myns:my-func(./*)" /> 
    <xsl:for-each select="$result"> 
     <xsl:copy-of select="." /> 
    </xsl:for-each>   
    </xsl:template> 
</xsl:stylesheet> 

Note URL namespace sử dụng trong stylesheet phải khớp với số đăng ký tại FunctionNamespace.

Bây giờ giả sử bạn đã nạp kiểu này thành một chuỗi gọi XSLT, một ví dụ chuyển đổi có thể trông như thế này:

root = etree.XML('<root></root>') 
doc = etree.ElementTree(root) 
transform = etree.XSLT(etree.XML(xslt)) 
res = transform(doc) 

Đối với một ví dụ làm việc đầy đủ, xem pastebin link này.

+0

Tôi đang sử dụng Python 2.7.3 và lxml 3.2.1, chạy mã pastebin và gặp lỗi: 'XSLTApplyError: Không thể đánh giá biểu thức của biến 'result'.' –

+0

@unpluggd Tôi vừa mới làm sạch cài đặt python 2.7.3 từ [here] (http://www.python.org/download/releases/2.7.3/) (Trình cài đặt MSI Windows x86) và lxml 3.2.1 từ [đây] (https://pypi.python.org/pypi/lxml/3.2.1) (trình cài đặt Windows 32bit - lxml-3.2.1.win32-py2.7.exe), và ví dụ của tôi vẫn hoạt động tốt cho tôi. Nó có thể là một vấn đề hệ điều hành? Bạn có trên Linux không? Dù bằng cách nào, nó có thể là giá trị cố gắng để cài đặt lại python và lxml. –

+0

@unpluggd Nó chỉ xảy ra với tôi nó cũng có thể là một vấn đề với phiên bản libxml hoặc libxslt mà bạn đang sử dụng nếu bạn đã cài đặt riêng rẽ. –

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