【问题标题】:wrap implicit section of an HTML document into section tags using lxml.etree使用 lxml.etree 将 HTML 文档的隐式部分包装到部分标签中
【发布时间】:2014-02-24 16:45:49
【问题描述】:

我正在尝试编写一个小函数来将 HTML 文档的隐式部分包装到部分标签中。我正在尝试使用 lxml.etree。

假设我的输入是:

<html>
    <head></head>
    <body>
        <h1>title</h1>
        <p>some text</p>
        <h1>title</h1>
        <p>some text</p>
    </body>
</html>

我想结束:

<html>
    <head></head>
    <body>
        <section>
            <h1>title</h1>
            <p>some text</p>
        </section>
        <section>
            <h1>title</h1>
            <p>some text</p>
        </section>
    </body>
</html>

这是我目前拥有的

def outline(tree):
    pattern = re.compile('^h(\d)')
    section = None

    for child in tree.iterchildren():
        tag = child.tag

        if tag is lxml.etree.Comment:
            continue

        match = pattern.match(tag.lower())

        # If a header tag is found
        if match:
            depth = int(match.group(1))

            if section is not None:
                child.addprevious(section)

            section = lxml.etree.Element('section')
            section.append(child)

        else:
            if section is not None:
                section.append(child)
            else:
                pass

        if child is not None:
            outline(child)

我是这样称呼的

 outline(tree.find('body'))

但目前它不适用于副标题,例如:

<section>
    <h1>ONE</h1>
    <section>
        <h3>TOO Deep</h3>
    </section>
    <section>
        <h2>Level 2</h2>
    </section>
</section>
<section>
    <h1>TWO</h1>
</section>

谢谢

【问题讨论】:

    标签: python html lxml elementtree


    【解决方案1】:

    在转换 xml 时,xslt 是最好的方法,请参阅lxml and xslt docs。

    这只是一个要求的方向,如果您需要进一步的帮助来编写 xslt,请告诉我

    【讨论】:

    • 谢谢。我从树的迭代开始。我也很好奇 xpath 的解决方案。
    【解决方案2】:

    这是我最终得到的代码,记录在案:

    def outline(tree, level=0):
        pattern = re.compile('^h(\d)')
        last_depth = None
        sections = [] # [header, <section />]
    
        for child in tree.iterchildren():
            tag = child.tag
    
            if tag is lxml.etree.Comment:
                continue
    
            match = pattern.match(tag.lower())
            #print("%s%s" % (level * ' ', child))
    
            if match:
                depth = int(match.group(1))
    
                if depth <= last_depth or last_depth is None:
                    #print("%ssection %d" % (level * ' ', depth))
                    last_depth = depth
    
                    sections.append([child, lxml.etree.Element('section')])
                    continue
    
            if sections:
                sections[-1][1].append(child)
    
        for section in sections:
            outline(section[1], level=((level + 1) * 4))
            section[0].addprevious(section[1])
            section[1].insert(0, section[0])
    

    对我来说效果很好

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-10
      相关资源
      最近更新 更多