Extension: XML

The xml extension supplies classes for interacting with data from xml.etree.ElementTree

Examples will share a root data object. To load, copy and paste the following:

from xml.etree.ElementTree import fromstring

xml_raw = (
    '<root>'
        '<a one="1" two="2"/>'
        '<b three="3" four="4">'
            '<listed>one</listed>'
            '<listed>two</listed>'
            '<listed>three</listed>'
        '</b>'
    '</root>'
)
root = fromstring(xml_raw)

XElm Bearing Type

class gemma.extensions.xml.XElm(name, factory=None)[source]
__init__(name, factory=None)[source]

Fetches and places xml.etree.ElementTree.Element objects from / on parent Elements.

Parameters
  • name (Union[str, Tuple[str, Union[int, slice]], BearingAbstract]) – tag name, index of Element

  • factory (Optional[Type[~FactoryType]]) – Type for filling empty bearings during a place.

fetch(target)[source]

Fetches xml.etree.ElementTree.Element from target

Parameters

target (Element) – Element to fetch from.

Return type

Union[Element, List[Element]]

Returns

Element with matching name

Equivalent to target.findall(self.tag)[self.index]

Example:
>>> elm_fetcher = XElm("a")
>>> fetched = elm_fetcher.fetch(root)
>>> fetched.tag
'a'
>>> fetched.attrib
{'one': '1', 'two': '2'}
property index
Return type

Union[int, slice]

Returns

index of element (defaults to “0”)

init_factory()[source]

As BearingAbstract.init_factory(), but will return xml elements with BearingAbstract.name() loaded as tag name.

Return type

~FactoryType

Returns

initialized type.

classmethod name_from_str(text)[source]

Tag and index (if present).

Parameters

text (str) – text to be converted

Return type

Tuple[str, Union[int, slice]]

Returns

name, index

Allowed conventions:

  • <name>

  • <name, 0>

  • <name, 1:4>

If no index is passed, 0 will be assumed.

place(target, value, **kwargs)[source]

Inserts value on target

Parameters
  • target (Element) – Element to fetch from.

  • value (Element) – to insert

Return type

None

Returns

None

Equivalent to target.insert(self.index, self.tag)

Example:
>>> elm_placer = XElm(("b", 0))
>>> elm_placer.place(root, Element("new node"))
>>> from xml.etree.ElementTree import tostring
>>> print(tostring(root))
'<root>...<b four="4" three="3">/...<new node /></root>'
property tag
Return type

str

Returns

tag name of element

XCourse

Simple subclass of Course that adds XElm to the list of auto-cast functions.

Like Course / gemma.PORT, XCourse has a shorter, initialized alias called XPATH.

class gemma.extensions.xml.XCourse(*bearings)[source]
Example XCourse.fetch()
>>> from gemma.extensions.xml import XCourse, XPath
>>>
>>> to_fetch = XCourse() / "<b>" / "<listed, -1>"
>>> fetched = to_fetch.fetch(root)
>>> fetched, fetched.text
(<Element 'listed' at 0x10b6d7c78>, 'three')
Example XCourse.place()
>>> to_place = XPath / "<b>" / "<listed, -1>" / "text"
>>> to_place.place(root, "changed value")
>>> print(tostring(root))
b'<root>...<b four="4" three="3">...<listed>changed value</listed></b></root>'

XCompass

class gemma.extensions.xml.XCompass(elms=True)[source]

Restricted compass for xml.etree.ElementTree.Element objects.

Returns all child elements as (XElm), value pairs.

Returned Attr bearings: .text, .attrib by default.

Members

Example
>>> from gemma.extensions.xml import XCompass
>>>
>>> for this_bearing, value in XCompass().bearings_iter(root):
...     print(repr(this_bearing), value)
...
<Attr: 'text'> None
<Attr: 'attrib'> {}
<XElm: ('a', 0)> <Element 'a' at 0x10b6d7ae8>
<XElm: ('b', 0)> <Element 'b' at 0x10b6d7b88>

xsurveyor

xsurveyor is an instance of Surveyor with XCompass added to its compasses and XCourse as its course type.

Example
>>> from gemma.extensions.xml import xsurveyor
>>>
>>> for course, value in xsurveyor.chart_iter(root):
...     print(repr(course), value)
...
<Course: <Attr: 'text'>> None
<Course: <Attr: 'attrib'>> {}
<Course: <XElm: ('a', 0)>> <Element 'a' at 0x104626688>
<Course: <XElm: ('a', 0)> / <Attr: 'text'>> None
<Course: <XElm: ('a', 0)> / <Attr: 'attrib'>> {'one': '1', 'two': '2'}
<Course: <XElm: ('a', 0)> / <Attr: 'attrib'> / <Item: 'one'>> 1
<Course: <XElm: ('a', 0)> / <Attr: 'attrib'> / <Item: 'two'>> 2
<Course: <XElm: ('b', 0)>> <Element 'b' at 0x104639f48>
<Course: <XElm: ('b', 0)> / <Attr: 'text'>> None
<Course: <XElm: ('b', 0)> / <Attr: 'attrib'>> {'three': '3', 'four': '4'}
<Course: <XElm: ('b', 0)> / <Attr: 'attrib'> / <Item: 'three'>> 3
<Course: <XElm: ('b', 0)> / <Attr: 'attrib'> / <Item: 'four'>> 4
<Course: <XElm: ('b', 0)> / <XElm: ('listed', 0)>> <Element 'listed' at 0x104639f98>
<Course: <XElm: ('b', 0)> / <XElm: ('listed', 0)> / <Attr: 'text'>> one
<Course: <XElm: ('b', 0)> / <XElm: ('listed', 0)> / <Attr: 'attrib'>> {}
<Course: <XElm: ('b', 0)> / <XElm: ('listed', 1)>> <Element 'listed' at 0x10464c638>
<Course: <XElm: ('b', 0)> / <XElm: ('listed', 1)> / <Attr: 'text'>> two
<Course: <XElm: ('b', 0)> / <XElm: ('listed', 1)> / <Attr: 'attrib'>> {}
<Course: <XElm: ('b', 0)> / <XElm: ('listed', 2)>> <Element 'listed' at 0x10464c688>
<Course: <XElm: ('b', 0)> / <XElm: ('listed', 2)> / <Attr: 'text'>> three
<Course: <XElm: ('b', 0)> / <XElm: ('listed', 2)> / <Attr: 'attrib'>> {}

Cartography

Mapping is done through the regular Cartographer class.

Example
>>> from gemma import Cartographer, Coordinate
>>> from gemma.extensions.xml import XPATH
>>>
... def explode_listed(listed_elements, coord, cache):
...     return [x.text for x in listed_elements]
>>>
>>> coords = [
...     Coordinate(org=XPATH / "a" / "attrib" / "one", dst=XPATH / "a.one"),
...     Coordinate(org=XPATH / "a" / "attrib" / "two", dst=XPATH / "a.two"),
...     Coordinate(org=XPATH / "b" / "attrib" / "three", dst=XPATH / "b.three"),
...     Coordinate(org=XPATH / "b" / "attrib" / "four", dst=XPATH / "b.four"),
...     Coordinate(
...         org=XPATH / "b" / "<listed, 0:>",
...         dst=XPATH / "b.listed",
...         clean_value=explode_listed
...     ),
... ]
>>>
>>> destination = dict()
>>>
>>> Cartographer().map(root, destination, coords)
>>> for key, value in destination.items():
...     print(f"{key}: {value}")
...
a.one: 1
a.two: 2
b.three: 3
b.four: 4
b.listed: ['one', 'two', 'three']