XSLT 模板不适用于所有使用 lxml 的元素
XSLT template does not apply to all elements using lxml
我对 XSLT templates 和 when/how 的使用感到困惑。假设我有以下 XML 文件:
<book>
<chapter> 1 </chapter>
<chapter> 2 </chapter>
</book>
我想按顺序匹配所有章节。这是一个 XSLT 样式表:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="book">
<h1>book</h1>
</xsl:template>
<xsl:template match="chapter">
<h2>chapter <xsl:value-of select="."/></h2>
</xsl:template>
</xsl:stylesheet>
样式表的结果是
<h1>book</h1>
没有预期的章节编号。添加一个 <xsl:apply-templates />
at the end of the book
matching template didn't help. I'd like to do without an xls:for-each
不过。
编辑 我应该提到这一点:我正在使用 Python 的 lxml module which uses libxml2 and libxslt。以下代码 不会 产生预期的结果,而是产生上面的结果:
import lxml.etree
xml = lxml.etree.XML("""
<book>
<chapter> 1 </chapter>
<chapter> 2 </chapter>
</book>
""")
transform = lxml.etree.XSLT( lxml.etree.XML("""
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="book">
<h1>book</h1>
<xsl:apply-templates />
</xsl:template>
<xsl:template match="chapter">
<h2>chapter <xsl:value-of select="."/></h2>
</xsl:template>
</xsl:stylesheet>
""") )
html = transform(xml)
print( lxml.etree.tostring(html, pretty_print=True) )
奇怪的是,正确的(预期的)结果被证明 here. Accessing libxslt
directly through the Python bindings 而不是通过 lxml 工作,但是:
import libxml2
import libxslt
doc = libxml2.parseDoc("""
<book>
<chapter> 1 </chapter>
<chapter> 2 </chapter>
</book>
""")
styledoc = libxml2.parseDoc("""
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="book">
<h1>book</h1>
<xsl:apply-templates />
</xsl:template>
<xsl:template match="chapter">
<h2>chapter <xsl:value-of select="."/></h2>
</xsl:template>
</xsl:stylesheet>
""")
style = libxslt.parseStylesheetDoc(styledoc)
print( style.applyStylesheet(doc, None) )
我错过了什么?
不确定为什么添加 <xsl:apply-templates/>
对您不起作用。
但是,您缺少输出 XML 的根元素。
此样式表:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="book">
<root>
<h1>book</h1>
<xsl:apply-templates/>
</root>
</xsl:template>
<xsl:template match="chapter">
<h2>chapter <xsl:value-of select="."/>
</h2>
</xsl:template>
</xsl:stylesheet>
会产生:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<h1>book</h1>
<h2>chapter 1 </h2>
<h2>chapter 2 </h2>
</root>
这看起来真的很奇怪 - 除非你意识到会发生什么。据我所知,这与 lxml 如何执行 XSLT 转换无关。
只是 lxml.etree.tostring()
需要一个包含 格式良好 HTML 或 XML 的对象作为输入。您不要 提交格式正确的标记:
<?xml version="1.0"?>
<h1>book</h1>
<h2>chapter 1 </h2>
<h2>chapter 2 </h2>
因为你不这样做,所以它在第一个最外层(是的,有三个)元素之后停止。在我看来完全合理,不应该有任何理由不输出格式正确的 XHTML - 如果后面的内容不是 XML (如其他已指出)。
为了证明这一切,运行 下面的代码。唯一的变化是我只是 print
结果。
import lxml.etree
xml = lxml.etree.XML("""
<book>
<chapter> 1 </chapter>
<chapter> 2 </chapter>
</book>
""")
transform = lxml.etree.XSLT( lxml.etree.XML("""
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="book">
<h1>book</h1>
<xsl:apply-templates />
</xsl:template>
<xsl:template match="chapter">
<h2>chapter <xsl:value-of select="."/></h2>
</xsl:template>
</xsl:stylesheet>
""") )
html = transform(xml)
print(html)
命令行的结果是
<?xml version="1.0"?>
<h1>book</h1>
<h2>chapter 1 </h2>
<h2>chapter 2 </h2>
[EMPTY OUPUT LINE]
[EMPTY OUPUT LINE]
而且,现在显而易见的是:
- 使用 libxml2 和 libxslt 的代码可以工作,因为打印方法不同
- 修改 XSLT 样式表以插入单个根元素是有效的,因为这样
tostring()
可以序列化格式良好的 XML.
使用lxml 3.4.1, Python sys.version 为2.7.5, Mac OS X.
我对 XSLT templates 和 when/how 的使用感到困惑。假设我有以下 XML 文件:
<book>
<chapter> 1 </chapter>
<chapter> 2 </chapter>
</book>
我想按顺序匹配所有章节。这是一个 XSLT 样式表:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="book">
<h1>book</h1>
</xsl:template>
<xsl:template match="chapter">
<h2>chapter <xsl:value-of select="."/></h2>
</xsl:template>
</xsl:stylesheet>
样式表的结果是
<h1>book</h1>
没有预期的章节编号。添加一个 <xsl:apply-templates />
at the end of the book
matching template didn't help. I'd like to do without an xls:for-each
不过。
编辑 我应该提到这一点:我正在使用 Python 的 lxml module which uses libxml2 and libxslt。以下代码 不会 产生预期的结果,而是产生上面的结果:
import lxml.etree
xml = lxml.etree.XML("""
<book>
<chapter> 1 </chapter>
<chapter> 2 </chapter>
</book>
""")
transform = lxml.etree.XSLT( lxml.etree.XML("""
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="book">
<h1>book</h1>
<xsl:apply-templates />
</xsl:template>
<xsl:template match="chapter">
<h2>chapter <xsl:value-of select="."/></h2>
</xsl:template>
</xsl:stylesheet>
""") )
html = transform(xml)
print( lxml.etree.tostring(html, pretty_print=True) )
奇怪的是,正确的(预期的)结果被证明 here. Accessing libxslt
directly through the Python bindings 而不是通过 lxml 工作,但是:
import libxml2
import libxslt
doc = libxml2.parseDoc("""
<book>
<chapter> 1 </chapter>
<chapter> 2 </chapter>
</book>
""")
styledoc = libxml2.parseDoc("""
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="book">
<h1>book</h1>
<xsl:apply-templates />
</xsl:template>
<xsl:template match="chapter">
<h2>chapter <xsl:value-of select="."/></h2>
</xsl:template>
</xsl:stylesheet>
""")
style = libxslt.parseStylesheetDoc(styledoc)
print( style.applyStylesheet(doc, None) )
我错过了什么?
不确定为什么添加 <xsl:apply-templates/>
对您不起作用。
但是,您缺少输出 XML 的根元素。
此样式表:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="book">
<root>
<h1>book</h1>
<xsl:apply-templates/>
</root>
</xsl:template>
<xsl:template match="chapter">
<h2>chapter <xsl:value-of select="."/>
</h2>
</xsl:template>
</xsl:stylesheet>
会产生:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<h1>book</h1>
<h2>chapter 1 </h2>
<h2>chapter 2 </h2>
</root>
这看起来真的很奇怪 - 除非你意识到会发生什么。据我所知,这与 lxml 如何执行 XSLT 转换无关。
只是 lxml.etree.tostring()
需要一个包含 格式良好 HTML 或 XML 的对象作为输入。您不要 提交格式正确的标记:
<?xml version="1.0"?>
<h1>book</h1>
<h2>chapter 1 </h2>
<h2>chapter 2 </h2>
因为你不这样做,所以它在第一个最外层(是的,有三个)元素之后停止。在我看来完全合理,不应该有任何理由不输出格式正确的 XHTML - 如果后面的内容不是 XML (如其他已指出)。
为了证明这一切,运行 下面的代码。唯一的变化是我只是 print
结果。
import lxml.etree
xml = lxml.etree.XML("""
<book>
<chapter> 1 </chapter>
<chapter> 2 </chapter>
</book>
""")
transform = lxml.etree.XSLT( lxml.etree.XML("""
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="book">
<h1>book</h1>
<xsl:apply-templates />
</xsl:template>
<xsl:template match="chapter">
<h2>chapter <xsl:value-of select="."/></h2>
</xsl:template>
</xsl:stylesheet>
""") )
html = transform(xml)
print(html)
命令行的结果是
<?xml version="1.0"?>
<h1>book</h1>
<h2>chapter 1 </h2>
<h2>chapter 2 </h2>
[EMPTY OUPUT LINE]
[EMPTY OUPUT LINE]
而且,现在显而易见的是:
- 使用 libxml2 和 libxslt 的代码可以工作,因为打印方法不同
- 修改 XSLT 样式表以插入单个根元素是有效的,因为这样
tostring()
可以序列化格式良好的 XML.
使用lxml 3.4.1, Python sys.version 为2.7.5, Mac OS X.