2009-11-18 1 views
0

Я начинаю использовать lxml в Python для обработки XML/XSL-документов, и в целом это кажется очень прямым. Тем не менее, я не могу найти способ передать XML-фрагмент в качестве параметра таблицы стилей при выполнении перевода.Пропустить XML-фрагменты как параметры таблицы стилей с lxml?

Например, в PHP можно передать DOMDocument фрагментов XML как параметры таблиц стилей, так что один может иметь сложный Params, доступный в таблице стилей:

$xml = new DOMDocument(); 
$xml->loadXML('<root><node/></root>'); 

$xsl = new DOMDocument(); 
$xsl->loadXML('<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:output method="html" omit-xml-declaration="yes" 
    indent="yes" media-type="text/html" /> 
<xsl:param name="a" /> 

<xsl:template match="/"> 
<html> 
    <body> 
    <xsl:value-of select="$a/foo/bar/text()" /> 
    </body> 
</html> 
</xsl:template> 

</xsl:stylesheet>'); 

$fragment = new DOMDocument(); 
$fragment->loadXML('<foo><bar>baz</bar></foo>'); 

$proc = new XSLTProcessor; 
$proc->registerPHPFunctions(); 
$proc->importStyleSheet($xsl); 

$param_ns = ''; 
$param_name = 'a'; 
$proc->setParameter($param_ns, $param_name, $fragment->documentElement); 

Который приведет:

<html> 
    <body> 
    baz 
    </body> 
</html> 

Как это сделать, используя lxml?

ответ

1

Насколько я знаю, вы можете использовать выражения xpath (или результат метода etree.XSLT.strparam() для строк с кавычками) в lxml (на данный момент в любом случае).

Однако, поскольку вы можете использовать выражения xpath, это означает, что вы можете «работать» с помощью custom xpath extension function, который возвращает рассматриваемый элемент. Другим способом может быть использование стандартной функции xpath document() и использование custom resolver

+0

Спасибо. Не могли бы вы отредактировать сообщение и изменить ссылку на страницу с помощью настраиваемого распознавателя? Я заметил пользовательские функции xpath после публикации и пришел к такому же выводу, но метод 'document()' может быть более полезным. –

+0

Этот ответ особенный, потому что с момента, когда @Steven было так мало очков, он не мог опубликовать несколько ссылок. Сейчас у него около 12 тысяч очков. Долгий путь. – mlissner

+0

@mlissner: спасибо, что напомнил мне ;-), я исправил ссылки. – Steven

0

Вы можете использовать функцию расширения python для возврата документа etree.XML в xslt. Вот минимальный пример. Он регистрирует глобальное пространство имен (uri: params), объединяет функцию с методом «params» в этом пространстве имен. Это используется таблицей стилей для достижения функции расширения. Не забывайте объявление xmlns: ptest в таблице стилей.

hmm, похоже, мне нужно будет помещать html-объекты в символ < в этом коде. Я также положил его в http://bkc.pastebin.com/f67461ccc


from lxml import etree 

stylesheet = etree.XML(""" 
    <xsl:stylesheet version="1.0" 
     xmlns:ptest="uri:params" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
     <xsl:variable name="params" select="ptest:params()" /> 
     <xsl:template match="/"> 
      <name_is><xsl:value-of select="$params/name" /></name_is> 
     </xsl:template> 
    </xsl:stylesheet> 
""") 

def params(context): 
    # this is the extension function, it returns 
    # a etree.XML document 
    return etree.XML(
     """<params> 
       <name>fred 
     </params>""" 
     ) 


def test(): 
    """test passing document to xslt via python extension function 

    >>> test() 
    <?xml version="1.0"?> 
    <name_is xmlns:ptest="uri:params">fred 
    <BLANKLINE> 
    """  
    ns = etree.FunctionNamespace('uri:params') # register global namespace 
    ns['params'] = params # define function in new global namespace 
    transform = etree.XSLT(stylesheet) 
    print str(transform(etree.XML("""<source />"""))) 

if __name__ == "__main__": 
    import doctest 
    doctest.testmod() 
Смежные вопросы