3

曾使用过数十种语言,但对 Python 不熟悉。

我在这里的第一个(也许是第二个)问题,所以要温柔......

试图有效地将类似 HTML 的 markdown 文本转换为 wiki 格式(特别是 Linux Tomboy/GNote 到 Zim 的注释)并且一直卡在转换列表上。

对于像这样的 2 级无序列表...

  • 第一级
    • 第二级

Tomboy/GNote 使用类似...

<list><list-item>First level<list><list-item>Second level</list-item></list></list-item></list>

然而,Zim 个人 wiki 希望这是……

* First level
  * Second level

...带有前导标签。

我探索了正则表达式模块函数 re.sub()、re.match()、re.search() 等,并发现了很酷的 Python 功能,可以将重复文本编码为...

 count * "text"

因此,看起来应该有一种方法可以做类似的事情......

 newnote = re.sub("<list>", LEVEL * "\t", oldnote)

其中 LEVEL 是<list>注释中的序数(出现)。因此0,对于第一个<list>遇到的,1对于第二个,等等。

</list>每次遇到时, LEVEL 都会递减。

<list-item>标签被转换为项目符号的星号(在适当的情况下以换行符开头)和</list-item>标签被删除。

最后……问题……

  • 如何获得 LEVEL 的值并将其用作制表符乘数?
4

2 回答 2

4

您确实应该使用 xml 解析器来执行此操作,但要回答您的问题:

import re

def next_tag(s, tag):
    i = -1
    while True:
        try:
            i = s.index(tag, i+1)
        except ValueError:
            return
        yield i

a = "<list><list-item>First level<list><list-item>Second level</list-item></list></list-item></list>"

a = a.replace("<list-item>", "* ")

for LEVEL, ind in enumerate(next_tag(a, "<list>")):
    a = re.sub("<list>", "\n" + LEVEL * "\t", a, 1)

a = a.replace("</list-item>", "")
a = a.replace("</list>", "")

print a

这将适用于您的示例,并且适用于您的示例。使用 XML 解析器。您可以使用xml.dom.minidom(它包含在 Python 中(至少 2.7),无需下载任何东西):

import xml.dom.minidom

def parseList(el, lvl=0):
    txt = ""
    indent = "\t" * (lvl)
    for item in el.childNodes:
        # These are the <list-item>s: They can have text and nested <list> tag
        for subitem in item.childNodes:
            if subitem.nodeType is xml.dom.minidom.Element.TEXT_NODE:
                # This is the text before the next <list> tag
                txt += "\n" + indent + "* " + subitem.nodeValue
            else:
                # This is the next list tag, its indent level is incremented
                txt += parseList(subitem, lvl=lvl+1)
    return txt

def parseXML(s):
    doc = xml.dom.minidom.parseString(s)
    return parseList(doc.firstChild)

a = "<list><list-item>First level<list><list-item>Second level</list-item><list-item>Second level 2<list><list-item>Third level</list-item></list></list-item></list></list-item></list>"
print parseXML(a)

输出:

* First level
    * Second level
    * Second level 2
        * Third level
于 2012-04-15T12:19:19.967 回答
2

使用Beautiful soup ,它允许您在标签中迭代,即使它们是海关。做这种类型的操作非常实用

from BeautifulSoup import BeautifulSoup
tags = "<list><list-item>First level<list><list-item>Second level</list-item></list></list-item></list>"
soup = BeautifulSoup(tags)
print [[ item.text for item in list_tag('list-item')]  for list_tag in soup('list')]

Output : [[u'First level'], [u'Second level']]

我使用了嵌套列表推导,但您可以使用嵌套 for 循环

for list_tag in soup('list'):
     for item in list_tag('list-item'):
         print item.text

我希望这对你有帮助。

在我的示例中,我使用了 BeautifulSoup 3,但该示例应该与 BeautifulSoup4 一起使用,但只有导入更改。

from bs4 import BeautifulSoup
于 2012-04-15T11:30:15.520 回答