如何在xsl:apply-templates中使用变量作为值



我试图从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&lt;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)

最新更新