4. XML, XSLT, XPath

4.1. xml module from standard library

Listing 226. xml module from standard library
from xml.etree.ElementTree import parse


FILE = r'../serialization/data/xml-commands.xml'
# <execute>
#     <command timeout="2">/bin/ls -la /etc/</command>
#     <command>/bin/ls -l /home/ /tmp/</command>
#     <command timeout="1">/bin/sleep 2</command>
#     <command timeout="2">/bin/echo 'juz wstalem'</command>
# </execute>

root = parse(FILE).getroot()

for command in root.findall('./command'):
    print(command.tag)
    print(command.text)
    print(command.attrib)
    print()

# command
# /bin/ls -la /etc/
# {'timeout': '2'}
#
# command
# /bin/ls -l /home/ /tmp/
# {}
#
# command
# /bin/sleep 2
# {'timeout': '1'}
#
# command
# /bin/echo 'juz wstalem'
# {'timeout': '2'}

4.2. lxml module

4.2.1. Creating elements

Listing 227. Creating elements
from lxml.etree import tostring, Element


root = Element("iris")

print(tostring(root))
# b'<iris/>'
Listing 228. Adding elements using list interface
from lxml.etree import tostring, Element


root = Element("iris")
root.append(Element("setosa"))
root.append(Element("versicolor"))
root.append(Element("virginica"))

print(tostring(root))
# b'<iris><setosa/><versicolor/><virginica/></iris>'

4.2.2. Length of a subtree

Listing 229. Length of a subtree
from lxml.etree import Element


root = Element("iris")
root.append(Element("setosa"))
root.append(Element("versicolor"))
root.append(Element("virginica"))

print(len(root))
# 3

4.2.3. Selecting subtree

Listing 230. Selecting subtree
from lxml.etree import Element


root = Element("iris")
root.append(Element("setosa"))
root.append(Element("versicolor"))
root.append(Element("virginica"))

selected = root[2]
print(selected.tag)
# virginica
Listing 231. Where is selected element
from lxml.etree import Element


root = Element("iris")
root.append(Element("setosa"))
root.append(Element("versicolor"))
root.append(Element("virginica"))

selected = root[1]
root.index(selected)
# 1

selected = root[2]
root.index(selected)
# 2

4.2.4. Element tree as a lists

Listing 232. Elements are lists
from lxml.etree import tostring, Element


root = Element("iris")
root.append(Element("setosa"))
root.append(Element("versicolor"))
root.append(Element("virginica"))

children = list(root)
print(children)
# [
#     <Element setosa at 0x113cd4048>,
#     <Element versicolor at 0x113cd4188>,
#     <Element virginica at 0x113cd41c8>
# ]
Listing 233. Iterating over elements
from lxml.etree import Element


root = Element("iris")
root.append(Element("setosa"))
root.append(Element("versicolor"))
root.append(Element("virginica"))

for child in root:
    print(child.tag)

# setosa
# versicolor
# virginica
Listing 234. Slicing elements
from lxml.etree import Element


root = Element("iris")
root.append(Element("setosa"))
root.append(Element("versicolor"))
root.append(Element("virginica"))

root.insert(0, Element("arctica"))

start = root[:1]
end = root[-1:]

print(start[0].tag)  # arctica
print(end[0].tag)    # virginica

4.2.5. Elements as a dict

Listing 235. Create element using dict interface
from lxml.etree import tostring, Element


tag = Element("iris", kingdom="plantae")

print(tostring(tag))
# b'<iris kingdom="plantae"/>'
Listing 236. Get element attributes and values
from lxml.etree import tostring, Element


tag = Element("iris", kingdom="plantae")

print(tag.get("kingdom"))          # plantae
print(tag.get("not-existing"))     # None
Listing 237. Set element attributes and values
from lxml.etree import tostring, Element


tag = Element("iris", kingdom="plantae")
tag.set("kind", "flower")

print(tag.get("kind"))
# flower

print(tostring(tag))
# b'<iris kingdom="plantae" kind="flower"/>'
Listing 238. Elements carry attributes as a dict
from lxml.etree import Element


tag = Element("iris", kingdom="plantae")
tag.set("kind", "flower")

tag.keys()
# ['kind', 'kingdom']

tag.values()
# ['plantae', 'flower']

tag.items()
# [('kingdom', 'plantae'), ('kind', 'flower')]
Listing 239. Iterating over element attributes and values
from lxml.etree import Element


tag = Element("iris", kingdom="plantae")
tag.set("kind", "flower")

for key, value in tag.items():
    print(f'{key} -> {value}')

# kingdom -> plantae
# kind -> flower
Listing 240. Elements carry attributes as a dict
from lxml.etree import Element


tag = Element("iris", kingdom="plantae")
tag.set("kind", "flower")

tag.attrib['kingdom']
# 'plantae'

tag.attrib['not-existing']
# KeyError: 'not-existing'

tag.attrib['species'] = 'Setosa'
tag.attrib.get('species')
# 'Setosa'

tag.attrib
# {'kingdom': 'plantae', 'kind': 'flower'}

tag.attrib.items()
# [('kingdom', 'plantae'), ('kind', 'flower'), ('species', 'Setosa')]

4.2.6. Elements contain text

from lxml.etree import tostring, Element

tag = Element("iris")
tag.text = "Setosa"

tag.text
# 'Setosa'

tostring(tag)
# b'<iris>Setosa</iris>'

4.2.7. Tree iteration

from lxml.etree import tostring, Element, SubElement

root = Element("iris")
SubElement(root, "species").text = "Setosa"
SubElement(root, "species").text = "Virginica"
SubElement(root, "flower").text = "Versicolor"

print(tostring(root, pretty_print=True))
# b'<iris>
#       <species>Setosa</species>
#       <species>Virginica</species>
#       <flower>Versicolor</flower>
# </iris>'


for element in root.iter():
    print(f'{element.tag} -> {element.text}')

# iris -> None
# species -> Setosa
# species -> Virginica
# flower -> Versicolor


for element in root.iter("species"):
    print(f'{element.tag} -> {element.text}')

# species -> Setosa
# species -> Virginica


for element in root.iter("species", "flower"):
    print(f'{element.tag} -> {element.text}')

# species -> Setosa
# species -> Virginica
# flower -> Versicolor

4.2.8. Entities

from lxml.etree import tostring, Element, SubElement, Entity

root = Element("iris")
print(tostring(root))
# b'<iris/>'

root.append(Entity("#234"))
print(tostring(root))
# b'<iris>&#234;</iris>'

4.2.9. Comments

from lxml.etree import tostring, Element, SubElement, Comment

root = Element("iris")
print(tostring(root))
# b'<iris/>'

root.append(Comment("Hello World"))
print(tostring(root))
# b'<iris><!--Hello World--></iris>'
from lxml.etree import tostring, Element, SubElement, Comment

root = Element("iris")
SubElement(root, "species").text = "Setosa"
SubElement(root, "species").text = "Virginica"
SubElement(root, "flower").text = "Versicolor"

print(tostring(root))
# b'<iris><species>Setosa</species><species>Virginica</species><flower>Versicolor</flower></iris>'

root.append(Entity("#234"))
print(tostring(root))
# b'<iris><species>Setosa</species><species>Virginica</species><flower>Versicolor</flower>&#234;</iris>'

root.append(Comment("Hello World"))
print(tostring(root))
# b'<iris><species>Setosa</species><species>Virginica</species><flower>Versicolor</flower>&#234;<!--Hello World--></iris>'


for element in root.iter():
    if isinstance(element.tag, str):
        print(f'TAG: {element.tag} -> {element.text}')
    else:
        print(f'SPECIAL: {element} -> {element.text}')

# TAG: iris -> None
# TAG: species -> Setosa
# TAG: species -> Virginica
# TAG: flower -> Versicolor
# SPECIAL: &#234; -> &#234;
# SPECIAL: <!--Hello World--> -> Hello World


for element in root.iter(tag=Element):
        print(f'{element.tag} -> {element.text}')

# iris -> None
# species -> Setosa
# species -> Virginica
# flower -> Versicolor


for element in root.iter(tag=Entity):
    print(element.text)

# &#234;


for element in root.iter(tag=Comment):
    print(element.text)

# Hello World

4.2.10. Serialization

>>> root = etree.XML('<root><a><b/></a></root>')

>>> etree.tostring(root)
b'<root><a><b/></a></root>'

>>> print(etree.tostring(root, xml_declaration=True))
<?xml version='1.0' encoding='ASCII'?>
<root><a><b/></a></root>

>>> print(etree.tostring(root, encoding='iso-8859-1'))
<?xml version='1.0' encoding='iso-8859-1'?>
<root><a><b/></a></root>

>>> print(etree.tostring(root, pretty_print=True))
<root>
  <a>
    <b/>
  </a>
</root>
>>> root = etree.XML(
...    '<html><head/><body><p>Hello<br/>World</p></body></html>')

>>> etree.tostring(root) # default: method = 'xml'
b'<html><head/><body><p>Hello<br/>World</p></body></html>'

>>> etree.tostring(root, method='xml') # same as above
b'<html><head/><body><p>Hello<br/>World</p></body></html>'

>>> etree.tostring(root, method='html')
b'<html><head></head><body><p>Hello<br>World</p></body></html>'

>>> print(etree.tostring(root, method='html', pretty_print=True))
<html>
<head></head>
<body><p>Hello<br>World</p></body>
</html>

>>> etree.tostring(root, method='text')
b'HelloWorld'

4.3. HTML

  • Using lxml module

<html><body>Iris<br/>Setosa</body></html>
from lxml.etree import tostring, Element, SubElement


html = Element("html")
body = SubElement(html, "body")

body.text = "Iris"
tostring(html)
# b'<html><body>Iris</body></html>'

br = SubElement(body, "br")
tostring(html)
# b'<html><body>Iris<br/></body></html>'

br.tail = "Setosa"
tostring(html)
# b'<html><body>Iris<br/>Setosa</body></html>'

4.4. XPATH

  • Using lxml module

>>> print(html.xpath("string()")) # lxml.etree only!
TEXTTAIL
>>> print(html.xpath("//text()")) # lxml.etree only!
['TEXT', 'TAIL']

4.5. XSLT

  • Using lxml module

4.5.1. Example 1

import io
from lxml import etree


XSLT = '''
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
    <foo><xsl:value-of select="/a/b/text()" /></foo>
    </xsl:template>
</xsl:stylesheet>
'''

xslt_root = etree.XML(XSLT)
transform = etree.XSLT(xslt_root)

f = io.StringIO('<a><b>Text</b></a>')
doc = etree.parse(f)
result_tree = transform(doc)

print(result_tree)

4.5.2. Example 2

<?xml version="1.0" encoding="UTF-8"?>
<CATALOG>
    <PLANT>
        <COMMON>Bloodroot</COMMON>
        <BOTANICAL>Sanguinaria canadensis</BOTANICAL>
        <ZONE>4</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>$2.44</PRICE>
        <AVAILABILITY>031599</AVAILABILITY>
    </PLANT>
</CATALOG>
<html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<style>
    body {font-family: Arial; font-size: 1em; background-color: #EEEEEE}
    div.title {background-color: teal; color: white; padding: 4px}
    div.description {margin-left:20px;margin-bottom:1em;font-size:10pt}
    span {font-weight: bold}

</style>

<body>

<xsl:for-each select="CATALOG/PLANT">
  <div class="title">
        <span><xsl:value-of select="BOTANICAL"/></span>
        <xsl:value-of select="PRICE"/>
    </div>

  <div class="description">
    <p>
        <xsl:value-of select="description"/>
        <span> (<xsl:value-of select="AVAILABILITY"/> will be available)</span>
    </p>
  </div>

</xsl:for-each>

4.6. Assignments

4.6.1. XML Parsing

  • Complexity level: easy

  • Lines of code to write: 20 lines

  • Estimated time of completion: 20 min

  • Filename: solution/xml_parse.py

English
  1. Convert input data to Python List[dict]

Polish
  1. Przekonwertuj dane wejściowe do Pythonowego List[dict]

Input
<?xml version="1.0" encoding="UTF-8"?>
<CATALOG>
    <PLANT>
        <COMMON>Bloodroot</COMMON>
        <BOTANICAL>Sanguinaria canadensis</BOTANICAL>
        <ZONE>4</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>$2.44</PRICE>
        <AVAILABILITY>031599</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Columbine</COMMON>
        <BOTANICAL>Aquilegia canadensis</BOTANICAL>
        <ZONE>3</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>$9.37</PRICE>
        <AVAILABILITY>030699</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Marsh Marigold</COMMON>
        <BOTANICAL>Caltha palustris</BOTANICAL>
        <ZONE>4</ZONE>
        <LIGHT>Mostly Sunny</LIGHT>
        <PRICE>$6.81</PRICE>
        <AVAILABILITY>051799</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Cowslip</COMMON>
        <BOTANICAL>Caltha palustris</BOTANICAL>
        <ZONE>4</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>$9.90</PRICE>
        <AVAILABILITY>030699</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Dutchman's-Breeches</COMMON>
        <BOTANICAL>Dicentra cucullaria</BOTANICAL>
        <ZONE>3</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>$6.44</PRICE>
        <AVAILABILITY>012099</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Ginger, Wild</COMMON>
        <BOTANICAL>Asarum canadense</BOTANICAL>
        <ZONE>3</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>$9.03</PRICE>
        <AVAILABILITY>041899</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Hepatica</COMMON>
        <BOTANICAL>Hepatica americana</BOTANICAL>
        <ZONE>4</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>$4.45</PRICE>
        <AVAILABILITY>012699</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Liverleaf</COMMON>
        <BOTANICAL>Hepatica americana</BOTANICAL>
        <ZONE>4</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>$3.99</PRICE>
        <AVAILABILITY>010299</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Jack-In-The-Pulpit</COMMON>
        <BOTANICAL>Arisaema triphyllum</BOTANICAL>
        <ZONE>4</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>$3.23</PRICE>
        <AVAILABILITY>020199</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Mayapple</COMMON>
        <BOTANICAL>Podophyllum peltatum</BOTANICAL>
        <ZONE>3</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>$2.98</PRICE>
        <AVAILABILITY>060599</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Phlox, Woodland</COMMON>
        <BOTANICAL>Phlox divaricata</BOTANICAL>
        <ZONE>3</ZONE>
        <LIGHT>Sun or Shade</LIGHT>
        <PRICE>$2.80</PRICE>
        <AVAILABILITY>012299</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Phlox, Blue</COMMON>
        <BOTANICAL>Phlox divaricata</BOTANICAL>
        <ZONE>3</ZONE>
        <LIGHT>Sun or Shade</LIGHT>
        <PRICE>$5.59</PRICE>
        <AVAILABILITY>021699</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Spring-Beauty</COMMON>
        <BOTANICAL>Claytonia Virginica</BOTANICAL>
        <ZONE>7</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>$6.59</PRICE>
        <AVAILABILITY>020199</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Trillium</COMMON>
        <BOTANICAL>Trillium grandiflorum</BOTANICAL>
        <ZONE>5</ZONE>
        <LIGHT>Sun or Shade</LIGHT>
        <PRICE>$3.90</PRICE>
        <AVAILABILITY>042999</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Wake Robin</COMMON>
        <BOTANICAL>Trillium grandiflorum</BOTANICAL>
        <ZONE>5</ZONE>
        <LIGHT>Sun or Shade</LIGHT>
        <PRICE>$3.20</PRICE>
        <AVAILABILITY>022199</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Violet, Dog-Tooth</COMMON>
        <BOTANICAL>Erythronium americanum</BOTANICAL>
        <ZONE>4</ZONE>
        <LIGHT>Shade</LIGHT>
        <PRICE>$9.04</PRICE>
        <AVAILABILITY>020199</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Trout Lily</COMMON>
        <BOTANICAL>Erythronium americanum</BOTANICAL>
        <ZONE>4</ZONE>
        <LIGHT>Shade</LIGHT>
        <PRICE>$6.94</PRICE>
        <AVAILABILITY>032499</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Adder's-Tongue</COMMON>
        <BOTANICAL>Erythronium americanum</BOTANICAL>
        <ZONE>4</ZONE>
        <LIGHT>Shade</LIGHT>
        <PRICE>$9.58</PRICE>
        <AVAILABILITY>041399</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Anemone</COMMON>
        <BOTANICAL>Anemone blanda</BOTANICAL>
        <ZONE>6</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>$8.86</PRICE>
        <AVAILABILITY>122698</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Grecian Windflower</COMMON>
        <BOTANICAL>Anemone blanda</BOTANICAL>
        <ZONE>6</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>$9.16</PRICE>
        <AVAILABILITY>071099</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Bee Balm</COMMON>
        <BOTANICAL>Monarda didyma</BOTANICAL>
        <ZONE>4</ZONE>
        <LIGHT>Shade</LIGHT>
        <PRICE>$4.59</PRICE>
        <AVAILABILITY>050399</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Bergamot</COMMON>
        <BOTANICAL>Monarda didyma</BOTANICAL>
        <ZONE>4</ZONE>
        <LIGHT>Shade</LIGHT>
        <PRICE>$7.16</PRICE>
        <AVAILABILITY>042799</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Black-Eyed Susan</COMMON>
        <BOTANICAL>Rudbeckia hirta</BOTANICAL>
        <ZONE>Annual</ZONE>
        <LIGHT>Sunny</LIGHT>
        <PRICE>$9.80</PRICE>
        <AVAILABILITY>061899</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Buttercup</COMMON>
        <BOTANICAL>Ranunculus</BOTANICAL>
        <ZONE>4</ZONE>
        <LIGHT>Shade</LIGHT>
        <PRICE>$2.57</PRICE>
        <AVAILABILITY>061099</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Crowfoot</COMMON>
        <BOTANICAL>Ranunculus</BOTANICAL>
        <ZONE>4</ZONE>
        <LIGHT>Shade</LIGHT>
        <PRICE>$9.34</PRICE>
        <AVAILABILITY>040399</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Butterfly Weed</COMMON>
        <BOTANICAL>Asclepias tuberosa</BOTANICAL>
        <ZONE>Annual</ZONE>
        <LIGHT>Sunny</LIGHT>
        <PRICE>$2.78</PRICE>
        <AVAILABILITY>063099</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Cinquefoil</COMMON>
        <BOTANICAL>Potentilla</BOTANICAL>
        <ZONE>Annual</ZONE>
        <LIGHT>Shade</LIGHT>
        <PRICE>$7.06</PRICE>
        <AVAILABILITY>052599</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Primrose</COMMON>
        <BOTANICAL>Oenothera</BOTANICAL>
        <ZONE>3 - 5</ZONE>
        <LIGHT>Sunny</LIGHT>
        <PRICE>$6.56</PRICE>
        <AVAILABILITY>013099</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Gentian</COMMON>
        <BOTANICAL>Gentiana</BOTANICAL>
        <ZONE>4</ZONE>
        <LIGHT>Sun or Shade</LIGHT>
        <PRICE>$7.81</PRICE>
        <AVAILABILITY>051899</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Blue Gentian</COMMON>
        <BOTANICAL>Gentiana</BOTANICAL>
        <ZONE>4</ZONE>
        <LIGHT>Sun or Shade</LIGHT>
        <PRICE>$8.56</PRICE>
        <AVAILABILITY>050299</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Jacob's Ladder</COMMON>
        <BOTANICAL>Polemonium caeruleum</BOTANICAL>
        <ZONE>Annual</ZONE>
        <LIGHT>Shade</LIGHT>
        <PRICE>$9.26</PRICE>
        <AVAILABILITY>022199</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Greek Valerian</COMMON>
        <BOTANICAL>Polemonium caeruleum</BOTANICAL>
        <ZONE>Annual</ZONE>
        <LIGHT>Shade</LIGHT>
        <PRICE>$4.36</PRICE>
        <AVAILABILITY>071499</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>California Poppy</COMMON>
        <BOTANICAL>Eschscholzia californica</BOTANICAL>
        <ZONE>Annual</ZONE>
        <LIGHT>Sun</LIGHT>
        <PRICE>$7.89</PRICE>
        <AVAILABILITY>032799</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Shooting Star</COMMON>
        <BOTANICAL>Dodecatheon</BOTANICAL>
        <ZONE>Annual</ZONE>
        <LIGHT>Mostly Shady</LIGHT>
        <PRICE>$8.60</PRICE>
        <AVAILABILITY>051399</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Snakeroot</COMMON>
        <BOTANICAL>Cimicifuga</BOTANICAL>
        <ZONE>Annual</ZONE>
        <LIGHT>Shade</LIGHT>
        <PRICE>$5.63</PRICE>
        <AVAILABILITY>071199</AVAILABILITY>
    </PLANT>
    <PLANT>
        <COMMON>Cardinal Flower</COMMON>
        <BOTANICAL>Lobelia cardinalis</BOTANICAL>
        <ZONE>2</ZONE>
        <LIGHT>Shade</LIGHT>
        <PRICE>$3.02</PRICE>
        <AVAILABILITY>022299</AVAILABILITY>
    </PLANT>
</CATALOG>

4.6.2. XSLT Transformation

  • Complexity level: medium

  • Lines of code to write: 5 lines

  • Estimated time of completion: 10 min

  • Filename: solution/xml_xslt.py

English
  1. Convert input data to Python List[dict]

Polish
  1. Przekonwertuj dane wejściowe do Pythonowego List[dict]

Input
<?xml version="1.0" encoding="UTF-8"?>
<breakfast_menu>

    <food>
        <name>Belgian Waffles</name>
        <price>$5.95</price>
        <description>Two of our famous Belgian Waffles with plenty of real maple syrup</description>
        <calories>650</calories>
    </food>

    <food>
        <name>Strawberry Belgian Waffles</name>
        <price>$7.95</price>
        <description>Light Belgian waffles covered with strawberries and whipped cream</description>
        <calories>900</calories>
    </food>

    <food>
        <name>Berry-Berry Belgian Waffles</name>
        <price>$8.95</price>
        <description>Light Belgian waffles covered with an assortment of fresh berries and whipped cream</description>
        <calories>900</calories>
    </food>

    <food>
        <name>French Toast</name>
        <price>$4.50</price>
        <description>Thick slices made from our homemade sourdough bread</description>
        <calories>600</calories>
    </food>

    <food>
        <name>Homestyle Breakfast</name>
        <price>$6.95</price>
        <description>Two eggs, bacon or sausage, toast, and our ever-popular hash browns</description>
        <calories>950</calories>
    </food>

</breakfast_menu>