-1

I'm writing an XML file using lxml and in one of the nodes, the content to write is a very long string. I'm looking for a way to wrap these strings in the XML nodes.

For now, I tried as below :

from lxml import etree


def lines_lenght(string, width):
    words = string.split()
    for i in range(0, len(words), width):
        yield " ".join(words[i:i+width])

s = """
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec in enim at arcu tincidunt tristique. Ut commodo dui hendrerit lobortis egestas. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed laoreet interdum enim ut cursus. Fusce condimentum dictum dictum. Morbi feugiat bibendum enim, ut mollis turpis tincidunt vitae. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce libero ante, consectetur at sollicitudin at, eleifend lacinia ipsum. In hac habitasse platea dictumst. Sed laoreet mi eu nisi condimentum, sit amet vestibulum purus elementum. Nam a eros mi. 
"""


root = etree.Element("corpus")

doc = etree.ElementTree(root)

article_node = etree.SubElement(root, "article")

final_content = "\n".join(lines_lenght(s, 10))
article_node.text = final_content

doc.write("corpus.xml", xml_declaration=True, encoding="utf-8")

But in the generated XML file, the line breaks do not seem to be preserved. According this answer I tried with 
 instead of \n, but the result is the same.

Any hint to help me?

Edit: Here is a preview of what I try to achieve:

<corpus>  
<article>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec in  
enim at arcu tincidunt tristique. Ut commodo dui hendrerit lobortis  
egestas. Orci varius natoque penatibus et magnis dis parturient   montes</article>  
</corpus>  

Instead of:

<corpus>
<article>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec in enim at arcu tincidunt tristique. Ut commodo dui hendrerit lobortis egestas. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</article>
</corpus>
Tetro
  • 5
  • 4

1 Answers1

0

Well, it took a while to get there, and on the way I had to enlist the help of this answer here, and move out of lxml (which, as others have said, is a great library but has many limitations), to a python built in.

Is starts like yours, but stops right after article_node.text = final_content (before doc.write()). And adds from the answer linked above:

def indent(elem, level=0):
i = "\n" + level*"  "
if len(elem):
    #print(len(elem))
    if not elem.text or not elem.text.strip():
        elem.text = i + "  "
    if not elem.tail or not elem.tail.strip():
        elem.tail = i
    for elem in elem:
        indent(elem, level+1)
    if not elem.tail or not elem.tail.strip():
        elem.tail = i

else:
    if level and (not elem.tail or not elem.tail.strip()):
        elem.tail = i

Then on to:

import xml.etree.ElementTree as ET
root2 = ET.fromstring(etree.tostring(doc))
tree = ET.ElementTree(root2)

indent(root2)
tree.write("corpus.xml", encoding="utf-8", xml_declaration=True)

To test it:

with open("corpus.xml") as f:
    print(f.read())

Output:

<?xml version='1.0' encoding='utf-8'?>
<corpus>
  <article>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec in
enim at arcu tincidunt tristique. Ut commodo dui hendrerit lobortis
egestas. Orci varius natoque penatibus et magnis dis parturient montes,
nascetur ridiculus mus. Sed laoreet interdum enim ut cursus. Fusce
condimentum dictum dictum. Morbi feugiat bibendum enim, ut mollis turpis
tincidunt vitae. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Fusce libero ante, consectetur at sollicitudin at, eleifend lacinia ipsum.
In hac habitasse platea dictumst. Sed laoreet mi eu nisi
condimentum, sit amet vestibulum purus elementum. Nam a eros mi.</article>
</corpus>

Those more familiar with the xml library may be able to make this shorter, but that's the best I could do...

Jack Fleeting
  • 24,385
  • 6
  • 23
  • 45