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) -> DtdContent | None:
            """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 attributes.copy():
                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
--- | ---
`DtdContent | None` | 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) -> DtdContent | None:
        """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 attributes.copy():
            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