namespace bcf = "https://sourceforge.net/projects/biblatex"

start =
  element bcf:controlfile {
    # This is usually the same as the biblatex version string but not necessarily.
    # Sometimes the BCF format version doesn't change between biblatex releases
    attribute version { xsd:string {minLength="1"}},
    attribute bltxversion { xsd:string {minLength="1"}},

    # "Global" Biber options. It's not clear what a non-global biber option
    # would be but just in case, we have the option ...
    element bcf:options {
      attribute component { "biber" },
      attribute type { "global" },
      output_encoding,
      input_encoding,
      debug,
      mincrossrefs,
      minxrefs,
      sortcase,
      sortupper
    },

    # Global BibLaTeX options. That is, options that apply to all
    # entrytypes (unless a more specifically scoped option is specified)
    element bcf:options {
      attribute component { "biblatex" },
      attribute type { "global" },
      alphaothers,
      labelalpha,
      labelnamespec,
      labeltitle,
      labeltitlespec,
      labeltitleyear,
      labeldateparts,
      labeldatespec,
      julian,
      gregorianstart,
      maxalphanames,
      maxbibnames,
      maxcitenames,
      maxsortnames,
      maxitems,
      minalphanames,
      minbibnames,
      mincitenames,
      minsortnames,
      minitems,
      nohashothers,
      noroman,
      nosortothers,
      pluralothers,
      singletitle,
      skipbib,
      skipbiblist,
      skiplab,      
      sortalphaothers?,
      sortlocale,
      sortingtemplatename,
      sortsets,
      uniquelist,
      uniquename,
      uniqueprimaryauthor,
      uniquetitle,
      uniquebaretitle,
      uniquework,
      useprefix,
      usenames
    },
    
    # Per-entrytype BibLaTeX options
    element bcf:options {
      attribute component { "biblatex" },
      attribute type { text },
      alphaothers?,
      labelalpha?,
      labelnamespec?,
      labeltitle?,
      labeltitlespec?,
      labeltitleyear?,
      labeldateparts?,
      labeldatespec?,
      maxalphanames?,
      maxbibnames?,
      maxcitenames?,
      maxsortnames?,
      maxitems?,
      minalphanames?,
      minbibnames?,
      mincitenames?,
      minsortnames?,
      minitems?,
      nohashothers?,
      noroman?,
      nosortothers?,
      singletitle?,
      skipbib?,
      skipbiblist?,
      skiplab?,
      skiplos?,
      sortalphaothers?,
      uniquelist?,
      uniquename?,
      uniqueprimaryauthor?,
      uniquetitle?,
      uniquebaretitle?,
      uniquework?,
      useprefix?,
      usenames?
    }*,

    # Option scope
    element bcf:optionscope {
      attribute type { "GLOBAL" | "ENTRYTYPE" | "ENTRY" | "NAMELIST" | "NAME" },
      element bcf:option {
        attribute datatype { "boolean" | "integer" | "string" | "xml" },
        # Applies to ENTRY, NAMELIST and NAME scope
        # Only set for meta-options and if defined, what biber should split
        # the option into on reading it
        attribute backendin {xsd:string}?,
        # Applies to ENTRY, NAMELIST and NAME scope
        # Determines whether biber will write the option to its ouput (e.g.
        # .bbl) because biblatex needs to know the value.
        attribute backendout {xsd:boolean}?,
      xsd:string
      }+
    }*,
    
    # datafield sets
    element bcf:datafieldset {
      attribute name { text },
      element bcf:member {
        ((attribute fieldtype { dmfieldtype }?,
          attribute datatype { dmdatatype }?) |
        attribute field { text }?),
        empty
      }+
    }+,

    # user field/entrytype mapping
    element bcf:sourcemap {
      element bcf:maps {
        attribute datatype { "bibtex" | "biblatexml" },
        attribute map_overwrite { xsd:boolean }?,
        attribute level { "user" | "style" | "driver" }?,
        map+
      }+
    }?,

    # labelalphanametemplate specification
    element bcf:labelalphanametemplate {
      attribute name { xsd:string }?,
      element bcf:namepart {
        attribute order { xsd:integer },
        attribute use { xsd:boolean }?,
        attribute pre { xsd:boolean }?,
        attribute substring_width { xsd:integer }?,
        attribute substring_compound { xsd:boolean }?,
        attribute substring_side { "left" | "right" }?,
        text
      }+
    }+,
    
    # labelalpha template specification
    element bcf:labelalphatemplate {
      attribute type { xsd:string }?, # per-type?
      element bcf:labelelement {
        attribute order { xsd:integer },
        element bcf:labelpart {          
          attribute final { xsd:boolean }?,
          attribute pad_char { xsd:string {minLength="1"}}?,
          attribute pad_side { "left" | "right" }?,
          attribute substring_width { xsd:integer | "v" | "vf" | "l" }?,
          attribute substring_fixed_threshold { xsd:integer }?,
          attribute substring_width_max { xsd:integer }?,
          attribute substring_side { "left" | "right" }?,
          attribute ifnames { text }?,
          attribute names { text }?,
          attribute namessep { string }?,
          attribute noalphaothers { xsd:boolean }?,
          xsd:string
        }+
      }+
    }+,

    # Extradate specification
    element bcf:extradatespec {
      # Scope of extradate tracking - an ordered set of fields to try
      element bcf:scope {
        # A field used to track extradate
        element bcf:field {
          attribute order { xsd:integer },
          text
        }+
      }+
    },

    # Cross-reference inheritance specifications
    element bcf:inheritance {
      # Defaults
      element bcf:defaults {
        # Whether to inherit all fields
        attribute inherit_all { "true" | "false" },
        # Should we overwrite the target field if it exists?
        attribute override_target { "true" | "false" },
        # ignore of uniqueness tracking
        attribute ignore { text }?,
        # Default inherit_all and override_target settings for entrytype source/target pairs
        element bcf:type_pair {
          attribute source { "*" | xsd:string {minLength="1"}},
          attribute target { "*" | xsd:string {minLength="1"}},
          attribute inherit_all { "true" | "false" }?,
          attribute override_target { "true" | "false" }?,
          attribute suppress { text }?,
          empty
        }*
      },
      # An inheritance specification
      element bcf:inherit {
        # ignore of uniqueness tracking
        attribute ignore { text }?,
        # applies to these pairs of source/target entrytypes
        element bcf:type_pair {
          attribute source { "*" | xsd:string {minLength="1"}},
          attribute target { "*" | xsd:string {minLength="1"}},
          empty
        }+,
        # and here are the field specifications
        element bcf:field {
          (
            # either a "skip this field" specification
            # so we can say inherit all except certain fields OR ...
            (attribute source { xsd:string },
              attribute skip { "true" | "false" }) |
            # ... a source and target field with an optional override attribute
            (attribute source { xsd:string {minLength="1"}},
              attribute target { xsd:string {minLength="1"}},
              attribute override_target { "true" | "false" }?)
          ),
          empty
        }+
      }*
    },
    # noinit specification
    element bcf:noinits {
      element bcf:noinit {
        attribute value { xsd:string },
        empty
      }+
    }?,
    # nolabel specification
    element bcf:nolabels {
      element bcf:nolabel {
        attribute value { xsd:string },
        empty
      }+
    }?,
    # nosort specification
    element bcf:nosorts {
      element bcf:nosort {
        attribute field { xsd:string },
        attribute value { xsd:string },
        empty
      }+
    }?,
    # nonamestring specification
    element bcf:nonamestrings {
      element bcf:nonamestring {
        attribute field { xsd:string },
        attribute value { xsd:string },
        empty
      }+
    }?,
    # Transliteration specification(s)
    translit*,
    # Uniquename template
    uniquenametemplate+,
    # Sorting name key specification
    sortingnamekeytemplate+,
    # presort default strings for different entry types
    element bcf:presort {
      attribute type { text }?,
      text
    }+,
    # excludes of certain fields for sorting for specified types
    element bcf:sortexclusion {
      attribute type { text },
      element bcf:exclusion { text }+
    }*,
    # forcibly includes certain fields excluded by sortexclusion for sorting for specified types
    element bcf:sortinclusion {
      attribute type { text },
      element bcf:inclusion { text }+
    }*,
    # Data model specification
    element bcf:datamodel {
      # Constants
      element bcf:constants {
        element bcf:constant {
          attribute type { "string" | "list" }?,
          attribute name { text },
          text
        }+
      },
      # Valid entrytypes
      element bcf:entrytypes {
        element bcf:entrytype {
          # Some entrytypes should be completely skipped on output (XDATA etc.)
          attribute skip_output { "true" }?,
          text
        }+
      },
      # BibLaTeX field types. Biber uses this to determine how to output various types
      # to the .bbl
      element bcf:fields {
        element bcf:field {
          # fieldtype is "field" or "list"
          attribute fieldtype { dmfieldtype },
          # format is a specification of the format of the field. If not specified, field contents
          # are just as is. 
          attribute format { "xsv" }?,
          # datatype of field content
          attribute datatype { dmdatatype },
          # Are we allowed to output a null field value to the .bbl for this field?
          attribute nullok { "true" }?,
          # Should this field be skipped and not output to the .bbl?
          attribute skip_output { "true" }?,
          # Field can be used as a label? This auto-generates some defaults in biblatex
          attribute label { "true" }?,
          text
        }+
      },
      # Allowable fields for entrytypes
      # Only one specification per entrytype: even though it might be nice to have several 
      # so that one could share information, this would be hard to manage and confusing as it
      # not be visible in one place which fields were valid for an entrytype.
      element bcf:entryfields {
         element bcf:entrytype { text }*,
         element bcf:field { text }+
      }+,
      # Allowable multiscript fields which can have alternate form/languages
      element bcf:multiscriptfields {
         element bcf:field { text }+
      },
      # Constraints on field (co-)existence and format
      element bcf:constraints {
        # Set of entrytypes that this constraint applies to
        # An entrytype can be specified in multiple constraints
        #
        element bcf:entrytype { text }*,
        # A constraint specification
        element bcf:constraint {
          (
            # Conditional constraints have an antecedent and consequent
            # both of which have a quantifier. This allows you to enforce
            # constraints like:
            #
            # if field a,b,c are all present then one of x,y,z must be
            # if one of field a,b,c are present then none of x,y,z must be
            # etc.
            (attribute type { "conditional" },
              element bcf:antecedent {
                attribute quant { "all" | "one" | "none"},
                element bcf:field { text }+
              },
              element bcf:consequent {
                attribute quant { "all" | "one" | "none"},
                element bcf:field { text }+
              }
            ) |
            # Datatype and format constraints
            (attribute type { "data" },
              # range* attributes are for limiting integer type range
              attribute datatype { "integer" | "isbn" | "issn" | "ismn" | "date" | "pattern" }?,
              attribute rangemin { xsd:int }?,
              attribute rangemax { xsd:int }?,
              attribute pattern { text }?,
              element bcf:field { text }+
            ) |
            # Mandatoriness constraints which say which fields must appear
            (attribute type { "mandatory" },
              (element bcf:field { text } |
                # An XOR set of fields so you can enforce:
                #
                # One (but not more) of fields a,b,c must exist
                element bcf:fieldxor {
                  element bcf:field { text }+
                } |
                # An OR set of fields so you can enforce:
                #
                # One (possibly more) of fields a,b,c must exist
                element bcf:fieldor {
                  element bcf:field { text }+
                }
                )+
              )
            )
          }*
        }+
      }?,
      # Section specifications
      secspec+,
      sorting+,
      listspec+
    }

listspec = 
    element bcf:datalist {
      attribute section { xsd:integer },
      attribute type { "entry" | "list" },
      attribute sortingtemplatename { xsd:string {minLength="1"} },
      attribute sortingnamekeytemplatename { xsd:string {minLength="1"} },
      attribute labelprefix { xsd:string },
      attribute uniquenametemplatename { xsd:string },
      attribute labelalphanametemplatename { xsd:string },      
      # name is only needed for list types
      attribute name { xsd:string {minLength="1"} },
      (filter | filteror )*
    }*

translit =
  element bcf:transliteration {
    attribute entrytype { "*" | xsd:string {minLength="1"} },
    element bcf:translit {
      attribute langids { xsd:string {minLength="1"} }?,
      attribute target { "*" | xsd:string {minLength="1"} },
      attribute from { xsd:string {minLength="1"} },
      attribute to { xsd:string {minLength="1"} }
    }+
  }

uniquenametemplate = 
  element bcf:uniquenametemplate {
    attribute name { xsd:string {minLength="1"} },
    element bcf:namepart {
     attribute order { xsd:integer },
      attribute use { xsd:boolean }?,
      attribute base { xsd:boolean }?,
      attribute disambiguation { "none" | "init" | "initorfull" | "full"}?,
      text
    }+
  }

sortingnamekeytemplate = 
  element bcf:sortingnamekeytemplate {
    attribute name { text },
    attribute visibility { text },
    element bcf:keypart {
     attribute order { xsd:integer },
     element bcf:part {
       attribute type { "namepart" | "literal" },
       attribute order { xsd:integer },
       attribute use { xsd:boolean }?,
       attribute inits { xsd:boolean }?,
        text
      }+
    }+
  }+

sorting = 
  element bcf:sortingtemplate {
    # sorting template name
    attribute name { xsd:string {minLength="1"}},
    # locale for entire sorting specification
    attribute locale { xsd:string {minLength="1"}}?,
    sort+
  }

sort =
  # sort specification
  element bcf:sort {
    # order of this specification in the set of all sort specifications
    attribute order { xsd:integer },
    # Should we stop generating sorting information after this item?
    attribute final { "1" }?,
    # Sort ascending or descending
    attribute sort_direction { "ascending" | "descending" }?,
    # Sort case sensitive or not?
    attribute sortcase { xsd:boolean }?,
    # Sort upper before lower?
    attribute sortupper { xsd:boolean }?,
    # sortset specific override for locale
    attribute locale { xsd:string {minLength="1"}}?,
    # A sort item specification - a field or pseudo-field to get sort information from
    element bcf:sortitem {
      # Is this sortitem a literal string?
      attribute literal { xsd:boolean }?,
      # order of this item in the set of all other item specifications
      attribute order { xsd:integer },
      # Just use a part of the item information for sorting?
      attribute substring_side { "left" | "right" }?,
      attribute substring_width { xsd:integer }?,
      # Pad the item information when sorting with it?
      attribute pad_side { "left" | "right" }?,
      attribute pad_width { xsd:integer }?,
      attribute pad_char { xsd:string { minLength = "1" maxLength = "1" } }?,
      text
    }+
  }+

# Section specification
secspec =
  # data sources
  element bcf:bibdata {
    # which sections the datafiles are for
    attribute section { xsd:integer },
    element bcf:datasource {
      attribute type { "file" },
      attribute datatype { "bibtex" | "biblatexml" }?,
      attribute encoding { text }?,
      attribute glob { "true" | "false" }?,
      xsd:anyURI
    }*
  }?,
  # citekeys or citekey sets in each section
  element bcf:section {
    attribute number { xsd:integer },
    element bcf:citekey {
      ( attribute type { "set" },
        attribute members { xsd:string {minLength="1"}},
        xsd:string {minLength="1"}) |
      ( attribute order { xsd:integer },
        attribute intorder { xsd:integer }?,
        attribute nocite { xsd:boolean }?,
        xsd:string {minLength="1"} )
    }*,
    element bcf:citekeycount {
      attribute count { xsd:integer },
      xsd:string {minLength="1"}
    }*
  }

filteror = element bcf:filteror {
             filter+
           }

filter = element bcf:filter {
           attribute type { "type" | "nottype" | "subtype" | "notsubtype"
                         | "keyword" | "notkeyword" | "field" | "notfield" },
           xsd:string {minLength="1"}
         }

# option definitions
# use<name> options are dynamically determined from data model
usenames =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { xsd:string {pattern = "use.*"} },
    element bcf:value { xsd:boolean }
  }+
useprefix =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "useprefix" },
    element bcf:value { xsd:boolean }
  }
labelalpha =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "labelalpha" },
    element bcf:value { xsd:boolean }
  }
labeltitle =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "labeltitle" },
    element bcf:value { xsd:boolean }
  }
labeltitlespec =
  element bcf:option {
    attribute type { "multivalued" },
    element bcf:key { "labeltitlespec" },
    element bcf:value {
      attribute order { xsd:integer },
      attribute lang { text }?,
      text
    }+
  }
labeltitleyear =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "labeltitleyear" },
    element bcf:value { xsd:boolean }
  }
labeldateparts =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "labeldateparts" },
    element bcf:value { xsd:boolean }
  }
labeldatespec =
  element bcf:option {
    attribute type { "multivalued" },
    element bcf:key { "labeldatespec" },
    element bcf:value {
      attribute order { xsd:integer },
      attribute type { "field" | "string" },
      text
    }+
  }
singletitle =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "singletitle" },
    element bcf:value { xsd:boolean }
  }
skipbib =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "skipbib" },
    element bcf:value { xsd:boolean }
  }
skiplab =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "skiplab" },
    element bcf:value { xsd:boolean }
  }
skiplos =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "skiplos" },
    element bcf:value { xsd:boolean }
  }
skipbiblist =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "skipbiblist" },
    element bcf:value { xsd:boolean }
  }
# false = do not provide uniquelist information
# true = disambiguate lists regardless of year
# minyear = disambiguate lists only when year is the same
uniquelist =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "uniquelist" },
    element bcf:value { "false" | "true" | "minyear" }
  }
nohashothers =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "nohashothers" },
    element bcf:value { xsd:boolean }
  }
noroman =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "noroman" },
    element bcf:value { xsd:boolean }
  }
nosortothers =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "nosortothers" },
    element bcf:value { xsd:boolean }
  }
# false = do not provide uniquename information
# init = disambiguate with initials, only up to maxcitenames/uniquelist
# full (true) = disambiguate with full name or initials, only up to maxcitenames/uniquelist
# allinit = disambiguate with initials, ignore maxcitenames/uniquelist
# allfull = disambiguate with full name or initials, ignore maxcitenames/uniquelist
# mininit = disambiguate with initials, only between identical lists in different entries
# minfull = disambiguate with full name or initials, only between identical lists in different entries
pluralothers =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "pluralothers" },
    element bcf:value { xsd:boolean }
  }
uniquename =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "uniquename" },
    element bcf:value { "false" | "init" | "full" | "allinit" | "allfull" | "mininit" | "minfull" }
  }
uniqueprimaryauthor =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "uniqueprimaryauthor" },
    element bcf:value { xsd:boolean }
  }
uniquetitle =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "uniquetitle" },
    element bcf:value { xsd:boolean }
  }
uniquebaretitle =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "uniquebaretitle" },
    element bcf:value { xsd:boolean }
  }
uniquework =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "uniquework" },
    element bcf:value { xsd:boolean }
  }
julian =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "julian" },
    element bcf:value { xsd:boolean }
  }
gregorianstart =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "gregorianstart" },
    element bcf:value { text }
  }
maxitems =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "maxitems" },
    element bcf:value { xsd:integer }
  }
maxbibnames =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "maxbibnames" },
    element bcf:value { xsd:integer }
  }
maxalphanames =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "maxalphanames" },
    element bcf:value { xsd:integer }
  }
maxcitenames =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "maxcitenames" },
    element bcf:value { xsd:integer }
  }
maxsortnames =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "maxsortnames" },
    element bcf:value { xsd:integer }
  }
minitems =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "minitems" },
    element bcf:value { xsd:integer }
  }
minbibnames =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "minbibnames" },
    element bcf:value { xsd:integer }
  }
minalphanames =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "minalphanames" },
    element bcf:value { xsd:integer }
  }
mincitenames =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "mincitenames" },
    element bcf:value { xsd:integer }
  }
minsortnames =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "minsortnames" },
    element bcf:value { xsd:integer }
  }
sortlocale =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "sortlocale" },
    element bcf:value { text }
  }
sortingtemplatename =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "sortingtemplatename" },
    element bcf:value { text }
  }
sortsets =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "sortsets" },
    element bcf:value { xsd:boolean }
  }
labelnamespec =
  element bcf:option {
    attribute type { "multivalued" },
    element bcf:key { "labelnamespec" },
    element bcf:value {
      attribute order { xsd:integer },
      attribute lang { text }?,
      text
    }+
  }
mincrossrefs =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "mincrossrefs" },
    element bcf:value { xsd:integer }
  }
minxrefs =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "minxrefs" },
    element bcf:value { xsd:integer }
  }
debug =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "debug" },
    element bcf:value { xsd:boolean }
  }
wrapline =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "wrapline" },
    element bcf:value { xsd:integer }
  }  
output_encoding =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "output_encoding" },
    element bcf:value { text }
  }
input_encoding =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "input_encoding" },
    element bcf:value { text }
  }
sortcase =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "sortcase" },
    element bcf:value { xsd:boolean }
  }
alphaothers =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "alphaothers" },
    element bcf:value {
      xsd:normalizedString { pattern = "\S+" }
    }
  }
sortupper = 
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "sortupper" },
    element bcf:value { xsd:boolean }
  }
sortalphaothers =
  element bcf:option {
    attribute type { "singlevalued" },
    element bcf:key { "sortalphaothers" },
    element bcf:value {
      xsd:normalizedString { pattern = "\S+" }
    }
  }

map =
  element bcf:map {
    attribute map_overwrite { xsd:boolean }?,
    attribute map_foreach { xsd:string {minLength="1"} }?,
    attribute refsection { xsd:integer }?,
    element bcf:per_datasource { xsd:string {minLength="1"} }*,
    element bcf:per_type { xsd:string {minLength="1"} }*,
    element bcf:per_nottype { xsd:string {minLength="1"} }*,
    element bcf:map_step {
      (
        ( attribute map_entry_clone { xsd:string {minLength="1"} }
        ) |
        ( attribute map_entry_new { xsd:string {minLength="1"} },
          attribute map_entry_newtype { xsd:string {minLength="1"} }
        ) |
        ( attribute map_entrykey_cited { "1" }?,
          attribute map_entrykey_nocited { "1" }?,
          attribute map_entrykey_citedornocited { "1" }?,
          attribute map_entrykey_allnocited { "1" }?,
          attribute map_entrykey_starnocited { "1" }?,
          attribute map_type_source { xsd:string {minLength="1"} }?,
          attribute map_type_target { xsd:string {minLength="1"} }?,
          attribute map_field_source { xsd:string {minLength="1"} }?,
          attribute map_notfield { xsd:string {minLength="1"} }?,
          attribute map_field_target { xsd:string {minLength="1"} }?,
          attribute map_entrytarget { xsd:string {minLength="1"} }?,
          attribute map_field_set { xsd:string {minLength="1"} }?,
          attribute map_entry_null { "1" }?,
          attribute map_append { "1" }?,
          attribute map_appendstrict { "1" }?,
          attribute map_final { "1" }?,
          attribute map_match { xsd:string {minLength="1"} }?,
          attribute map_matches { xsd:string {minLength="1"} }?,
          attribute map_matchesi { xsd:string {minLength="1"} }?,
          attribute map_matchi { xsd:string {minLength="1"} }?,
          attribute map_notmatch { xsd:string {minLength="1"} }?,
          attribute map_notmatchi { xsd:string {minLength="1"} }?,
          attribute map_replace { xsd:string }?,
          ( attribute map_null { "1" } |
            attribute map_origfield { "1" } |
            attribute map_origfieldval { "1" } |
            attribute map_origentrytype { "1" } |
            attribute map_field_value { xsd:string {minLength="1"} } )?
        )
      ),
      empty
    }+
  }

dmfieldtype =  "field" | "list"
dmdatatype =  "literal" | "name" | "key" | "entrykey" | "date" | "verbatim" | "integer" | "range" | "code" | "uri" | "datepart" | "keyword" | "option"

# Copyright 2009-2012 François Charette and Philip Kime, all rights reserved.
# Copyright 2012-2022 Philip Kime, all rights reserved.

# This code is free software.  You can redistribute it and/or
# modify it under the terms of the Artistic License 2.0.

# This program is distributed in the hope that it will be useful,
# but without any warranty; without even the implied warranty of
# merchantability or fitness for a particular purpose.
