1

I have some XML text like this:

text = '<sp> <speaker>T<seg rend="small">ARSIS</seg>. </speaker> <p>—Adelante, Señora. Gracias á la luz rosada, franquearemos sin tropezones este ingrato sendero.</p> </sp> <sp> <speaker>L<seg rend="small">A</seg> M<seg rend="small">ADRE</seg>. </speaker> <p>—La llovizna nos coge ahora de cara… Yo no la temo. Tengo mi rostro bien curtido para estas inclemencias que hacen á mis hijos duros, y tan insensibles al frío como al calor. Tú también te has endurecido, según veo, y te has dejado en los aires sutiles y en los ardores del sol tu antigua carita de galancete afeminado.</p>'

I want everything in the <seg rend="small"> to become lowercase, like:

 <sp> <speaker>T<seg rend="small">arsis</seg>. </speaker> <p>—Adelante, Señora. Gracias á la luz rosada, franquearemos sin tropezones este ingrato sendero.</p> </sp> <sp> <speaker>L<seg rend="small">a</seg> M<seg rend="small">adre</seg>. </speaker> <p>—La llovizna nos coge ahora de cara… Yo no la temo. Tengo mi rostro bien curtido para estas inclemencias que hacen á mis hijos duros, y tan insensibles al frío como al calor. Tú también te has endurecido, según veo, y te has dejado en los aires sutiles y en los ardores del sol tu antigua carita de galancete afeminado.</p> </sp> <sp> <speaker>T<seg rend="small">arsis</seg>. </speaker> <p>—En los días ásperos de la Aldehuela empecé á soltar mi máscara de cera, y cambié los goznes quebradizos de mi máquina corporal por otros de acero.</p> </sp> <sp> <speaker>L<seg rend="small">a</seg> M<seg rend="small">adre</seg>. </speaker> <p>—Al nombrar la Aldehuela traes á mi memoria algo que tenía que decirte, y es cosa en verdad lamentable. ¿Sabes que ha muerto el pobre José Caminero?</p> </sp>

I have tried different variants of something like this in Python:

    for f in re.findall(r'<seg rend="small">([^<]*?)</seg>', text):
        text = text.replace(f, f.lower())

But it doesn't work and I get weird results like <seg rend="small">aDRE</seg>, no idea why. Could please anyone help me? Thanks in advance!

José
  • 533
  • 1
  • 4
  • 14

2 Answers2

1

First of all, do not parse HTML with regex. That being said, you could use lxml:

from lxml import html

text = '<sp> <speaker>T<seg rend="small">ARSIS</seg>. </speaker> <p>—Adelante, Señora. Gracias á la luz rosada, franquearemos sin tropezones este ingrato sendero.</p> </sp> <sp> <speaker>L<seg rend="small">A</seg> M<seg rend="small">ADRE</seg>. </speaker> <p>—La llovizna nos coge ahora de cara… Yo no la temo. Tengo mi rostro bien curtido para estas inclemencias que hacen á mis hijos duros, y tan insensibles al frío como al calor. Tú también te has endurecido, según veo, y te has dejado en los aires sutiles y en los ardores del sol tu antigua carita de galancete afeminado.</p>'

tree = html.fromstring(text)
results = [x.lower() for x in tree.xpath('//seg[@rend="small"]/text()')]
print results

Output:

['arsis', 'a', 'adre']
Andrés Pérez-Albela H.
  • 4,003
  • 1
  • 18
  • 29
  • 1
    Hi! thanks for your answer, but the thing is that I deal with very crappy HTML, not even wellformed, so I can't work directly with lxml. Maybe I should have said that in first place. Thanks! – José Apr 18 '16 at 06:09
  • Yes, tagging the question "xml" when the data isn't XML is probably not a good idea. – Michael Kay Apr 18 '16 at 08:07
1

You may use regex..

>>> txt = 'foo <seg rend="small">ARSIS</seg> bar'
>>> import re
>>> re.sub(r'(<seg\s+rend\s*=\s*"small">)(.*?)(?=</seg>)', lambda m: m.group(1) + m.group(2).lower(), txt)
'foo <seg rend="small">arsis</seg> bar'
>>> 
Avinash Raj
  • 172,303
  • 28
  • 230
  • 274