Converting HTML list (<li>) to tabs (i.e. indentation)
html, python, regex, tabs
Solution
You should really use an xml parser to do this, but to answer your question:
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
This will work for your example, and your example ONLY. Use an XML parser. You can use `xml.dom.minidom` (it's included in Python (2.7 at least), no need to download anything):
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)
Output:
* First level
* Second level
* Second level 2
* Third level
Problem
Have worked in dozens of languages but new to Python. My first (maybe second) question here, so be gentle... Trying to efficiently convert HTML-like markdown text to wiki format (specifically, Linux Tomboy/GNote notes to Zim) and have gotten stuck on converting lists. For a 2-level unordered list like this... - First level - Second level Tomboy/GNote uses something like... `<list><list-item>First level<list><list-item>Second level</list-item></list></list-item></list>` However, the Zim personal wiki wants that to be... ``` * First level * Second level ``` ... with leading tabs. I've explored the regex module functions re.sub(), re.match(), re.search(), etc. and found the cool Python ability to code repeating text as... ``` count * "text" ``` Thus, it looks like there should be a way to do something like... ``` newnote = re.sub("<list>", LEVEL * "\t", oldnote) ``` Where LEVEL is the ordinal (occurrance) of `<list>` in the note. It would thus be `0` for the first `<list>` incountered, `1` for the second, etc. LEVEL would then be decremented each time `</list>` was encountered. `<list-item>` tags are converted to the asterisk for the bullet (preceded by newline as appropriate) and `</list-item>` tags dropped. Finally... the question... - How do I get the value of LEVEL and use it as a tabs multiplier?