我对使用XSLT templates以及何时/如何应用它感到困惑。假设我有以下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>
没有章节的预期编号。在book
匹配模板的末尾添加<xsl:apply-templates />
没有帮助。我不想做xls:for-each
。
编辑我应该提到这一点:我正在使用使用lxml module的Python 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。但是,直接通过Python bindings访问libxslt
而不是通过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) )
我错过了什么?
答案 0 :(得分:4)
这真的很奇怪 - 除非你意识到会发生什么。就我所见,这与lxml执行XSLT转换的方式无关。
只是lxml.etree.tostring()
期望包含格式良好的 HTML或XML的对象作为输入。你不交出格式正确的标记:
<?xml version="1.0"?>
<h1>book</h1>
<h2>chapter 1 </h2>
<h2>chapter 2 </h2>
因为你没有,它会在第一个最外面的(是的,有三个)元素之后停止。在我看来,完全合理的是,没有任何理由不输出格式良好的XHTML - 如果后面的内容不是XML(正如其他人所指出的那样),那么使用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]
而且,陈述现在显而易见的:
tostring()
可以序列化格式良好的XML。使用lxml 3.4.1,Python sys.version是2.7.5,Mac OS X.
答案 1 :(得分:0)
不确定为什么添加<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>