Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python lxml-xslt性能与xpath和replace_Python_Xslt_Xpath_Lxml - Fatal编程技术网

Python lxml-xslt性能与xpath和replace

Python lxml-xslt性能与xpath和replace,python,xslt,xpath,lxml,Python,Xslt,Xpath,Lxml,我有一些代码,作为其运行的一部分,它将HTML文档转换为另一种形式以便于输出。(基本上是HTML到BBCode。) 我目前正在通过定义XPath和替换的字典来实现这一点,然后使用lxml中的工具对字典进行迭代: change_xpaths = { XPath(".//span[contains(@style, 'font')]") : "font", XPath(".//span[contains(@style, 'colo

我有一些代码,作为其运行的一部分,它将HTML文档转换为另一种形式以便于输出。(基本上是HTML到BBCode。)

我目前正在通过定义XPath和替换的字典来实现这一点,然后使用lxml中的工具对字典进行迭代:

change_xpaths = {
                  XPath(".//span[contains(@style, 'font')]") : "font",
                  XPath(".//span[contains(@style, 'color')]") : "color",
                  XPath(".//span[contains(@style, 'size')]") : "size"
                  }

replace_xpaths = {
            XPath(".//span[@style='text-decoration: underline']") : "u",
            XPath(".//span[@style='text-decoration: line-through']") : "s",
            XPath(".//div[@style='padding-left: 30px']") : "remove"
                }

def _clean_text(cls, raw):
    for ele in cls.struck_through_xpath(raw):
        ele.getparent().remove(ele)
    for xp, repl in cls.replace_xpaths.items():
        for ele in xp(raw):
            ele.attrib.pop("style")
            ele.tag = repl
    for xp, chng in cls.change_xpaths.items():
        for ele in xp(raw):
            ele.tag = chng
    for br in raw.xpath(".//br"):
        try:
            br.tail = "\n" + br.tail
        except TypeError:
            br.tail = "\n"
    strip_elements(raw, 'img', with_tail = False)
    strip_elements(raw, 'br', with_tail = False)
    strip_tags(raw, 'remove')
(这确实是类定义的一部分。)

我知道我也可以使用xslt转换来实现这一点

首先,我想确认我确实可以用xslt完成这一切,也就是说,用非标准标记替换一些标记,完全删除标记,同时保留它们的文本或尾部内容

第二,我想知道这样做是否能显著提高绩效?但是,我怀疑是这样,我似乎在互联网上找不到太多关于这方面的信息。

问题1:是的,XSLT可以做到这一点。但似乎您只是忽略了字体、颜色和大小值。实际上,使用XSLT1.0从内联CSS解析这些值可能会很复杂

问题2:我认为速度会明显加快。使用当前的解决方案,您必须多次迭代文档的所有节点(超过10次,AFAIC)。使用XSLT样式表,每个输入节点只访问一次。另外,由于lxml基于libxml2和libxslt,因此需要较少的对C-API的调用,根据我的经验,这可能会非常昂贵

OTOH,通过重写Python代码只扫描文档一次,可以获得类似的性能提升

如果进行多次转换,请确保只编译一次XSLT样式表

在XSLT级别也有一些可能的优化。最优雅的方法是编写如下模板:

<xsl:template match="span[contains(@style, 'font')]">...
<xsl:template match="span[contains(@style, 'color')]">...
<xsl:template match="span[contains(@style, 'size')]">...
。。。
...
...
对于每个元素名使用一个模板可能会更快一些,如下所示:

<xsl:template match="span">
    <xsl:choose>
        <xsl:when test="contains(@style, 'font')">...
        <xsl:when test="contains(@style, 'color')">...
        <xsl:when test="contains(@style, 'size')">...

...
...
...

感谢您的回复!实际上,我并不完全忽略颜色、字体和大小值;我只是先用XPath将它们清理一下,然后用正则表达式将它们替换成所需的
[color=#123456]
。另外,我如何重写它,使它只在文档中浏览一次?除了一些笨重的状态机,我真的看不到其他方法。我可以遍历整个文档,并根据测试字典测试每个节点。但是,这会比测试每个XPath的成本更低吗?经过仔细考虑,如果对C的调用本身是昂贵的,我根本不确定迭代文档并在每个节点上调用测试的成本是否会更低。我肯定会用这种方式调用更多的C函数!