Skip to content

dtd

xsdata.codegen.parsers.dtd

DtdParser

Document type definition parser.

The parser requires lxml package to be installed.

Source code in xsdata/codegen/parsers/dtd.py
 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
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
class DtdParser:
    """Document type definition parser.

    The parser requires lxml package to be installed.
    """

    @classmethod
    def parse(cls, source: bytes, location: str) -> Dtd:
        """Parse the input source bytes object into a dtd instance.

        Args:
            source: The source bytes object to parse
            location: The source location uri

        Returns:
            A dtd instance representing the parsed content.
        """
        try:
            from lxml import etree

            dtd = etree.DTD(io.BytesIO(source))
        except ImportError:
            raise ParserError("DtdParser requires lxml to run.")

        elements = list(map(cls.build_element, dtd.iterelements()))
        return Dtd(elements=elements, location=location)

    @classmethod
    def build_element(cls, element: Any) -> DtdElement:
        """Build a dtd element from the lxml element.

        Args:
            element: The lxml dtd element instance

        Returns:
            The converted xsdata dtd element instance.
        """
        content = cls.build_content(element.content)
        attributes = list(map(cls.build_attribute, element.iterattributes()))
        ns_map = cls.build_ns_map(element.prefix, attributes)
        return DtdElement(
            name=element.name,
            prefix=element.prefix,
            type=DtdElementType(element.type),
            content=content,
            attributes=attributes,
            ns_map=ns_map,
        )

    @classmethod
    def build_content(cls, content: Any) -> Optional[DtdContent]:
        """Build a dtd content instance from the lxml content.

        Args:
            content: The lxml content instance

        Returns:
            The converted xsdata dtd content instance, or None if the content is empty.
        """
        if not content:
            return None

        return DtdContent(
            name=content.name,
            occur=DtdContentOccur(content.occur),
            type=DtdContentType(content.type),
            left=cls.build_content(content.left),
            right=cls.build_content(content.right),
        )

    @classmethod
    def build_attribute(cls, attribute: Any) -> DtdAttribute:
        """Build a dtd attribute instance from the lxml instance.

        Args:
            attribute: The lxml attribute instance

        Returns:
            The converted xsdata dtd attribute instance.
        """
        return DtdAttribute(
            prefix=attribute.prefix,
            name=attribute.name,
            type=DtdAttributeType(attribute.type),
            default=DtdAttributeDefault(attribute.default),
            default_value=attribute.default_value,
            values=attribute.values(),
        )

    @classmethod
    def build_ns_map(cls, prefix: str, attributes: List[DtdAttribute]) -> Dict:
        """Build the dtd element namespace prefix-URI map.

        It also adds common namespaces like xs, xsi, xlink and xml.

        Args:
            prefix: The element namespace prefix
            attributes: Element attributes, to extract any xmlns keys

        Returns:
            The element namespace prefix-URI map.
        """
        ns_map = {ns.prefix: ns.uri for ns in Namespace.common()}

        for attribute in list(attributes):
            if not attribute.default_value:
                continue

            if attribute.prefix == "xmlns":
                ns_map[attribute.name] = attribute.default_value
                attributes.remove(attribute)
            elif attribute.name == "xmlns":
                ns_map[prefix] = attribute.default_value
                attributes.remove(attribute)

        return ns_map

parse(source, location) classmethod

Parse the input source bytes object into a dtd instance.

Parameters:

Name Type Description Default
source bytes

The source bytes object to parse

required
location str

The source location uri

required

Returns:

Type Description
Dtd

A dtd instance representing the parsed content.

Source code in xsdata/codegen/parsers/dtd.py
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
@classmethod
def parse(cls, source: bytes, location: str) -> Dtd:
    """Parse the input source bytes object into a dtd instance.

    Args:
        source: The source bytes object to parse
        location: The source location uri

    Returns:
        A dtd instance representing the parsed content.
    """
    try:
        from lxml import etree

        dtd = etree.DTD(io.BytesIO(source))
    except ImportError:
        raise ParserError("DtdParser requires lxml to run.")

    elements = list(map(cls.build_element, dtd.iterelements()))
    return Dtd(elements=elements, location=location)

build_element(element) classmethod

Build a dtd element from the lxml element.

Parameters:

Name Type Description Default
element Any

The lxml dtd element instance

required

Returns:

Type Description
DtdElement

The converted xsdata dtd element instance.

Source code in xsdata/codegen/parsers/dtd.py
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
@classmethod
def build_element(cls, element: Any) -> DtdElement:
    """Build a dtd element from the lxml element.

    Args:
        element: The lxml dtd element instance

    Returns:
        The converted xsdata dtd element instance.
    """
    content = cls.build_content(element.content)
    attributes = list(map(cls.build_attribute, element.iterattributes()))
    ns_map = cls.build_ns_map(element.prefix, attributes)
    return DtdElement(
        name=element.name,
        prefix=element.prefix,
        type=DtdElementType(element.type),
        content=content,
        attributes=attributes,
        ns_map=ns_map,
    )

build_content(content) classmethod

Build a dtd content instance from the lxml content.

Parameters:

Name Type Description Default
content Any

The lxml content instance

required

Returns:

Type Description
Optional[DtdContent]

The converted xsdata dtd content instance, or None if the content is empty.

Source code in xsdata/codegen/parsers/dtd.py
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
@classmethod
def build_content(cls, content: Any) -> Optional[DtdContent]:
    """Build a dtd content instance from the lxml content.

    Args:
        content: The lxml content instance

    Returns:
        The converted xsdata dtd content instance, or None if the content is empty.
    """
    if not content:
        return None

    return DtdContent(
        name=content.name,
        occur=DtdContentOccur(content.occur),
        type=DtdContentType(content.type),
        left=cls.build_content(content.left),
        right=cls.build_content(content.right),
    )

build_attribute(attribute) classmethod

Build a dtd attribute instance from the lxml instance.

Parameters:

Name Type Description Default
attribute Any

The lxml attribute instance

required

Returns:

Type Description
DtdAttribute

The converted xsdata dtd attribute instance.

Source code in xsdata/codegen/parsers/dtd.py
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
@classmethod
def build_attribute(cls, attribute: Any) -> DtdAttribute:
    """Build a dtd attribute instance from the lxml instance.

    Args:
        attribute: The lxml attribute instance

    Returns:
        The converted xsdata dtd attribute instance.
    """
    return DtdAttribute(
        prefix=attribute.prefix,
        name=attribute.name,
        type=DtdAttributeType(attribute.type),
        default=DtdAttributeDefault(attribute.default),
        default_value=attribute.default_value,
        values=attribute.values(),
    )

build_ns_map(prefix, attributes) classmethod

Build the dtd element namespace prefix-URI map.

It also adds common namespaces like xs, xsi, xlink and xml.

Parameters:

Name Type Description Default
prefix str

The element namespace prefix

required
attributes List[DtdAttribute]

Element attributes, to extract any xmlns keys

required

Returns:

Type Description
Dict

The element namespace prefix-URI map.

Source code in xsdata/codegen/parsers/dtd.py
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
@classmethod
def build_ns_map(cls, prefix: str, attributes: List[DtdAttribute]) -> Dict:
    """Build the dtd element namespace prefix-URI map.

    It also adds common namespaces like xs, xsi, xlink and xml.

    Args:
        prefix: The element namespace prefix
        attributes: Element attributes, to extract any xmlns keys

    Returns:
        The element namespace prefix-URI map.
    """
    ns_map = {ns.prefix: ns.uri for ns in Namespace.common()}

    for attribute in list(attributes):
        if not attribute.default_value:
            continue

        if attribute.prefix == "xmlns":
            ns_map[attribute.name] = attribute.default_value
            attributes.remove(attribute)
        elif attribute.name == "xmlns":
            ns_map[prefix] = attribute.default_value
            attributes.remove(attribute)

    return ns_map