
class MEIBasic {
public:
    static bool IsAllowed(const std::string &element, const std::string &attr)
    {
        if (attr == "xml:id") return true;
        if (!MEIBasic::map.count(element)) return false;
        const std::vector<std::string> &attributes = MEIBasic::map.at(element);
        return (std::find(attributes.begin(), attributes.end(), attr) != attributes.end());
    }

    // clang-format off
    
    inline static std::map<std::string, std::vector<std::string>> map = {
        {"arpeg", {"order", "layer", "plist", "staff", "tstamp", "startid", "arrow", "arrow.shape", "arrow.size", "arrow.color", "arrow.fillcolor", "line.form", "line.width", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}},
        {"beam", {"layer", "staff", "cue"}},
        {"beatRpt", {"beatdef", "layer", "staff", "slash", "expand", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "plist"}},
        {"breath", {"layer", "staff", "startid", "tstamp", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}},
        {"bTrem", {"form", "layer", "staff", "dots", "dur", "num", "num.place", "num.visible", "unitdur"}},
        {"fermata", {"layer", "plist", "staff", "tstamp", "endid", "startid"}},
        {"fTrem", {"form", "layer", "staff", "dots", "dur", "unitdur"}},
        {"gliss", {"layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lsegs", "lwidth"}},
        {"graceGrp", {"attach", "layer", "staff", "grace", "grace.time"}},
        {"hairpin", {"form", "niente", "layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "opening", "closed", "opening.vertical", "angle.optimize", "lform", "lsegs", "lwidth", "place"}},
        {"halfmRpt", {"layer", "staff", "dur", "expand", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}},
        {"harpPedal", {"c", "d", "e", "f", "g", "a", "b", "layer", "plist", "staff", "tstamp", "endid", "startid", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}},
        {"lv", {"layer", "plist", "staff", "tstamp", "endid", "startid", "tstamp2", "curvedir"}},
        {"measure", {"left", "right", "metcon", "n"}},
        {"mNum", {"xml:lang", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}},
        {"mRest", {"cue", "dur", "layer", "staff", "cutout", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}},
        {"mRpt", {"layer", "staff", "num", "expand", "num.place", "num.visible", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}},
        {"multiRest", {"layer", "staff", "num", "block", "num.place", "num.visible", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "width"}},
        {"multiRpt", {"layer", "staff", "num", "expand", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}},
        {"octave", {"coll", "layer", "plist", "staff", "tstamp", "dur", "dis", "dis.place", "endid", "startid", "tstamp2"}},
        {"pedal", {"dir", "func", "layer", "plist", "staff", "tstamp", "endid", "startid", "tstamp2", "form", "lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lsegs", "lwidth", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}},
        {"reh", {"xml:lang", "staff", "startid", "tstamp", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}},
        {"slur", {"layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "curvedir"}},
        {"tie", {"layer", "plist", "staff", "tstamp", "endid", "startid", "tstamp2", "curvedir"}},
        {"tuplet", {"dur", "num", "numbase", "layer", "staff", "endid", "startid", "bracket.place", "bracket.visible", "dur.visible", "num.format", "num.place", "num.visible"}},
        {"mordent", {"form", "long", "layer", "plist", "staff", "tstamp", "endid", "startid", "accidupper", "accidlower", "accidupper.ges", "accidlower.ges", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}},
        {"trill", {"layer", "plist", "staff", "tstamp", "dur", "accidupper", "accidlower", "accidupper.ges", "accidlower.ges", "endid", "startid", "tstamp2", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}},
        {"turn", {"delayed", "form", "layer", "plist", "staff", "tstamp", "accidupper", "accidlower", "accidupper.ges", "accidlower.ges", "startid", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}},
        {"fig", {"halign", "valign"}},
        {"figDesc", {"xml:lang"}},
        {"graphic", {"height", "width", "mimetype", "startid", "ulx", "uly"}},
        {"table", {"xml:lang"}},
        {"td", {"xml:lang", "colspan", "rowspan"}},
        {"th", {"xml:lang", "colspan", "rowspan"}},
        {"tr", {"xml:lang"}},
        {"fing", {"layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "place"}},
        {"fingGrp", {"form", "layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2"}},
        {"expression", {"data"}},
        {"expressionList", {}},
        {"item", {"data"}},
        {"itemList", {}},
        {"manifestation", {"comptype", "data", "recordtype", "singleton"}},
        {"manifestationList", {}},
        {"chordDef", {"tab.pos", "tab.strings"}},
        {"chordMember", {"accid.ges", "pname", "oct", "tab.fing", "tab.fret", "tab.string"}},
        {"chordTable", {}},
        {"f", {"layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "place"}},
        {"fb", {}},
        {"harm", {"chordref", "layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2"}},
        {"availability", {"data"}},
        {"fileDesc", {"corresp"}},
        {"meiHead", {"xml:lang", "type"}},
        {"pubStmt", {}},
        {"titleStmt", {}},
        {"refrain", {"xml:lang", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "voltasym"}},
        {"verse", {"xml:lang", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "voltasym"}},
        {"volta", {"xml:lang", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}},
        {"accMat", {"xml:lang"}},
        {"addDesc", {"xml:lang"}},
        {"binding", {"enddate", "isodate", "notafter", "notbefore", "startdate", "xml:lang", "contemporary"}},
        {"bindingDesc", {"xml:lang"}},
        {"catchwords", {"xml:lang"}},
        {"collation", {"xml:lang"}},
        {"colophon", {"xml:lang"}},
        {"decoDesc", {"xml:lang"}},
        {"decoNote", {"xml:lang"}},
        {"explicit", {"xml:lang"}},
        {"foliation", {"xml:lang"}},
        {"heraldry", {"xml:lang"}},
        {"layout", {"xml:lang", "cols", "ruledlines", "writtenlines", "ruledstaves", "writtenstaves"}},
        {"layoutDesc", {"xml:lang"}},
        {"locus", {"xml:lang", "scheme", "from", "to"}},
        {"locusGrp", {"xml:lang", "scheme"}},
        {"rubric", {"xml:lang", "func"}},
        {"scriptDesc", {"xml:lang"}},
        {"scriptNote", {"xml:lang"}},
        {"seal", {"enddate", "isodate", "notafter", "notbefore", "startdate", "xml:lang", "contemporary"}},
        {"sealDesc", {"xml:lang"}},
        {"secFolio", {"xml:lang"}},
        {"signatures", {"xml:lang"}},
        {"stamp", {"enddate", "isodate", "notafter", "notbefore", "startdate", "xml:lang"}},
        {"support", {"xml:lang"}},
        {"supportDesc", {"xml:lang", "material"}},
        {"typeDesc", {"xml:lang"}},
        {"typeNote", {"xml:lang"}},
        {"addName", {"xml:lang", "nymref", "role", "enddate", "isodate", "notafter", "notbefore", "startdate"}},
        {"bloc", {"xml:lang", "nymref", "role", "enddate", "isodate", "notafter", "notbefore", "startdate"}},
        {"corpName", {"xml:lang", "nymref", "role", "enddate", "isodate", "notafter", "notbefore", "startdate"}},
        {"country", {"xml:lang", "nymref", "role", "enddate", "isodate", "notafter", "notbefore", "startdate"}},
        {"district", {"xml:lang", "nymref", "role", "enddate", "isodate", "notafter", "notbefore", "startdate"}},
        {"famName", {"xml:lang", "nymref", "role", "enddate", "isodate", "notafter", "notbefore", "startdate"}},
        {"foreName", {"xml:lang", "nymref", "role", "enddate", "isodate", "notafter", "notbefore", "startdate"}},
        {"genName", {"xml:lang", "nymref", "role", "enddate", "isodate", "notafter", "notbefore", "startdate"}},
        {"geogFeat", {"xml:lang", "nymref", "role", "enddate", "isodate", "notafter", "notbefore", "startdate"}},
        {"geogName", {"xml:lang", "nymref", "role", "enddate", "isodate", "notafter", "notbefore", "startdate"}},
        {"nameLink", {"xml:lang", "nymref", "role", "enddate", "isodate", "notafter", "notbefore", "startdate"}},
        {"periodName", {"xml:lang", "nymref", "role", "enddate", "isodate", "notafter", "notbefore", "startdate"}},
        {"persName", {"xml:lang", "nymref", "role", "enddate", "isodate", "notafter", "notbefore", "startdate"}},
        {"postBox", {"xml:lang"}},
        {"postCode", {"xml:lang"}},
        {"region", {"xml:lang", "nymref", "role", "enddate", "isodate", "notafter", "notbefore", "startdate"}},
        {"roleName", {"xml:lang", "nymref", "role", "enddate", "isodate", "notafter", "notbefore", "startdate"}},
        {"settlement", {"xml:lang", "nymref", "role", "enddate", "isodate", "notafter", "notbefore", "startdate"}},
        {"street", {"xml:lang"}},
        {"styleName", {"xml:lang", "nymref", "role", "enddate", "isodate", "notafter", "notbefore", "startdate"}},
        {"accid", {"func", "accid", "layer", "plist", "staff", "tstamp", "accid.ges"}},
        {"actor", {"xml:lang"}},
        {"address", {"xml:lang"}},
        {"addrLine", {"xml:lang"}},
        {"ambitus", {"inth"}},
        {"ambNote", {"accid", "dur", "pname", "oct"}},
        {"analytic", {"comptype", "data", "recordtype"}},
        {"arranger", {"xml:lang"}},
        {"artic", {"artic", "layer", "plist", "staff", "tstamp", "onstaff", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}},
        {"author", {"xml:lang"}},
        {"bibl", {"xml:lang"}},
        {"biblList", {"xml:lang"}},
        {"biblScope", {"extent", "unit", "atleast", "atmost", "min", "max", "confidence", "xml:lang", "from", "to"}},
        {"biblStruct", {"data", "xml:lang", "recordtype"}},
        {"body", {}},
        {"caesura", {"layer", "staff", "startid", "tstamp", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}},
        {"caption", {"xml:lang"}},
        {"castGrp", {"xml:lang"}},
        {"castItem", {"xml:lang"}},
        {"castList", {"xml:lang"}},
        {"chord", {"dots", "grace", "grace.time", "cue", "dur", "layer", "staff", "stem.dir", "stem.len", "stem.mod"}},
        {"clef", {"layer", "staff", "cautionary", "shape", "line", "oct", "dis", "dis.place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}},
        {"clefGrp", {"layer", "staff"}},
        {"composer", {"xml:lang"}},
        {"contributor", {"xml:lang", "role"}},
        {"creation", {"enddate", "isodate", "notafter", "notbefore", "startdate", "xml:lang"}},
        {"date", {"calendar", "enddate", "isodate", "notafter", "notbefore", "startdate", "xml:lang"}},
        {"dedicatee", {"xml:lang"}},
        {"depth", {"xml:lang", "quantity", "unit", "atleast", "atmost", "min", "max", "confidence"}},
        {"desc", {"xml:lang"}},
        {"dim", {"xml:lang", "quantity", "unit", "atleast", "atmost", "min", "max", "confidence", "form"}},
        {"dimensions", {"xml:lang", "unit"}},
        {"dir", {"xml:lang", "layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "place"}},
        {"distributor", {"xml:lang"}},
        {"dot", {"form", "layer", "plist", "staff", "tstamp", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}},
        {"dynam", {"layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "place", "xml:lang"}},
        {"edition", {"xml:lang"}},
        {"editor", {"xml:lang"}},
        {"ending", {"lendsym", "lendsym.size", "lstartsym", "lstartsym.size", "lform", "lsegs", "lwidth"}},
        {"event", {"calendar", "enddate", "isodate", "notafter", "notbefore", "startdate", "xml:lang"}},
        {"eventList", {}},
        {"expansion", {"plist"}},
        {"extent", {"xml:lang", "quantity", "unit", "atleast", "atmost", "min", "max", "confidence"}},
        {"funder", {"xml:lang"}},
        {"genre", {"xml:lang"}},
        {"grpSym", {"level", "symbol", "endid", "startid", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}},
        {"head", {"xml:lang"}},
        {"height", {"xml:lang", "quantity", "unit", "atleast", "atmost", "min", "max", "confidence"}},
        {"identifier", {}},
        {"imprint", {}},
        {"incip", {}},
        {"keyAccid", {"accid", "pname", "oct", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "form"}},
        {"label", {"xml:lang"}},
        {"labelAbbr", {"xml:lang"}},
        {"layer", {"n"}},
        {"layerDef", {"n", "trans.diat", "trans.semi", "tune.Hz", "tune.pname", "tune.temper"}},
        {"lb", {}},
        {"lg", {"xml:lang", "layer", "staff", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}},
        {"librettist", {"xml:lang"}},
        {"lyricist", {"xml:lang"}},
        {"mdiv", {"attacca", "n", "label"}},
        {"mei", {"meiversion"}},
        {"monogr", {"data", "recordtype"}},
        {"music", {}},
        {"name", {"xml:lang", "nymref", "role", "enddate", "isodate", "notafter", "notbefore", "startdate", "n", "type"}},
        {"note", {"dots", "cue", "dur", "layer", "staff", "grace", "grace.time", "pname", "oct", "stem.dir", "stem.len", "stem.mod", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "oct.ges", "pname.ges", "tab.fing", "tab.fret", "tab.string"}},
        {"num", {"xml:lang", "unit", "atleast", "atmost", "min", "max", "confidence", "value"}},
        {"ornam", {"layer", "plist", "staff", "tstamp", "dur", "accidupper", "accidlower", "accidupper.ges", "accidlower.ges", "endid", "startid", "tstamp2", "place"}},
        {"p", {"xml:lang"}},
        {"pb", {"folium"}},
        {"pgDesc", {"xml:lang"}},
        {"pgFoot", {"xml:lang", "halign", "func"}},
        {"pgHead", {"xml:lang", "halign", "func"}},
        {"phrase", {"layer", "plist", "staff", "tstamp", "dur", "endid", "startid", "tstamp2", "curvedir"}},
        {"physLoc", {}},
        {"publisher", {"xml:lang"}},
        {"pubPlace", {"xml:lang"}},
        {"recipient", {"xml:lang"}},
        {"relatedItem", {"data", "rel"}},
        {"rend", {"halign", "xml:lang", "altrend", "rend", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "valign", "xml:space", "rotation"}},
        {"repository", {"xml:lang", "nymref", "role", "enddate", "isodate", "notafter", "notbefore", "startdate"}},
        {"resp", {"enddate", "isodate", "notafter", "notbefore", "startdate", "xml:lang"}},
        {"respStmt", {}},
        {"rest", {"dots", "cue", "dur", "layer", "staff", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}},
        {"role", {"xml:lang"}},
        {"roleDesc", {"xml:lang"}},
        {"sb", {"form", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}},
        {"score", {}},
        {"scoreDef", {"key.sig", "meter.count", "meter.unit", "meter.sym"}},
        {"section", {"attacca", "restart"}},
        {"series", {"xml:lang"}},
        {"space", {"dots", "dur", "layer", "staff", "compressable", "cutout"}},
        {"speaker", {"xml:lang"}},
        {"sponsor", {"xml:lang"}},
        {"stack", {"xml:lang", "delim", "align"}},
        {"staff", {"n"}},
        {"staffDef", {"n", "lines", "clef.shape", "clef.line", "clef.dis", "clef.dis.place", "key.sig", "meter.count", "meter.unit", "meter.sym", "trans.diat", "trans.semi", "tab.strings", "tune.Hz", "tune.pname", "tune.temper"}},
        {"staffGrp", {"bar.thru", "symbol"}},
        {"syl", {"xml:lang", "con", "wordpos", "place", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight", "halign"}},
        {"symbol", {"startid", "scale", "fontfam", "fontname", "fontsize", "fontstyle", "fontweight", "letterspacing", "lineheight"}},
        {"tempo", {"xml:lang", "func", "layer", "plist", "staff", "tstamp", "mm", "mm.unit", "mm.dots", "endid", "startid", "tstamp2", "place"}},
        {"term", {"data", "xml:lang"}},
        {"textLang", {"xml:lang", "lang.main", "lang.other"}},
        {"title", {"xml:lang", "n", "level", "type"}},
        {"titlePage", {"xml:lang"}},
        {"titlePart", {"xml:lang", "n", "type"}},
        {"width", {"xml:lang", "quantity", "unit", "atleast", "atmost", "min", "max", "confidence"}},
        {"barre", {"endid", "startid", "fret"}},
        {"argument", {"xml:lang"}},
        {"epigraph", {"xml:lang"}},
        {"imprimatur", {"xml:lang"}},
        {"l", {"xml:lang", "rhythm"}},
        {"li", {"xml:lang"}},
        {"list", {"xml:lang", "n", "form", "type"}},
        {"q", {"xml:lang", "n", "type"}},
        {"quote", {"xml:lang"}},
        {"seg", {"xml:lang"}},
    };

    // clang-format on
};
