Example #1
0
 def __init__(self, value, max_length=None, validation_level=None):
     if validation_level is None:
         validation_level = get_default_validation_level()
     self.validation_level = validation_level
     self.max_length = max_length
     if Validator.is_strict(self.validation_level):
         if self.max_length is not None and len('{0}'.format(value)) > self.max_length:
             raise MaxLengthReached(value, self.max_length)
     self.value = value
Example #2
0
 def __init__(self, value, max_length=None, validation_level=None):
     if validation_level is None:
         validation_level = get_default_validation_level()
     self.validation_level = validation_level
     self.max_length = max_length
     if Validator.is_strict(self.validation_level):
         if self.max_length is not None and len('{0}'.format(value)) > self.max_length:
             raise MaxLengthReached(value, self.max_length)
     self.value = value
Example #3
0
def parse_component(text, name=None, datatype='ST', version=None, encoding_chars=None, validation_level=None, reference=None):
    """
    Parse the given ER7-encoded component and return an instance of :class:`hl7apy.core.Component`.

    :type text: ``basestring``
    :param text: the ER7-encoded string containing the components to be parsed
    :type name: ``basestring``
    :param name: the component's name (e.g. XPN_2)
    :type datatype: ``basestring``
    :param datatype: the datatype of the component (e.g. ST)
    :type version: ``basestring``
    :param version: the HL7 version (e.g. "2.5"), or ``None`` to use the default (see :func:`hl7apy.set_default_version`)
    :type encoding_chars: ``dict``
    :param encoding_chars: a dictionary containing the encoding chars or None to use the default (see :func:`hl7apy.set_default_encoding_chars`)
    :param validation_level: the validation level. Possible values are those defined in :class:`hl7apy.consts.VALIDATION_LEVEL` class or ``None`` to use the default validation level (see :func:`hl7apy.set_default_validation_level`)
    :type reference: ``dict``
    :param reference: a dictionary containing the element structure returned by :func:`hl7apy.load_reference` or :func:`hl7apy.find_reference`
    :return: an instance of :class:`hl7apy.core.Component`

    >>> component = "GATEWAY&1.3.6.1.4.1.21367.2011.2.5.17"
    >>> cx_4 = parse_component(component, name="CX_4")
    >>> print cx_4
    <Component CX_4 (ASSIGNING_AUTHORITY) of type None>
    >>> print cx_4.to_er7()
    GATEWAY&1.3.6.1.4.1.21367.2011.2.5.17
    >>> print parse_component(component)
    <Component ST (None) of type None>
    """
    version = _get_version(version)
    encoding_chars = _get_encoding_chars(encoding_chars)

    try:
        component = Component(name, datatype, version=version, validation_level=validation_level, reference=reference)
    except InvalidName as e:
        if Validator.is_strict(validation_level):
            raise e
        component = Component(datatype, version=version, validation_level=validation_level, reference=reference)
    children = parse_subcomponents(text, component.datatype, version, encoding_chars, validation_level)
    if Validator.is_quiet(component.validation_level) and is_base_datatype(component.datatype, version) and \
            len(children) > 1:
        component.datatype = None
    component.children = children
    return component
Example #4
0
def parse_field(text, name=None, version=None, encoding_chars=None, validation_level=None, reference=None, force_varies=False):
    """
    Parse the given ER7-encoded field and return an instance of :class:`hl7apy.core.Field`.

    :type text: ``basestring``
    :param text: the ER7-encoded string containing the fields to be parsed
    :type name: ``basestring``
    :param name: the field name (e.g. MSH_7)
    :type version: ``basestring``
    :param version: the HL7 version (e.g. "2.5"), or ``None`` to use the default (see :func:`hl7apy.set_default_version`)
    :type encoding_chars: ``dict``
    :param encoding_chars: a dictionary containing the encoding chars or None to use the default (see :func:`hl7apy.set_default_encoding_chars`)
    :param validation_level: the validation level. Possible values are those defined in :class:`hl7apy.consts.VALIDATION_LEVEL` class or ``None`` to use the default validation level (see :func:`hl7apy.set_default_validation_level`)
    :type reference: ``dict``
    :param reference: a dictionary containing the element structure returned by :func:`hl7apy.load_reference` or :func:`hl7apy.find_reference`
    :return: an instance of :class:`hl7apy.core.Field`

    >>> field = "NUCLEAR^NELDA^W"
    >>> nk1_2 = parse_field(field, name="NK1_2")
    >>> print nk1_2
    <Field NK1_2 (NAME) of type XPN>
    >>> print nk1_2.to_er7()
    NUCLEAR^NELDA^W
    >>> unknown = parse_field(field)
    >>> print unknown
    <Field of type None>
    >>> print unknown.to_er7()
    NUCLEAR^NELDA^W
    """
    version = _get_version(version)
    encoding_chars = _get_encoding_chars(encoding_chars)

    if force_varies:
        reference = ('leaf', 'varies', None, None)
    try:
        field = Field(name, version=version, validation_level=validation_level, reference=reference)
    except InvalidName:
        field = Field(version=version, validation_level=validation_level, reference=reference)
    if name in ('MSH_1', 'MSH_2'):
        s = SubComponent(datatype='ST', value=text)
        c = Component(datatype='ST')
        c.add(s)
        field.add(c)
    else:
        children = parse_components(text, field.datatype, version, encoding_chars, validation_level)
        if Validator.is_quiet(validation_level) and is_base_datatype(field.datatype, version) and \
                len(children) > 1:
            field.datatype = None
        field.children = children
    return field
Example #5
0
def parse_message(message, validation_level=None, find_groups=True, reference=None):
    """
    Parse the given ER7-encoded message and return an instance of :class:`hl7apy.core.Message`.

    :type message: ``basestring``
    :param message: the ER7-encoded message to be parsed
    :param validation_level: the validation level. Possible values are those defined in :class:`hl7apy.consts.VALIDATION_LEVEL` class or ``None`` to use the default validation level (see :func:`hl7apy.set_default_validation_level`)
    :type find_groups: ``bool``
    :param find_groups: if ``True``, automatically assign the segments found to the appropriate :class:`hl7apy.core.Group` instances. If ``False``, the segments found are assigned as children of the :class:`hl7apy.core.Message` instance
    :return: an instance of :class:`hl7apy.core.Message`

    >>> message = "MSH|^~\&|GHH_ADT||||20080115153000||OML^O33^OML_O33|0123456789|P|2.5||||AL\\rPID|1||566-554-3423^^^GHH^MR||EVERYMAN^ADAM^A|||M|||2222 HOME STREET^^ANN ARBOR^MI^^USA||555-555-2004|||M\\r"
    >>> m = parse_message(message)
    >>> print m
    <Message OML_O33>
    >>> print m.msh.sending_application.to_er7()
    GHH_ADT
    >>> print m.children
    [<Segment MSH>, <Group OML_O33_PATIENT>]
    """
    message = message.lstrip()
    encoding_chars, message_structure, version = get_message_info(message)

    try:
        m = Message(name=message_structure, version=version, validation_level=validation_level, encoding_chars=encoding_chars)
    except InvalidName:
        m = Message(version=version, validation_level=validation_level, encoding_chars=encoding_chars)
    children = parse_segments(message, m.version, encoding_chars, validation_level)
    if m.name is not None and find_groups:
        m.children = []
        create_groups(m, children, validation_level)
    else:
        m.children = children
    if Validator.is_strict(validation_level):
        m.validate()
    return m
Example #6
0
def datatype_factory(datatype, value, version=None, validation_level=None):
    """
    Factory function for both base and complex datatypes. It generates the correct object according
    to the datatype in input.
    It should be noted that if you use the factory it is not possible to specify
    some parameters for the datatype (e.g. the format for datetime base datatypes)
    If the value is not valid for the datatype specified if the ``validation_level`` is
    :attr:`hl7apy.consts.VALIDATION_LEVEL.TOLERANT` it generates an :class:`hl7apy.base_datatypes.ST` object

    :type datatype: ``str``
    :param datatype: The datatype to be generated

    :param value: The value of the datatype

    :type version: ``str``
    :param version: A valid HL7 version. It must be one of
        :attr:`SUPPRTED_LIBRARIES <hl7apy.SUPPORTED_LIBRARIES>`

    :type validation_level: ``int``
    :param validation_level: It must be a value from class :attr:`validation_level`
        :class:`VALIDATION_LEVEL hl7apy.consts.VALIDATION_LEVEL` or ``None`` to use the default value

    :rtype: The type specified in datatype

    :raises :exc:`ValueError`: If the ``validation_level`` is
        :attr:`VALIDATION_LEVEL.STRICT <hl7apy.consts.VALIDATION_LEVEL.STRICT>`
     and the value is not valid for the specified datatype

    :raises :exc:`InvalidDatatype <hl7apy.exceptions.InvalidDatatype>`: If the ``datatype`` specified is not
        valid for the given ``version``

    """

    from hl7apy.validation import Validator

    if validation_level is None:
        validation_level = get_default_validation_level()

    if version is None:
        version = get_default_version()

    lib = load_library(version)

    base_datatypes = lib.get_base_datatypes()

    factories = base_datatypes.copy()

    if 'DT' in factories:
        factories['DT'] = date_factory
    if 'TM' in factories:
        factories['TM'] = timestamp_factory
    if 'DTM' in factories:
        factories['DTM'] = datetime_factory
    if 'NM' in factories:
        factories['NM'] = numeric_factory
    if 'SI' in factories:
        factories['SI'] = sequence_id_factory

    try:
        factory = factories[datatype]
        if isinstance(factory, FunctionType):
            return factory(value,
                           base_datatypes[datatype],
                           validation_level=validation_level)
        return factory(value, validation_level=validation_level)
    except KeyError:
        raise InvalidDataType(datatype)
    except ValueError as e:
        if Validator.is_strict(validation_level):
            raise e
        # TODO: Do we really want this? In that case the parent's datatype must be changed accordingly
        return factories['ST'](value)
Example #7
0
def datatype_factory(datatype, value, version=None, validation_level=None):
    """
    Factory function for both base and complex datatypes. It generates the correct object according
    to the datatype in input.
    It should be noted that if you use the factory it is not possible to specify
    some parameters for the datatype (e.g. the format for datetime base datatypes)
    If the value is not valid for the datatype specified if the ``validation_level`` is
    :attr:`hl7apy.consts.VALIDATION_LEVEL.TOLERANT` it generates an :class:`hl7apy.base_datatypes.ST` object

    :type datatype: ``str``
    :param datatype: The datatype to be generated

    :param value: The value of the datatype

    :type version: ``str``
    :param version: A valid HL7 version. It must be one of
        :attr:`SUPPRTED_LIBRARIES <hl7apy.SUPPORTED_LIBRARIES>`

    :type validation_level: ``int``
    :param validation_level: It must be a value from class :attr:`validation_level`
        :class:`VALIDATION_LEVEL hl7apy.consts.VALIDATION_LEVEL` or ``None`` to use the default value

    :rtype: The type specified in datatype

    :raises :exc:`ValueError`: If the ``validation_level`` is
        :attr:`VALIDATION_LEVEL.STRICT <hl7apy.consts.VALIDATION_LEVEL.STRICT>`
     and the value is not valid for the specified datatype

    :raises :exc:`InvalidDatatype <hl7apy.exceptions.InvalidDatatype>`: If the ``datatype`` specified is not
        valid for the given ``version``

    """

    from hl7apy.validation import Validator

    if validation_level is None:
        validation_level = get_default_validation_level()

    if version is None:
        version = get_default_version()

    lib = load_library(version)

    base_datatypes = lib.get_base_datatypes()

    factories = base_datatypes.copy()

    if 'DT' in factories:
        factories['DT'] = date_factory
    if 'TM' in factories:
        factories['TM'] = timestamp_factory
    if 'DTM' in factories:
        factories['DTM'] = datetime_factory
    if 'NM' in factories:
        factories['NM'] = numeric_factory
    if 'SI' in factories:
        factories['SI'] = sequence_id_factory

    try:
        factory = factories[datatype]
        if isinstance(factory, FunctionType):
            return factory(value, base_datatypes[datatype], validation_level=validation_level)
        return factory(value, validation_level=validation_level)
    except KeyError:
        raise InvalidDataType(datatype)
    except ValueError as e:
        if Validator.is_strict(validation_level):
            raise e
        # TODO: Do we really want this? In that case the parent's datatype must be changed accordingly
        return factories['ST'](value)
Example #8
0
def parse_component(text, name=None, datatype='ST', version=None, encoding_chars=None,
                    validation_level=None, reference=None):
    """
    Parse the given ER7-encoded component and return an instance of
    :class:`Component <hl7apy.core.Component>`.

    :type text: ``str``
    :param text: the ER7-encoded string containing the components to be parsed

    :type name: ``str``
    :param name: the component's name (e.g. XPN_2)

    :type datatype: ``str``
    :param datatype: the datatype of the component (e.g. ST)

    :type version: ``str``
    :param version: the HL7 version (e.g. "2.5"), or ``None`` to use the default
        (see :func:`set_default_version <hl7apy.set_default_version>`)

    :type encoding_chars: ``dict``
    :param encoding_chars: a dictionary containing the encoding chars or None to use the default
        (see :func:`set_default_encoding_chars <hl7apy.set_default_encoding_chars>`)

    :type validation_level: ``int``
    :param validation_level: the validation level. Possible values are those defined in
        :class:`VALIDATION_LEVEL <hl7apy.consts.VALIDATION_LEVEL>` class or ``None`` to use the default
        validation level (see :func:`set_default_validation_level <hl7apy.set_default_validation_level>`)

    :type reference: ``dict``
    :param reference: a dictionary containing the element structure returned by
        :func:`load_reference <hl7apy.load_reference>` or :func:`find_reference <hl7apy.find_reference>`
        or belonging to a message profile

    :return: an instance of :class:`Component <hl7apy.core.Component>`

    >>> component = "GATEWAY&1.3.6.1.4.1.21367.2011.2.5.17"
    >>> cx_4 = parse_component(component, name="CX_4")
    >>> print(cx_4)
    <Component CX_4 (ASSIGNING_AUTHORITY) of type None>
    >>> print(cx_4.to_er7())
    GATEWAY&1.3.6.1.4.1.21367.2011.2.5.17
    >>> print(parse_component(component))
    <Component ST (None) of type None>
    """
    version = _get_version(version)
    encoding_chars = _get_encoding_chars(encoding_chars)
    validation_level = _get_validation_level(validation_level)

    try:
        component = Component(name, datatype, version=version, validation_level=validation_level,
                              reference=reference)
    except InvalidName as e:
        if Validator.is_strict(validation_level):
            raise e
        component = Component(datatype, version=version, validation_level=validation_level,
                              reference=reference)
    children = parse_subcomponents(text, component.datatype, version, encoding_chars, validation_level)
    if Validator.is_tolerant(component.validation_level) and is_base_datatype(component.datatype, version) and \
            len(children) > 1:
        component.datatype = None
    component.children = children
    return component
Example #9
0
def parse_message(message, validation_level=None, find_groups=True, message_profile=None, report_file=None,
                  force_validation=False):
    """
    Parse the given ER7-encoded message and return an instance of :class:`Message <hl7apy.core.Message>`.

    :type message: ``str``
    :param message: the ER7-encoded message to be parsed

    :type validation_level: ``int``
    :param validation_level: the validation level. Possible values are those defined in
        :class:`VALIDATION_LEVEL <hl7apy.consts.VALIDATION_LEVEL>` class or ``None`` to use the default
        validation level (see :func:`set_default_validation_level <hl7apy.set_default_validation_level>`)

    :type find_groups: ``bool``
    :param find_groups: if ``True``, automatically assign the segments found to the appropriate
        :class:`Groups <hl7apy.core.Group>` instances. If ``False``, the segments found are assigned as
        children of the :class:`Message <hl7apy.core.Message>` instance
        
    :type force_validation: ``bool``
    :type force_validation: if ``True``, automatically forces the message validation after the end of the parsing

    :return: an instance of :class:`Message <hl7apy.core.Message>`

    >>> message = "MSH|^~\&|GHH_ADT||||20080115153000||OML^O33^OML_O33|0123456789|P|2.5||||AL\\rPID|1||" \
    "566-554-3423^^^GHH^MR||EVERYMAN^ADAM^A|||M|||2222 HOME STREET^^ANN ARBOR^MI^^USA||555-555-2004|||M\\r"
    >>> m = parse_message(message)
    >>> print(m)
    <Message OML_O33>
    >>> print(m.msh.sending_application.to_er7())
    GHH_ADT
    >>> print(m.children)
    [<Segment MSH>, <Group OML_O33_PATIENT>]
    """
    message = message.lstrip()
    encoding_chars, message_structure, version = get_message_info(message)

    validation_level = _get_validation_level(validation_level)

    try:
        reference = message_profile[message_structure] if message_profile else None
    except KeyError:
        raise MessageProfileNotFound()

    try:
        m = Message(name=message_structure, reference=reference, version=version,
                    validation_level=validation_level, encoding_chars=encoding_chars)
    except InvalidName:
        m = Message(version=version, validation_level=validation_level,
                    encoding_chars=encoding_chars)
    children = parse_segments(message, m.version, encoding_chars, validation_level,
                              m.structure_by_name)
    if m.name is not None and find_groups:
        m.children = []
        create_groups(m, children, validation_level)
    else:
        m.children = children

    if force_validation:
        if message_profile is None:
            Validator.validate(m, report_file=report_file)
        else:
            Validator.validate(m, message_profile[message_structure], report_file=report_file)

    return m
Example #10
0
def parse_field(text, name=None, version=None, encoding_chars=None, validation_level=None,
                reference=None, force_varies=False):
    """
    Parse the given ER7-encoded field and return an instance of :class:`Field <hl7apy.core.Field>`.

    :type text: ``str``
    :param text: the ER7-encoded string containing the fields to be parsed

    :type name: ``str``
    :param name: the field name (e.g. MSH_7)

    :type version: ``str``
    :param version: the HL7 version (e.g. "2.5"), or ``None`` to use the default
        (see :func:`set_default_version <hl7apy.set_default_version>`)

    :type encoding_chars: ``dict``
    :param encoding_chars: a dictionary containing the encoding chars or None to use the default
        (see :func:`set_default_encoding_chars <hl7apy.set_default_encoding_chars>`)

    :type validation_level: ``int``
    :param validation_level: the validation level. Possible values are those defined in
        :class:`VALIDATION_LEVEL <hl7apy.consts.VALIDATION_LEVEL>` class or ``None`` to use the default
        validation level (see :func:`set_default_validation_level <hl7apy.set_default_validation_level>`)

    :type reference: ``dict``
    :param reference: a dictionary containing the element structure returned by
        :func:`load_reference <hl7apy.load_reference>` or :func:`find_reference <hl7apy.find_reference>`
        or belonging to a message profile

    :type force_varies: ``boolean``
    :param force_varies: flag that force the fields to use a varies structure when no reference is found.
        It is used when a segment ends with a field of type varies that thus support infinite children

    :return: an instance of :class:`Field <hl7apy.core.Field>`

    >>> field = "NUCLEAR^NELDA^W"
    >>> nk1_2 = parse_field(field, name="NK1_2")
    >>> print(nk1_2)
    <Field NK1_2 (NAME) of type XPN>
    >>> print(nk1_2.to_er7())
    NUCLEAR^NELDA^W
    >>> unknown = parse_field(field)
    >>> print(unknown)
    <Field of type None>
    >>> print(unknown.to_er7())
    NUCLEAR^NELDA^W
    """
    version = _get_version(version)
    encoding_chars = _get_encoding_chars(encoding_chars)
    validation_level = _get_validation_level(validation_level)

    try:
        field = Field(name, version=version, validation_level=validation_level, reference=reference)
    except InvalidName:
        if force_varies:
            reference = ('leaf', 'varies', None, None)
            field = Field(name, version=version, validation_level=validation_level, reference=reference)
        else:
            field = Field(version=version, validation_level=validation_level, reference=reference)

    if name in ('MSH_1', 'MSH_2'):
        s = SubComponent(datatype='ST', value=text, validation_level=validation_level, version=version)
        c = Component(datatype='ST', validation_level=validation_level, version=version)
        c.add(s)
        field.add(c)
    else:
        children = parse_components(text, field.datatype, version, encoding_chars, validation_level,
                                    field.structure_by_name)
        if Validator.is_tolerant(validation_level) and is_base_datatype(field.datatype, version) and \
                len(children) > 1:
            field.datatype = None
        field.children = children
    return field
Example #11
0
def parse_message(message, validation_level=None, find_groups=True, message_profile=None, report_file=None,
                  force_validation=False):
    """
    Parse the given ER7-encoded message and return an instance of :class:`Message <hl7apy.core.Message>`.

    :type message: ``str``
    :param message: the ER7-encoded message to be parsed

    :type validation_level: ``int``
    :param validation_level: the validation level. Possible values are those defined in
        :class:`VALIDATION_LEVEL <hl7apy.consts.VALIDATION_LEVEL>` class or ``None`` to use the default
        validation level (see :func:`set_default_validation_level <hl7apy.set_default_validation_level>`)

    :type find_groups: ``bool``
    :param find_groups: if ``True``, automatically assign the segments found to the appropriate
        :class:`Groups <hl7apy.core.Group>` instances. If ``False``, the segments found are assigned as
        children of the :class:`Message <hl7apy.core.Message>` instance
        
    :type force_validation: ``bool``
    :type force_validation: if ``True``, automatically forces the message validation after the end of the parsing

    :return: an instance of :class:`Message <hl7apy.core.Message>`

    >>> message = "MSH|^~\&|GHH_ADT||||20080115153000||OML^O33^OML_O33|0123456789|P|2.5||||AL\\rPID|1||" \
    "566-554-3423^^^GHH^MR||EVERYMAN^ADAM^A|||M|||2222 HOME STREET^^ANN ARBOR^MI^^USA||555-555-2004|||M\\r"
    >>> m = parse_message(message)
    >>> print(m)
    <Message OML_O33>
    >>> print(m.msh.sending_application.to_er7())
    GHH_ADT
    >>> print(m.children)
    [<Segment MSH>, <Group OML_O33_PATIENT>]
    """
    message = message.lstrip()
    encoding_chars, message_structure, version = get_message_info(message)
    validation_level = _get_validation_level(validation_level)

    try:
        reference = message_profile[message_structure] if message_profile else None
    except KeyError:
        raise MessageProfileNotFound()

    try:
        m = Message(name=message_structure, reference=reference, version=version,
                    validation_level=validation_level, encoding_chars=encoding_chars)
    except InvalidName:
        m = Message(version=version, validation_level=validation_level,
                    encoding_chars=encoding_chars)

    try:
        children = parse_segments(message, m.version, encoding_chars, validation_level, m.reference, find_groups)
    except AttributeError:  # m.reference can raise i
        children = parse_segments(message, m.version, encoding_chars, validation_level, find_groups=False)

    m.children = children

    if force_validation:
        if message_profile is None:
            Validator.validate(m, report_file=report_file)
        else:
            Validator.validate(m, message_profile[message_structure], report_file=report_file)

    return m
Example #12
0
def parse_field(text, name=None, version=None, encoding_chars=None, validation_level=None,
                reference=None, force_varies=False):
    """
    Parse the given ER7-encoded field and return an instance of :class:`Field <hl7apy.core.Field>`.

    :type text: ``str``
    :param text: the ER7-encoded string containing the fields to be parsed

    :type name: ``str``
    :param name: the field name (e.g. MSH_7)

    :type version: ``str``
    :param version: the HL7 version (e.g. "2.5"), or ``None`` to use the default
        (see :func:`set_default_version <hl7apy.set_default_version>`)

    :type encoding_chars: ``dict``
    :param encoding_chars: a dictionary containing the encoding chars or None to use the default
        (see :func:`set_default_encoding_chars <hl7apy.set_default_encoding_chars>`)

    :type validation_level: ``int``
    :param validation_level: the validation level. Possible values are those defined in
        :class:`VALIDATION_LEVEL <hl7apy.consts.VALIDATION_LEVEL>` class or ``None`` to use the default
        validation level (see :func:`set_default_validation_level <hl7apy.set_default_validation_level>`)

    :type reference: ``dict``
    :param reference: a dictionary containing the element structure returned by
        :func:`load_reference <hl7apy.load_reference>` or :func:`find_reference <hl7apy.find_reference>`
        or belonging to a message profile

    :type force_varies: ``boolean``
    :param force_varies: flag that force the fields to use a varies structure when no reference is found.
        It is used when a segment ends with a field of type varies that thus support infinite children

    :return: an instance of :class:`Field <hl7apy.core.Field>`

    >>> field = "NUCLEAR^NELDA^W"
    >>> nk1_2 = parse_field(field, name="NK1_2")
    >>> print(nk1_2)
    <Field NK1_2 (NAME) of type XPN>
    >>> print(nk1_2.to_er7())
    NUCLEAR^NELDA^W
    >>> unknown = parse_field(field)
    >>> print(unknown)
    <Field of type None>
    >>> print(unknown.to_er7())
    NUCLEAR^NELDA^W
    """
    version = _get_version(version)
    encoding_chars = _get_encoding_chars(encoding_chars, version)
    validation_level = _get_validation_level(validation_level)

    try:
        field = Field(name, version=version, validation_level=validation_level, reference=reference)
    except InvalidName:
        if force_varies:
            reference = ('leaf', None, 'varies', None, None, -1)
            field = Field(name, version=version, validation_level=validation_level, reference=reference)
        else:
            field = Field(version=version, validation_level=validation_level, reference=reference)

    if name in ('MSH_1', 'MSH_2'):
        s = SubComponent(datatype='ST', value=text, validation_level=validation_level, version=version)
        c = Component(datatype='ST', validation_level=validation_level, version=version)
        c.add(s)
        field.add(c)
    else:
        children = parse_components(text, field.datatype, version, encoding_chars, validation_level,
                                    field.structure_by_name)
        if Validator.is_tolerant(validation_level) and is_base_datatype(field.datatype, version) and \
                len(children) > 1:
            field.datatype = None
        field.children = children
    return field