1

(Python 3.6.) I'm using lxml builder or E-factory to generate some XML for an API that requires some XML tags to have a dot in it. Say one particular tag must be <term.ID>.

The lxml builder examples I've found so far all hard-code the xml tag. (I haven't found how to use variables to specify xml tags - Can it be done?) Anyway, doing so, a dot in a tag will be interpreted as a method dot. As a workaround, I first specify the tag with an underscore:

import lxml.etree
import lxml.builder

E = lxml.builder.ElementMaker() 
terms = ['eggs', 'bacon', 'sausage', 'spam']

xmllist = E.recordList()
for term in terms: 
    xmlrecord = E.record(
        E.term_ID(term)         # term_ID should become term.ID
    )    
    xmllist.append(xmlrecord)

wrap = (E.someXMLdialect())     # wrap has type <class 'lxml.etree._Element'>
wrap.append(xmllist)     

# convert wrap to string, replace the underscore in term_ID with a dot
s = lxml.etree.tostring(wrap).replace(b'term_ID', b'term.ID')
with open('sample_2.xml', 'wb') as f:
    f.write(s)

At the end, I convert xml to a string so I can use replace to replace the underscore with a dot, and then write the result as a byte stream.

I chose lxml builder for ease of use and performance, but having to revert to this workaround reduces the ease of use.

So I'm wondering if there isn't a better, more Pythonic way?

Note that E.term_ID isn't a string. If it were, I could use E.term\uff0EID from here.

RolfBly
  • 3,612
  • 5
  • 32
  • 46

1 Answers1

2

ElementMaker allows you to pass the element name as a string.

for term in terms: 
    xmlrecord = E.record(
        E("term.ID", term)    # This works
    )    

See http://lxml.de/api/lxml.builder.ElementMaker-class.html.

mzjn
  • 48,958
  • 13
  • 128
  • 248