35 votes

XML, les outils d'écriture pour Python

Je suis en train d'essayer ElementTree et il a l'air bien, il s'échappe en entités HTML et ainsi de suite et ainsi de suite. Ai-je raté quelque chose de vraiment merveilleux que je n'ai pas entendu parler?

Ceci est similaire à ce que je suis en train de faire:

import xml.etree.ElementTree as ET
root = ET.Element('html')
head = ET.SubElement(root,'head')
script = ET.SubElement(head,'script')
script.set('type','text/javascript')
script.text = "var a = 'I love á letters'"
body = ET.SubElement(root,'body')
h1 = ET.SubElement(body,'h1')
h1.text = "And I like the fact that 3 > 1"
tree = ET.ElementTree(root)
tree.write('foo.xhtml')

# more foo.xhtml
<html><head><script type="text/javascript">var a = 'I love &amp;aacute;
letters'</script></head><body><h1>And I like the fact that 3 &gt; 1</h1>
</body></html>

28voto

Peter Hoffmann Points 13823

Un autre moyen est d'utiliser l' E Usine de générateur de lxml (disponible en Elementtree trop)

>>> from lxml.builder import E

>>> def CLASS(*args): # class is a reserved word in Python
...     return {"class":' '.join(args)}

>>> html = page = (
...   E.html(       # create an Element called "html"
...     E.head(
...       E.title("This is a sample document")
...     ),
...     E.body(
...       E.h1("Hello!", CLASS("title")),
...       E.p("This is a paragraph with ", E.b("bold"), " text in it!"),
...       E.p("This is another paragraph, with a", "\n      ",
...         E.a("link", href="http://www.python.org"), "."),
...       E.p("Here are some reserved characters: <spam&egg>."),
...       etree.XML("<p>And finally an embedded XHTML fragment.</p>"),
...     )
...   )
... )

>>> print(etree.tostring(page, pretty_print=True))
<html>
  <head>
    <title>This is a sample document</title>
  </head>
  <body>
    <h1 class="title">Hello!</h1>
    <p>This is a paragraph with <b>bold</b> text in it!</p>
    <p>This is another paragraph, with a
      <a href="http://www.python.org">link</a>.</p>
    <p>Here are some reservered characters: &lt;spam&amp;egg&gt;.</p>
    <p>And finally an embedded XHTML fragment.</p>
  </body>
</html>

24voto

oasisbob Points 369

Il y a toujours SimpleXMLWriter, une partie de la ElementTree toolkit. L'interface est extrêmement simple.

Voici un exemple:

from elementtree.SimpleXMLWriter import XMLWriter
import sys

w = XMLWriter(sys.stdout)
html = w.start("html")

w.start("head")
w.element("title", "my document")
w.element("meta", name="generator", value="my application 1.0")
w.end()

w.start("body")
w.element("h1", "this is a heading")
w.element("p", "this is a paragraph")

w.start("p")
w.data("this is ")
w.element("b", "bold")
w.data(" and ")
w.element("i", "italic")
w.data(".")
w.end("p")

w.close(html)

10voto

Eli Courtwright Points 53071

Je suppose que vous êtes en train de créer un XML DOM arbre, parce que vous souhaitez valider que ce qui va dans ce fichier XML valide, car sinon, on aurait suffit d'écrire une chaîne statique dans un fichier. Si la validation de votre sortie est en effet votre objectif, alors je vous suggère de

from xml.dom.minidom import parseString

doc = parseString("""<html>
    <head>
        <script type="text/javascript">
            var a = 'I love &amp;aacute; letters'
        </script>
    </head>
    <body>
        <h1>And I like the fact that 3 &gt; 1</h1>
    </body>
    </html>""")

with open("foo.xhtml", "w") as f:
    f.write( doc.toxml() )

Cela vous permet de vous écrire juste le XML que vous voulez à la sortie, s'assurer qu'il est correct (depuis parseString va lever une exception si c'est non valide) et votre code look beaucoup plus agréable.

Sans doute vous ne vous contentez pas d'écrire le même XML statiques chaque fois et que certains de substitution. Dans ce cas j'aurais des lignes comme

var a = '%(message)s'

et puis utiliser l'opérateur % à faire de la substitution, comme

</html>""" % {"message": "I love &amp;aacute; letters"})

7voto

Mikhail Korobov Points 6225

https://github.com/galvez/xmlwitch:

import xmlwitch
xml = xmlwitch.Builder(version='1.0', encoding='utf-8')
with xml.feed(xmlns='http://www.w3.org/2005/Atom'):
    xml.title('Example Feed')
    xml.updated('2003-12-13T18:30:02Z')
    with xml.author:
        xml.name('John Doe')
    xml.id('urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6')
    with xml.entry:
        xml.title('Atom-Powered Robots Run Amok')
        xml.id('urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a')
        xml.updated('2003-12-13T18:30:02Z')
        xml.summary('Some text.')
print(xml)

4voto

Daren Thomas Points 26812

ne vous voulez vraiment quelque chose comme:

html(head(script(type='text/javascript', content='var a = ...')),
body(h1('And I like the fact that 3 < 1'), p('just some paragraph'))

Je pense que j'ai vu quelque chose comme ça, quelque part. Ce serait merveilleux.

EDIT: en Fait, je suis allé et a écrit une bibliothèque aujourd'hui pour faire juste cela: magictree

Vous pouvez l'utiliser comme ceci:

from magictree import html, head, script, body, h1, p
root = html(
         head(
           script('''var a = 'I love &amp;aacute; letters''', 
                  type='text/javascript')),
         body(
           h1('And I like the fact that 3 > 1')))

# root is a plain Element object, like those created with ET.Element...
# so you can write it out using ElementTree :)
tree = ET.ElementTree(root)
tree.write('foo.xhtml')

La magie, en magictree réside dans la façon dont l'importation d'œuvres: L' Element des usines sont créées en cas de besoin. Ont un look à la source, il est basé sur une réponse à un autre StackOverflow question.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X