惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

J
Java Code Geeks
Jina AI
Jina AI
小众软件
小众软件
WordPress大学
WordPress大学
Last Week in AI
Last Week in AI
美团技术团队
V
V2EX
酷 壳 – CoolShell
酷 壳 – CoolShell
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 聂微东
博客园 - 【当耐特】
人人都是产品经理
人人都是产品经理
雷峰网
雷峰网
博客园 - 司徒正美
量子位
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
宝玉的分享
宝玉的分享
月光博客
月光博客
IT之家
IT之家
博客园 - 三生石上(FineUI控件)
大猫的无限游戏
大猫的无限游戏
T
Tailwind CSS Blog
博客园 - Franky

Secret Weblog

Becoming More Xee: A Modern XPath and XSLT Engine in Rust Looking for new challenges! Repeat Yourself, A Bit The Curious Case of Quentell The Humble For Loop in Rust The Humble For Loop in JavaScript Don Question Best Practices I Was a 1980s Teenage Programmer Part 5: Achieving Assembly I Was a 1980s Teenage Programmer Part 4: The Call of Assembly The Tooling Shift I Was a 1980s Teenage Programmer Part 3: MSX-2 JavaScript: when you need two ways to do it! Empowering Programming Languages Bloat and Retrofuturism Refreshing my Blog Again Random Rust Impressions Apilar: An Alife System I Was a 1980s Teenage Programmer Part 2: Olivetti M24 I Was a 1980s Teenage Programmer: the Alphatronic SolidJS fits my brain Is premature optimization the root of all evil? Framework Patterns: JavaScript edition Roll Your Own Frameworks Framework Patterns Secret Weblog Highlights Refactoring to Multiple Exit Points mstform: a form library for mobx-state-tree Seven Years: A Very Personal History of the Web
the why of lxml
Martijn Faassen · 2005-08-05 · via Secret Weblog

Today I read an article about libxslt on O'Reilly's xml.com. It demonstrates the power of libxslt; it's a cool library. It also demonstrates why I wrote lxml: writing Python code that correctly uses libxml2/libxslt's bindings directly is difficult.

The example in the article goes like this:

# xsltprocs.py: send an XML source document through a
# pipeline of multiple XSLT stylesheets.

import sys
import libxml2
import libxslt

args = len(sys.argv)

if args <  3:
    print "Pipeline an XML document through a series "
    print "of XSLT stylesheets. Usage:\n"
    print "  xsltprocs.py infile.xml stylesheet1.xsl   [stylesheet2.xsl...]"
    sys.exit(0)

sourceXMLFile = sys.argv[1]
sourceDoc = libxml2.parseFile(sourceXMLFile)

for xsl in range (2,args):
    # Read in stylesheet.
    styleDoc = libxml2.parseFile(sys.argv[xsl])
    style = libxslt.parseStylesheetDoc(styleDoc)
    # Apply stylesheet to sourceDoc, save in result.
    result = style.applyStylesheet(sourceDoc, None)
    # Result becomes new sourceDoc in case we send it
    sourceDoc = result   # through another stylesheet.

print result

style.freeStylesheet()
sourceDoc.freeDoc()

What it does is pipe a single XML document through multiple phases of XSLT transformation. It works, though with my version of libxml2 think the last line should say:

print result.serialize()

as otherwise you don't get the proper XML output as expected. Better yet, it should be serialized through the last XSLT sheet's serialization functionality as it may have things to say about the serialization process.

It however has a memory bug. It doesn't matter in this context, as it's just a script, but it might start to matter quickly in a long-running process. What happens is that at the end of the script, the document and the XSLT sheet are cleaned up manually, but the intermediate results or stylesheets never are.

It's an easy mistake to make. Python programmers aren't supposed to have to worry about manual memory management. I rewrote the script to use lxml:

# xsltprocs.py: send an XML source document through a
# pipeline of multiple XSLT stylesheets.

import sys
from lxml import etree

args = len(sys.argv)

if args <  3:
    print "Pipeline an XML document through a series "
    print "of XSLT stylesheets. Usage:\n"
    print "  xsltprocs.py infile.xml stylesheet1.xsl [stylesheet2.xsl...]"
    sys.exit(0)

sourceXMLFile = sys.argv[1]
sourceDoc = etree.parse(sourceXMLFile)

for xsl in range (2,args):
    # Read in stylesheet.
    styleDoc = etree.parse(sys.argv[xsl])
    style = etree.XSLT(styleDoc)
    # Apply stylesheet to sourceDoc, save in result.
    result = style.apply(sourceDoc)
    # Result becomes new sourceDoc in case we send it
    sourceDoc = result   # through another stylesheet.

print style.tostring(result)

This doesn't look much simpler than the pure libxml2/libxslt example (more involved examples would), but as you see the memory management logic is gone, as lxml takes care of this automatically. Moreover, the memory management logic is correct, or that's a bug in lxml.