I’m massaging some HTML dictionary data into XML for import into some dictionary software.
The original HTML looks something like this:
<div class="entry">
<span class="headword">word</span>
<span class="pos">part of speech</span>
<span class="definition">sense1; sense2
<span class="example">(example2.1; example2.2)</span>
; sense3 <span class="example">(example3.1; example3.2)</span>
</span>
</div>
Edit: In fact, the input‘s classes don’t neatly match the output XML tags. That was just to make the relationship clear in my example. I need to replace specific classes with specific XML tags, but they don’t match.
The ideal end result would look like this:
<entry>
<headword>word</headword>
<pos>part of speech</pos>
<sense>
<definition>sense1</definition>
</sense>
<sense>
<definition>sense2</definition>
<example>example2.1</example>
<example>example2.2</example>
</sense>
<sense>
<definition>sense3</definition>
<example>example3.1</example>
<example>example3.2</example>
</sense>
</entry>
The current state of my soup (having done the straightforward replacements) is:
<entry>
<headword>word</headword>
<pos>part of speech</pos>
<definition>sense1; sense2
<example>example2.1</example>
<example>example2.2</example>
; sense3
<example>example3.1</example>
<example>example3.2</example>
</definition>
</entry>
The divisions that map 1:1 are easy and wrapping the definitions+examples in a sense tag should be too, but the problem is the way the original indiscriminately uses ; to separate both senses and examples. This means I need to split the example tags first and then the definition tags at ; (i.e. effectively replace ; with </example>\n<example> or </definition>\n<definition>). Since I started writing this question I’ve figured out how to do that for the examples (since they only contain strings), but the definitions are very likely to contain <example> tags themselves, so I can’t just use split() because a list is returned & 'list' object has no attribute 'split'.
Is there any easier way to split tags containing other tags or do I have to iterate through the resultset list and recreate all the tags?
tags = soup.find_all("example")
for tag in tags:
tag.string = re.sub(r"[()]", "", tag.string) # remove parentheses
egs = tag.string.split("; ") # or str(tag.contents).split("; ") ?
new = ""
if len(egs) > 1:
for eg in reversed(egs[1:]):
new = soup.new_tag("example")
new.string = eg
tag.insert_after(new)
tag.string = egs[0] # orig tag becomes 1st seg only