我试图从xml文件中提取一些数据,并根据特定节点将其传递给许多html文件。我的source.xml
:
<?xml version="1.0" encoding="UTF-8" ?>
<products>
<product>
<id>1</id>
<feature>Product description escaped html tags</feature>
</product>
<product>
<id>2</id>
<feature>Product description escaped html tags</feature>
</product>
.........................
<product>
<id>5</id>
<feature>Product description escaped html tags</feature>
</product>
</products>
预期结果:有多个html文件,内容如下:
<p>1</p>
Product description with html tags
我使用的是这个python代码:
import lxml.etree as ET
doc = ET.parse('source.xml')
xslt = ET.parse('modify.xsl')
transform = ET.XSLT(xslt)
products = doc.findall('product')
for product in products:
i = product.find('id')
n = ET.XSLT.strparam(str(i))
describ = transform(doc, item_num=n)
f = open('file_nr_{}.html'.format(i.text), 'wb')
f.write(describ)
f.close()
我当前的样式表modify.xsl
:
<?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" indent="yes" encoding="UTF-8" />
<xsl:param name="item_num"/>
<xsl:template match="/products">
<xsl:apply-templates select="product[id=$item_num]" />
</xsl:template>
<xsl:template match="id" >
<p><xsl:value-of select="."/></p>
<xsl:value-of select="following-sibling::feature" disable-output-escaping="yes"/>
</xsl:template>
</xsl:stylesheet>
给了我多个完整的零字节空文件。但当我换线时:
<xsl:apply-templates select="product[id=$item_num]" />
到此:
<xsl:apply-templates select="product[id<4]" />
它给了我五个内容相同的文件:
<p>1</p>Product description with still escaped html tags
Product description with still escaped html tags
<p>2</p>Product description with still escaped html tags
Product description with still escaped html tags
<p>3</p>Product description with still escaped html tags
Product description with still escaped html tags
我不知道如何:
- 在仅匹配一个
<product>
和特定<id>
的路径中正确使用变量 - 有效禁用转义
- 适当地要求谷歌找到解决方案…;(
我尝试了这个和这个,这个和这个并在这里搜索,但我不能在我的情况下使用这些知识。可能是因为我仍然不明白传递变量值是如何工作的。从星期五开始,我就试着自己解决这个问题,但唯一的结果就是头疼。。请帮忙。
您的尝试:
<xsl:template match="/products">
<xsl:apply-templates select="product[id=$item_num]" />
</xsl:template>
<xsl:template match="id" >
<p><xsl:value-of select="."/></p>
<xsl:value-of select="following-sibling::feature" disable-output-escaping="yes"/>
</xsl:template>
将模板应用于<product>
节点,但具有用于<id>
节点的模板。
为<product>
节点制作一个模板。
<xsl:template match="product">
<p><xsl:value-of select="id"/></p>
<xsl:value-of select="feature" disable-output-escaping="yes" />
</xsl:template>
每当XSLT找不到特定节点的模板时,它就会返回到默认行为。默认行为是";复制子文本节点以输出,并将模板应用于子元素";。这就解释了为什么您在代码中看到的内容。
关于您的另一个问题:.find('...')
返回XML节点,而不是字符串值,即.find('id')
查找<id>
元素。您希望传递找到的节点的.text
作为XSLT参数,而不是节点本身:
import lxml.etree as ET
doc = ET.parse('source.xml')
xslt = ET.parse('modify.xsl')
transform = ET.XSLT(xslt)
products = doc.findall('product')
for product in products:
i = product.find('id').text
describ = transform(doc, item_num=i)
with open(f'file_nr_{i}.html', 'wb') as f:
f.write(describ)