<xs:schema version="2.8.0"
           attributeFormDefault="unqualified"
           elementFormDefault="qualified"
           xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="PGNDefinitions" type="PGNDefinitions">
    <xs:annotation>
      <xs:documentation>
CANboat version v9.2.0 2009-2026, Kees Verruijt, Harlingen, The Netherlands.
For more information see https://github.com/canboat/canboat

This file is part of CANboat.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
</xs:documentation>

    </xs:annotation>

    <xs:key name="PhysicalQuantity">
      <xs:selector xpath="./PhysicalQuantities/PhysicalQuantity"/>
      <xs:field xpath="@Name"/>
    </xs:key>

    <xs:keyref name="PhysicalQuantityRef" refer="PhysicalQuantity">
      <xs:selector xpath="./PGNS/PGNInfo/Fields/Field"/>
      <xs:field xpath="@PhysicalQuantity"/>
    </xs:keyref>

  </xs:element>

  <xs:complexType name="PGNDefinitions">
    <xs:annotation>
      <xs:documentation>
        The outer container has the historic name PGNDefinitions.
        Historic, because it now also contains other complex types that
        are referred to from the PGNs.
      </xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <xs:annotation>
        <xs:documentation>
          Wherever possible we use a straight sequence, which guarantees
          that the children elements are always in the same order.

          This has as children some basic string elements followed by
          the different complex types that we use to define the PGNs:
          Physical Quantities, Field Types, and five types of enumerations:
          Missing, Lookup, LookupIndirect, LookupBit and LookupFieldtype.
          The last element is the list of PGNs themselves.
        </xs:documentation>
      </xs:annotation>
      <xs:element type="xs:string" name="SchemaVersion">
        <xs:annotation>
          <xs:documentation>
            This is the version of the schema that the XML instance
            document uses.  The version of the schema is found in the
            version attribute in the xs:schema top-level element.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:string" name="Comment"/>
      <xs:element type="xs:string" name="CreatorCode"/>
      <xs:element type="xs:string" name="License"/>
      <xs:element type="xs:string" name="Version"/>
      <xs:element type="xs:string" name="Copyright"/>
      <xs:element type="Protocol" name="Protocol" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            The protocol on the CAN bus these PGNs are carried on. NMEA 2000
            (docs/canboat.xml) and SAE J1939 (docs/canboat-j1939.xml) share
            the ISO 11783 frame header, address claim and transport protocol
            but define different PGNs, and only NMEA 2000 has fast-packet
            framing. Quick PCS (docs/canboat-quick.xml) has 11-bit CAN
            identifiers instead: there the PGN is the identifier, a message
            type, with no priority, source or destination. Absent in documents
            older than schema 2.7.0, which are all NMEA 2000.

            pseudo (docs/canboat-pseudo.xml, since schema 2.8.0) is not a bus:
            it holds canboat's pseudo-PGNs, 0x40000 and up, which no other
            document has. They are records of a gateway (Actisense BEM
            messages, an NMEA 2000 gateway's network status) and of canboat
            itself. They never appear on a bus, but they do in canboat's
            output streams, whatever the protocol.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="PhysicalQuantities" name="PhysicalQuantities"/>
      <xs:element type="FieldTypes" name="FieldTypes"/>
      <xs:element type="MissingEnumerations" name="MissingEnumerations"/>
      <xs:element type="LookupEnumerations" name="LookupEnumerations"/>
      <xs:element type="LookupIndirectEnumerations" name="LookupIndirectEnumerations"/>
      <xs:element type="LookupBitEnumerations" name="LookupBitEnumerations"/>
      <xs:element type="LookupFieldTypeEnumerations" name="LookupFieldTypeEnumerations"/>
      <xs:element type="PGNs" name="PGNs"/>
    </xs:sequence>
  </xs:complexType>

  <xs:simpleType name="Protocol">
    <xs:restriction base="xs:string">
      <xs:enumeration value="nmea2000"/>
      <xs:enumeration value="j1939"/>
      <xs:enumeration value="quick"/>
      <xs:enumeration value="pseudo"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:complexType name="EnumPair">
    <xs:simpleContent>
      <xs:extension base="xs:string">
        <xs:attribute type="xs:unsignedShort" name="Value" />
        <xs:attribute type="xs:string" name="Name" />
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>

  <xs:complexType name="LookupEnumeration">
    <xs:annotation>
      <xs:documentation>
        The LookupEnumeration is a list of EnumPair elements with a name.
        This allows the PGN field to refer to this when it contains a lookup
        field, for instance 0 = No, 1 = Yes. The special null-like values
        for Unknown and Error are not placed in this list.
      </xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <xs:element type="EnumPair" name="EnumPair" maxOccurs="unbounded" minOccurs="0"/>
    </xs:sequence>
    <xs:attribute type="xs:string" name="Name"/>
    <xs:attribute type="xs:long" name="MaxValue"/>
  </xs:complexType>

  <xs:complexType name="LookupEnumerations">
    <xs:sequence>
      <xs:element type="LookupEnumeration" name="LookupEnumeration" maxOccurs="unbounded" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="EnumTriplet">
    <xs:simpleContent>
      <xs:extension base="xs:string">
        <xs:attribute type="xs:unsignedShort" name="Value1" />
        <xs:attribute type="xs:unsignedShort" name="Value2" />
        <xs:attribute type="xs:string" name="Name" />
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>

  <xs:complexType name="LookupIndirectEnumeration">
    <xs:annotation>
      <xs:documentation>
        The LookupEnumeration is a list of EnumTriplet elements with a name.
        This allows the PGN field to refer to this when it contains a lookup
        field. Indirect enumerations use two values to define a specific name.
        The first value is taken from another field. The second value is the value
        for this field.
        The special null-like values for Unknown and Error are not placed in this list.
      </xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <xs:element type="EnumTriplet" name="EnumTriplet" maxOccurs="unbounded" minOccurs="0"/>
    </xs:sequence>
    <xs:attribute type="xs:string" name="Name"/>
    <xs:attribute type="xs:long" name="MaxValue"/>
  </xs:complexType>

  <xs:complexType name="LookupIndirectEnumerations">
    <xs:sequence>
      <xs:element type="LookupIndirectEnumeration" name="LookupIndirectEnumeration" maxOccurs="unbounded" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="BitPair">
    <xs:simpleContent>
      <xs:extension base="xs:string">
        <xs:attribute type="xs:byte" name="Bit" />
        <xs:attribute type="xs:string" name="Name" />
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>

  <xs:complexType name="LookupBitEnumeration">
    <xs:annotation>
      <xs:documentation>
        The LookupBitEnumeration is a list of BitPair elements with a name.
        This allows the PGN field to refer to this when it contains a lookup
        field, for instance bit 0 = Too Hot, bit 1 = Too Cold.
        LookupBitEnumeration fields do not have special null-like values.
      </xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <xs:element type="BitPair" name="BitPair" maxOccurs="unbounded" minOccurs="0"/>
    </xs:sequence>
    <xs:attribute type="xs:string" name="Name"/>
    <xs:attribute type="xs:byte" name="MaxValue"/>
  </xs:complexType>
  <xs:complexType name="LookupBitEnumerations">
    <xs:sequence>
      <xs:element type="LookupBitEnumeration" name="LookupBitEnumeration" maxOccurs="unbounded" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="EnumFieldType">
    <xs:sequence>
      <xs:element type="xs:string" name="LookupEnumeration" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            When the FieldType is LOOKUP, the field value has meaning derived from 
            the lookup table mentioned here.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:string" name="LookupIndirectEnumeration" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            When the FieldType is INDIRECT_LOOKUP, the field value has meaning derived from 
            the lookup table mentioned here. It requires an additional first
            value derived from the field indicated by LookupIndirectEnumerationField..
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:byte" name="LookupIndirectEnumerationFieldOrder" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            When the FieldType is INDIRECT_LOOKUP, the field value has meaning that
            also depends on the value of the field mentioned by order in this element.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:string" name="LookupBitEnumeration" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            When the FieldType is BITLOOKUP, the field value has to be interpreted as
            a number of bits, with each bit forming a flag whose meaning is given in the lookup table.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
    </xs:sequence>
    <xs:attribute type="xs:unsignedShort" name="Value" />
    <xs:attribute type="xs:string" name="Name" />
    <xs:attribute type="xs:string" name="FieldType" use="optional" />
    <xs:attribute type="xs:boolean" name="Signed" use="optional" />
    <xs:attribute type="xs:float" name="Resolution" use="optional" />
    <xs:attribute type="xs:string" name="Unit" use="optional" />
    <xs:attribute type="xs:unsignedShort" name="Bits" use="optional" />
  </xs:complexType>

  <xs:complexType name="LookupFieldTypeEnumeration">
    <xs:annotation>
      <xs:documentation>
        The LookupFieldTypeEnumeration is a list of EnumFieldType elements with a name.
        This allows the PGN field to refer to this when it contains a lookup
        field, for instance 0 = No, 1 = Yes. The special null-like values
        for Unknown and Error are not placed in this list.
        This is different from a LookupEnumeration in that it also defines
        a set of field attributes for a following variable field.
      </xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <xs:element type="EnumFieldType" name="EnumFieldType" maxOccurs="unbounded" minOccurs="0"/>
    </xs:sequence>
    <xs:attribute type="xs:string" name="Name"/>
    <xs:attribute type="xs:int" name="MaxValue"/>
  </xs:complexType>

  <xs:complexType name="LookupFieldTypeEnumerations">
    <xs:sequence>
      <xs:element type="LookupFieldTypeEnumeration" name="LookupFieldTypeEnumeration" maxOccurs="unbounded" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="PhysicalQuantity">
    <xs:annotation>
      <xs:documentation>
        To explain numeric types more easily the concept of a PhysicalQuantity
        is introduced. Given the few public snippets of the NMEA PGN definitions
        it looks as if they do not explicitly have such a concept, but it seems
        a nice way of grouping similar fields.
        If a field represents a value with a particular unit, like 'A' for Ampere,
        this refers to the concept of ELECTRICAL_CURRENT -- at least that is how
        we see it.
        The PhysicalQuantity is mostly used for 'explanation', it is not fundamental
        to interpreting the PGN field values.
      </xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <xs:element type="xs:string" name="Description"/>
      <xs:element type="xs:string" name="Comment" minOccurs="0"/>
      <xs:element type="xs:string" name="URL" minOccurs="0"/>
      <xs:element type="xs:string" name="UnitDescription"/>
      <xs:element type="xs:string" name="Unit"/>
    </xs:sequence>
    <xs:attribute type="xs:string" name="Name"/>
  </xs:complexType>
  <xs:complexType name="PhysicalQuantities">
    <xs:sequence>
      <xs:element type="PhysicalQuantity" name="PhysicalQuantity" maxOccurs="unbounded" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="FieldType">
    <xs:annotation>
      <xs:documentation>
        There are only a few, really basic, field types.
        In the C code of the CANBoat analyzer, these map perfectly onto C functions
        that extract the bits from the PGN and emit them in "human" or "JSON" form.
      </xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <xs:element type="xs:string" name="Description">
      </xs:element>
      <xs:element type="xs:string" name="EncodingDescription" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            Explanation of how the field type is encoded.
            field type.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:string" name="Comment" minOccurs="0">
      </xs:element>
      <xs:element type="xs:string" name="URL" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            Optional external reference explaining the encoding of this
            field type.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:unsignedShort" name="Bits" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            The number of bits that this field takes up in the PGN, if this
            is fixed for all fields.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:string" name="Unit" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            Present in the FieldType when it has a typical unit.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:boolean" name="Signed" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            Present in the FieldType when all fields have a guaranteed sign.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:boolean" name="VariableSize" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            True if the fields of this FieldType all have a variable length in bits.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element name="Sentinels">
        <xs:annotation>
          <xs:documentation>
            How a field of this type signals "data not available" (and, for integers,
            out-of-range and reserved). One of:
            TopOfRange  - the top 1 to 3 raw integer values are reserved as
                          Unknown (most positive), OutOfRange (max-1) and Reserved
                          (max-2); the count depends on the bit width, so the actual
                          reserved values are given per field as UnknownValue,
                          OutOfRangeValue and ReservedValue. For LOOKUP fields a value
                          that the enumeration names explicitly is a real value and is
                          not reserved, lowering the count.
            EmptyString - an empty string (after trimming end-of-string bytes such as
                          0xff, 0x00 and '@') marks the field as unavailable.
            NaN         - the IEEE-754 Not-a-Number value.
            Variable    - the convention depends on the data type that is resolved at
                          run time through the companion DYNAMIC_FIELD_KEY field.
            None        - the field has no unavailable encoding (an identifier such as
                          PGN or MMSI, filler such as RESERVED, or a structured field).
          </xs:documentation>
        </xs:annotation>
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:enumeration value="TopOfRange"/>
            <xs:enumeration value="EmptyString"/>
            <xs:enumeration value="NaN"/>
            <xs:enumeration value="Variable"/>
            <xs:enumeration value="None"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
    </xs:sequence>
    <xs:attribute type="xs:string" name="Name"/>
  </xs:complexType>
  <xs:complexType name="FieldTypes">
    <xs:sequence>
      <xs:element type="FieldType" name="FieldType" maxOccurs="unbounded" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="Field">
    <xs:annotation>
      <xs:documentation>
        The Field is the core definition, as a PGN is usually just a bunch of fields
        in sequence.
      </xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <xs:element type="xs:byte" name="Order">
        <xs:annotation>
          <xs:documentation>
            The sequence in which the field is ordered within the PGN. 
            Starts at 1. In theory there could be 233 * 8 fields, but in practice
            there are no more than 29.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:string" name="Id">
        <xs:annotation>
          <xs:documentation>
            A generated string representing the field name; e.g. with spaces removed
            and in camelCase.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:string" name="Name">
        <xs:annotation>
          <xs:documentation>
            The field name.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:string" name="Description" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            An extra explanation.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:unsignedInt" name="SPN" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            SAE J1939 only: the Suspect Parameter Number J1939-71 gives this
            value. It identifies the value itself, whichever PGN carries it,
            and is what J1939 documentation and diagnostic trouble codes
            (DM1) refer to. Absent on NMEA 2000 fields.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:string" name="Continues" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            The Id of an earlier field in the same record (and the same
            repeating set) whose value this field continues: this field's
            bits are that value's high bits, above the earlier field's own
            BitLength. The field keeps its own place in the layout. J1939-73
            splits a trouble code's 19-bit SPN this way, around the FMI.
            A decoder that does not know this element sees two plain
            numbers; one that does shows the earlier field with the joined
            value (and its lookup name), and this field not at all.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:unsignedByte" name="TrailingZeroIsDigitField" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            Only on a DECIMAL field, together with TrailingZeroIsDigitValue:
            the Order of an earlier unsigned integer field without
            resolution or offset, at a fixed position (nothing of variable
            length, no proprietary field and no repeating set before it),
            so its raw value is compared. A DECIMAL
            with an odd number of digits is sent with a 0 added at the
            end, which a decoder drops: a DSC call sends a 9-digit MMSI as
            ten digits. When the field with this Order holds
            TrailingZeroIsDigitValue, that last digit is part of the value
            instead and must be kept. PGN 129808's DSC Message Address is
            ten digits of geographical area when the DSC Format is 102.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:long" name="TrailingZeroIsDigitValue" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            The raw value of the field named by TrailingZeroIsDigitField
            for which this DECIMAL keeps its last digit.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:boolean" name="BitLengthVariable" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            This is present, and true, if the field has a variable length.
            For instance, most types of strings. These will then have a minimum
            length defined by how the string length is determined, but that
            is type dependent. The field may also have a different field that
            specifies how long this field is, in that case BitLengthField will
            be present.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:byte" name="BitLengthField" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            If present, the field is variable length and the number of bits is
            contained in the field whose order is indicated here.
            Until now the only known occurrences have the property that the
            length field immediately precedes the variable length field.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:unsignedShort" name="BitLength" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            If present, the field has a fixed length and this element gives
            the number of bits that the field is long.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:unsignedShort" name="BitOffset" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            If present, the field is preceded by no other fields or only fixed
            length fields and the offset from the start of the PGN data can be
            pre-determined, and this element says how many bits from the start
            that this field is located.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:byte" name="BitStart" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            Some fields are not byte-aligned, and will contain a non-zero value
            for BitStart, indicating at which bit in the byte the field starts.
            Note that fields can span multiple bytes. In practice we have not
            seen fields that start at a non-zero BitStart and span more than 2
            bytes.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:string" name="Condition" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            When a field contains this element, this field may or may not
            appear in the PGN depending on the condition.
            At this moment the only possible condition is if the early
            field in the same PGN named 'PGN' is manufacturer proprietary.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:int" name="Match" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            Manufacturer proprietary PGNs do not have to have a unique PGN
            number, as each manufacturer is free to use all PGNs in the
            manufacturer proprietary ranges. To distinguish which PGN definition
            is the appropriate one, some PGNs contain Match values that must
            all match before this PGN definition is considered the right one.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:string" name="Unit" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            The unit that the PGN is defined in; these are generally, but not always,
            SI or SI like. Some manufacturer PGNs define angles in degrees instead
            of in radians, and some standardized fields use kWh instead of J.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:float" name="Resolution" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            All number-y fields have a resolution, which tells you how the binary
            value must be interpreted vis-a-vis the physical quantity. For instance,
            angles are generally stored as 0.0001 radian, so a binary value of 0
            means 0 radians, 1 means 0.0001 radian, 2 means 0.0002 radian, etc.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:boolean" name="Signed" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            All number-y fields have this element, and it reports whether the
            fields contains a signed or an unsigned value. Unsigned values are
            always in standard binary format, with the LSB representing the
            value 1, the 2nd bit the value 2, the 3rd bit the value 4, etc.
            Signed values are either in 2s complement, or in Excess K offset
            notation. If the latter, the Offset element is present.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:decimal" name="Offset" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            When the value is signed, but not in 2s complement, the value is in
            Excess K format and this element contains the (negative) offset that
            must be added to the unsigned binary number to end up with the 
            appropriate signed value. It is in the field's own units, so it can
            have a fraction (J1939's -62.5 L fluid level deviation). An unsigned
            value can have an offset too: J1939's 8-bit temperature starts at
            -40 deg C, which is an Offset of 233.15 K.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:unsignedByte" name="DynamicFieldLengthOverhead" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            For a DYNAMIC_FIELD_LENGTH field: the number of non-value header bytes (for example a class byte
            and a data-type id) that sit between this length field and the value and are counted in this
            length. A decoder must subtract this from the length to obtain the byte count of the following
            DYNAMIC_FIELD_VALUE field.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:float" name="RangeMin" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            The minimal value that the field can represent, after conversion to
            a floating point value -- e.g. after the sign and offset and resolution
            have been applied.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:float" name="RangeMax" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            The minimal value that the field can represent, after conversion to
            a floating point value -- e.g. after the sign and offset and resolution
            have been applied. Note that this reserves space for the special values
            that can be present.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:unsignedLong" name="UnknownValue" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            For integer number fields: the raw (unscaled) value that signals
            "data not available". This is the most positive value the field can hold.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:unsignedLong" name="OutOfRangeValue" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            For integer number fields of 4 bits and larger: the raw (unscaled) value
            that signals "out of range" (the most positive value minus one).
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:unsignedLong" name="ReservedValue" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            For integer number fields of 8 bits and larger: the raw (unscaled) value
            that the NMEA 2000 standard reserves (the most positive value minus two).
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:string" name="FieldType">
        <xs:annotation>
          <xs:documentation>
            Fields always contain a field type.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:string" name="Encoding" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            Character set to read this field's bytes as when they are not
            well-formed UTF-8. Only present on 8-bit string fields whose
            device is known to put some other charset on the wire; absent
            means Latin-1, which is what every string field uses by default.

            A reader should still try UTF-8 first and consult this only when
            that fails. RDS2 carries text as UTF-8, so a device that gains it
            will start sending valid UTF-8 in the same field and must keep
            decoding without a database change.

            RDS_G0 is the Basic RDS character set: IEC 62106 table E.1,
            published identically as the "Complete EBU Latin based
            repertoire" in ETSI TS 101 756 V1.6.1 (2014-05) annex C.

            Take it from V1.6.1, not from the V1.8.1 (2015-12) revision of
            that annex, and not from a third-party copy. V1.8.1 reassigns 36
            of the 224 positions - the whole 0xA0..0xBF block, 0x24, and
            backslash, brace and bar - as a DAB-only extension that never
            reached RDS. The two agree on every accented letter common in a
            station name, so the mistake does not show up in casual testing.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:string" name="PhysicalQuantity" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            Fields that represent a physical quantity refer to one of the
            PhysicalQuantities. If Unit is present, so is PhysicalQuantity.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:string" name="LookupEnumeration" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            When the FieldType is LOOKUP, the field value has meaning derived from 
            the lookup table mentioned here.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:string" name="LookupIndirectEnumeration" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            When the FieldType is INDIRECT_LOOKUP, the field value has meaning derived from 
            the lookup table mentioned here. It requires an additional first
            value derived from the field indicated by LookupIndirectEnumerationField..
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:byte" name="LookupIndirectEnumerationFieldOrder" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            When the FieldType is INDIRECT_LOOKUP, the field value has meaning that
            also depends on the value of the field mentioned by order in this element.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:string" name="LookupBitEnumeration" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            When the FieldType is BITLOOKUP, the field value has to be interpreted as
            a number of bits, with each bit forming a flag whose meaning is given in the lookup table.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:string" name="LookupFieldTypeEnumeration" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            When the FieldType is LOOKUP_FIELDTYPE, the field value has meaning derived from 
            the lookup table mentioned here. It also defines the field type of a
            following variable field.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:boolean" name="PartOfPrimaryKey" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            If present and set to true, this field serves as a component of the primary key for the PGN.
            It uniquely identifies records in conjunction with other key fields.
            Pure simplistic analyzers or software that just passes this data on can ignore this field.
            Software that stores data organised by source can store data indexed by all primary key
            fields. In other words: if a PGN repeats but it contains a different value in the primary
            key fields, it is for a different object. The prime example is AIS, where a different source
            MMSI means it is from a different ship. 
          </xs:documentation>
        </xs:annotation>
      </xs:element>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="Fields">
    <xs:sequence>
      <xs:element type="Field" name="Field" maxOccurs="unbounded" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="Missing">
    <xs:annotation>
      <xs:documentation>
        Documents the things that we do not know about this PGN yet.
      </xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <xs:element type="xs:string" name="MissingAttribute" maxOccurs="unbounded" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="MissingEnumerations">
    <xs:sequence>
      <xs:element name="MissingAttribute" maxOccurs="unbounded" minOccurs="0">
        <xs:complexType>
          <xs:simpleContent>
            <xs:extension base="xs:string">
              <xs:attribute type="xs:string" name="Name"/>
            </xs:extension>
          </xs:simpleContent>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="PGNInfo">
    <xs:sequence>
      <xs:element type="xs:int" name="PGN"/>
      <xs:element type="xs:string" name="Id"/>
      <xs:element type="xs:string" name="Description"/>
      <xs:element type="xs:unsignedShort" name="Priority" minOccurs="0"/>
      <xs:element type="xs:string" name="Explanation" minOccurs="0"/>
      <xs:element type="xs:string" name="URL" minOccurs="0"/>
      <xs:element type="xs:string" name="ResearchDoc" minOccurs="0"/>
      <xs:element type="xs:string" name="Type">
        <xs:annotation>
          <xs:documentation>
            Whether the PGN is a <i>Single</i> frame or a <i>Fast</i> packet set of frames.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:boolean" name="Complete">
        <xs:annotation>
          <xs:documentation>
            When present and true, the PGN has been reverse engineered to such a level that
            we believe it is nearly complete; e.g. in all practical ways the PGN is usable
            in producing proper results. If this is not present, there will be a Missing
            element that explains what we think we don't know.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:boolean" name="Fallback" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            When present and true, the PGN is a 'virtual' PGN used as a fallback mechanism
            to print unknown PGNs.
            The element will either be missing or contain true.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="Missing" name="Missing" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            Gives a list of MissingAttribute that we think we don't know.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:unsignedShort" name="FieldCount"/>
      <xs:element type="xs:unsignedShort" name="MinLength" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            The length in bytes of the shortest payload that still decodes as this PGN.
            On a variable-length PGN (one with a repeating field set, or a field whose
            width is not known in advance) this is the only length published: the actual
            length depends on how often the set repeats.
            On a fixed-length PGN it appears next to Length, and then documents that
            shorter payloads occur on the wire: the trailing fields were added by a later
            NMEA 2000 version and devices built against the earlier layout still omit
            them. Such a payload ends on a field boundary, so every field it does contain
            decodes normally and the fields past MinLength are simply absent.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:unsignedShort" name="Length" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            The length in bytes of a complete payload, present only when the PGN has a
            fixed length. See MinLength for the shortest form that is still accepted.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:byte" name="RepeatingFieldSet1Size" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            Some fields may repeat, either until the data is exhausted or a particular
            field says how often the fields repeat. There can be two sets of repeating
            fields.
            If present, this element documents how many fields are in the first set of 
            repeating fields.
            If not present, there are no repeating fields.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:byte" name="RepeatingFieldSet1StartField" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            Some fields may repeat, either until the data is exhausted or a particular
            field says how often the fields repeat. There can be two sets of repeating
            fields.
            This element documents at which field (e.g. its 'Order') the first set starts.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:byte" name="RepeatingFieldSet1CountField" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            Some fields may repeat, either until the data is exhausted or a particular
            field says how often the fields repeat. There can be two sets of repeating
            fields.
            This element documents which earlier field indicates how often the first set repeats.
            If RepeatingFieldSet1StartField is present but RepeatingFieldSet1CountField is not,
            the set repeats until the data is exhausted.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:byte" name="RepeatingFieldSet2Size" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            Some fields may repeat, either until the data is exhausted or a particular
            field says how often the fields repeat. There can be two sets of repeating
            fields.
            If present, this element documents how many fields are in the second set of
            repeating fields.
            If not present, there is no repeating second set.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:byte" name="RepeatingFieldSet2StartField" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            Some fields may repeat, either until the data is exhausted or a particular
            field says how often the fields repeat. There can be two sets of repeating
            fields.
            This element documents at which field (e.g. its 'Order') the second set starts.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:byte" name="RepeatingFieldSet2CountField" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            Some fields may repeat, either until the data is exhausted or a particular
            field says how often the fields repeat. There can be two sets of repeating
            fields.
            This element documents which earlier field indicates how often the second set repeats.
            If RepeatingFieldSet2StartField is present but RepeatingFieldSet2CountField is not,
            the set repeats until the data is exhausted.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:unsignedShort" name="TransmissionInterval" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            When present, it reports the typical interval, in milliseconds, that the PGN repeats.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="xs:boolean" name="TransmissionIrregular" minOccurs="0">
        <xs:annotation>
          <xs:documentation>
            When present, and true, the PGN is only transmitted when something happens (like
            an error condition), when a button is pressed, or when some other devices sends a
            request for the device to send this PGN.
          </xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="Fields" name="Fields" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="PGNs">
    <xs:sequence>
      <xs:element type="PGNInfo" name="PGNInfo" maxOccurs="unbounded" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>

</xs:schema>
