File: xmlbuilder.py

package info (click to toggle)
python-osmapi 5.0.0%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 848 kB
  • sloc: python: 4,113; xml: 1,599; makefile: 46; sh: 14
file content (77 lines) | stat: -rw-r--r-- 2,254 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
from typing import Any, Optional, TYPE_CHECKING
from xml.dom.minidom import Element

if TYPE_CHECKING:
    from .OsmApi import OsmApi


def _xml_build(  # noqa: C901
    element_type: str,
    element_data: dict[str, Any],
    with_headers: bool = True,
    *,
    data: "OsmApi",
) -> bytes:
    xml = ""
    if with_headers:
        xml += '<?xml version="1.0" encoding="UTF-8"?>\n'
        xml += '<osm version="0.6" generator="'
        xml += data._created_by + '">'
        xml += "\n"

    # <element attr="val">
    xml += "  <" + element_type
    if "id" in element_data:
        xml += ' id="' + str(element_data["id"]) + '"'
    if "lat" in element_data:
        xml += ' lat="' + str(element_data["lat"]) + '"'
    if "lon" in element_data:
        xml += ' lon="' + str(element_data["lon"]) + '"'
    if "version" in element_data:
        xml += ' version="' + str(element_data["version"]) + '"'
    visible_str = str(element_data.get("visible", True)).lower()
    xml += ' visible="' + visible_str + '"'
    if element_type in ["node", "way", "relation"]:
        xml += ' changeset="' + str(data._current_changeset_id) + '"'
    xml += ">\n"

    # <tag... />
    for k, v in element_data.get("tag", {}).items():
        xml += '    <tag k="' + _xml_encode(k)
        xml += '" v="' + _xml_encode(v) + '"/>\n'

    # <member... />
    for member in element_data.get("member", []):
        xml += '    <member type="' + member["type"]
        xml += '" ref="' + str(member["ref"])
        xml += '" role="' + _xml_encode(member["role"])
        xml += '"/>\n'

    # <nd... />
    for ref in element_data.get("nd", []):
        xml += '    <nd ref="' + str(ref) + '"/>\n'

    # </element>
    xml += "  </" + element_type + ">\n"

    if with_headers:
        xml += "</osm>\n"

    return xml.encode("utf8")


def _xml_encode(text: str) -> str:
    return (
        text.replace("&", "&amp;")
        .replace('"', "&quot;")
        .replace("<", "&lt;")
        .replace(">", "&gt;")
    )


def _get_xml_value(dom_element: Element, tag: str) -> Optional[str]:
    try:
        elem = dom_element.getElementsByTagName(tag)[0]
        return elem.firstChild.nodeValue  # type: ignore[union-attr]
    except Exception:
        return None