diff --git a/compiler2/Type.cc b/compiler2/Type.cc
index bd5d1fc495aea7ea5c1afda2f06b460724905be0..7e2d8bdf1c8ed10573ee96a0bc19ec84abc3d1b8 100644
--- a/compiler2/Type.cc
+++ b/compiler2/Type.cc
@@ -2849,8 +2849,12 @@ namespace Common {
 
       if (NULL != jsonattrib->alias) {
         Type* parent = get_parent_type();
-        if (NULL == parent || (T_SEQ_T != parent->typetype && 
-            T_SET_T != parent->typetype && T_CHOICE_T != parent->typetype)) {
+        if (!legacy_codec_handling &&
+            (NULL == parent || (T_SEQ_T != parent->typetype && 
+            T_SET_T != parent->typetype && T_CHOICE_T != parent->typetype))) {
+          // only report this error when using the new codec handling, otherwise
+          // ignore the attribute (since it can also be set by the XML 'name as ...'
+          // attribute)
           error("Invalid attribute, 'name as ...' requires field of a "
             "record, set or union.");
         }
diff --git a/compiler2/Type_chk.cc b/compiler2/Type_chk.cc
index bb0227ceab31ec6071d4faf8a5568a7c9cb9f873..777e7e12cbcb093ce061e76a32e7e975fb9a1bcf 100644
--- a/compiler2/Type_chk.cc
+++ b/compiler2/Type_chk.cc
@@ -965,10 +965,11 @@ void Type::chk_this_variant(const Ttcn::SingleWithAttrib* swa, bool global)
     }
   }
   else {
-    const string& enc_str = swa->get_attribSpec().get_encoding();
-    MessageEncodingType_t coding = get_enc_type(enc_str);
+    const vector<string>* coding_strings = swa->get_attribSpec().get_encodings();
+    // gather the built-in codecs referred to by the variant's encoding strings
+    vector<MessageEncodingType_t> codings;
     bool erroneous = false;
-    if (enc_str.empty()) {
+    if (coding_strings == NULL) {
       if (t->coding_table.size() > 1) {
         if (!global) {
           swa->error("The encoding reference is mandatory for variant attributes "
@@ -977,129 +978,148 @@ void Type::chk_this_variant(const Ttcn::SingleWithAttrib* swa, bool global)
         erroneous = true;
       }
       else if (t->coding_table[0]->built_in) {
-        coding = t->coding_table[0]->built_in_coding;
+        codings.add(new MessageEncodingType_t(t->coding_table[0]->built_in_coding));
       }
-      else if (strcmp(t->coding_table[0]->custom_coding.name, "PER") == 0) {
-        coding = CT_PER;
+      else { // PER or custom encoding
+        MessageEncodingType_t coding =
+          strcmp(t->coding_table[0]->custom_coding.name, "PER") == 0 ?
+          CT_PER : CT_CUSTOM;
+        swa->warning("Variant attributes related to %s encoding are ignored",
+          get_encoding_name(coding));
       }
-      // else leave it as CT_CUSTOM
     }
     else {
-      if (!has_encoding(coding, &enc_str)) {
-        erroneous = true;
-        if (!global) {
-          if (coding != CT_CUSTOM) {
-            swa->error("Type `%s' does not support %s encoding",
-              get_typename().c_str(), get_encoding_name(coding));
-          }
-          else {
-            swa->error("Type `%s' does not support custom encoding `%s'",
-              get_typename().c_str(), enc_str.c_str());
+      for (size_t i = 0; i < coding_strings->size(); ++i) {
+        const string& enc_str = *(*coding_strings)[i];
+        MessageEncodingType_t coding = get_enc_type(enc_str);
+        if (!has_encoding(coding, &enc_str)) {
+          erroneous = true;
+          if (!global) {
+            if (coding != CT_CUSTOM) {
+              swa->error("Type `%s' does not support %s encoding",
+                get_typename().c_str(), get_encoding_name(coding));
+            }
+            else {
+              swa->error("Type `%s' does not support custom encoding `%s'",
+                get_typename().c_str(), enc_str.c_str());
+            }
           }
         }
+        else if (coding != CT_PER && coding != CT_CUSTOM) {
+          codings.add(new MessageEncodingType_t(coding));
+        }
+        else { // PER or custom encoding
+          swa->warning("Variant attributes related to %s encoding are ignored",
+            get_encoding_name(coding));
+        }
       }
     }
-    if (!erroneous && coding != CT_PER && coding != CT_CUSTOM) {
-      bool new_ber = false;    // a BerAST object was allocated here
-      bool new_raw = false;    // a RawAST object was allocated here
-      bool new_text = false;   // a TextAST object was allocated here
-      bool new_xer = false;    // a XerAttribute object was allocated here
-      bool new_json = false;   // a JsonAST object was allocated here
-      bool ber_found = false;  // a BER attribute was found by the parser
-      bool raw_found = false;  // a RAW attribute was found by the parser
-      bool text_found = false; // a TEXT attribute was found by the parser
-      bool xer_found = false;  // a XER attribute was found by the parser
-      bool json_found = false; // a JSON attribute was found by the parser
-      if (berattrib == NULL) {
-        berattrib = new BerAST;
-        new_ber = true;
-      }
-      if (rawattrib == NULL) {
-        Type* t_refd = this;
-        while (t_refd->rawattrib == NULL && t_refd->is_ref()) {
-          t_refd = t_refd->get_type_refd();
+    if (!erroneous && codings.size() != 0) {
+      for (size_t i = 0; i < codings.size(); ++i) {
+        MessageEncodingType_t coding = *codings[i];
+        bool new_ber = false;    // a BerAST object was allocated here
+        bool new_raw = false;    // a RawAST object was allocated here
+        bool new_text = false;   // a TextAST object was allocated here
+        bool new_xer = false;    // a XerAttribute object was allocated here
+        bool new_json = false;   // a JsonAST object was allocated here
+        bool ber_found = false;  // a BER attribute was found by the parser
+        bool raw_found = false;  // a RAW attribute was found by the parser
+        bool text_found = false; // a TEXT attribute was found by the parser
+        bool xer_found = false;  // a XER attribute was found by the parser
+        bool json_found = false; // a JSON attribute was found by the parser
+        if (berattrib == NULL) {
+          berattrib = new BerAST;
+          new_ber = true;
         }
-        rawattrib = new RawAST(t_refd->rawattrib, get_default_raw_fieldlength());
-        new_raw = true;
-      }
-      if (textattrib == NULL) {
-        Type* t_refd = this;
-        while (t_refd->textattrib == NULL && t_refd->is_ref()) {
-          t_refd = t_refd->get_type_refd();
+        if (rawattrib == NULL) {
+          Type* t_refd = this;
+          while (t_refd->rawattrib == NULL && t_refd->is_ref()) {
+            t_refd = t_refd->get_type_refd();
+          }
+          rawattrib = new RawAST(t_refd->rawattrib, get_default_raw_fieldlength());
+          new_raw = true;
         }
-        textattrib = new TextAST(t_refd->textattrib);
-        new_text = true;
-      }
-      if (xerattrib == NULL) {
-        xerattrib = new XerAttributes;
-        new_xer = true;
-      }
-      if (jsonattrib == NULL) {
-        Type* t_refd = this;
-        while (t_refd->jsonattrib == NULL && t_refd->is_ref()) {
-          t_refd = t_refd->get_type_refd();
+        if (textattrib == NULL) {
+          Type* t_refd = this;
+          while (t_refd->textattrib == NULL && t_refd->is_ref()) {
+            t_refd = t_refd->get_type_refd();
+          }
+          textattrib = new TextAST(t_refd->textattrib);
+          new_text = true;
         }
-        jsonattrib = new JsonAST(t_refd->jsonattrib);
-        new_json = true;
-      }
-      int ret = parse_rawAST(rawattrib, textattrib, xerattrib, berattrib, jsonattrib,
-        swa->get_attribSpec(), get_length_multiplier(), my_scope->get_scope_mod(), 
-        raw_found, text_found, xer_found, ber_found, json_found, coding);
-      bool mismatch = false;
-      if (ber_found || raw_found || text_found || xer_found || json_found) {
-        switch (coding) {
-        case CT_BER:
-          mismatch = !ber_found;
-          break;
-        case CT_RAW:
-          mismatch = !raw_found;
-          break;
-        case CT_TEXT:
-          mismatch = !text_found;
-          break;
-        case CT_XER:
-          mismatch = !xer_found;
-          break;
-        case CT_JSON:
-          mismatch = !json_found;
-          break;
-        default:
-          FATAL_ERROR("Type::chk_this_variant");
-          break;
+        if (xerattrib == NULL) {
+          xerattrib = new XerAttributes;
+          new_xer = true;
         }
-      }
-      if (mismatch && ret == 0) {
-        if (!global || !enc_str.empty()) {
-          // don't display this if there were parsing errors in the variant 
-          // attribute, or if it was empty
-          swa->error("Variant attribute is not related to %s encoding",
-            get_encoding_name(coding));
+        if (jsonattrib == NULL) {
+          Type* t_refd = this;
+          while (t_refd->jsonattrib == NULL && t_refd->is_ref()) {
+            t_refd = t_refd->get_type_refd();
+          }
+          jsonattrib = new JsonAST(t_refd->jsonattrib);
+          new_json = true;
+        }
+        int ret = parse_rawAST(rawattrib, textattrib, xerattrib, berattrib, jsonattrib,
+          swa->get_attribSpec(), get_length_multiplier(), my_scope->get_scope_mod(), 
+          raw_found, text_found, xer_found, ber_found, json_found, coding);
+        bool mismatch = false;
+        if (ber_found || raw_found || text_found || xer_found || json_found) {
+          switch (coding) {
+          case CT_BER:
+            mismatch = !ber_found;
+            break;
+          case CT_RAW:
+            mismatch = !raw_found;
+            break;
+          case CT_TEXT:
+            mismatch = !text_found;
+            break;
+          case CT_XER:
+            mismatch = !xer_found;
+            break;
+          case CT_JSON:
+            mismatch = !json_found;
+            break;
+          default:
+            FATAL_ERROR("Type::chk_this_variant");
+            break;
+          }
+        }
+        if (mismatch && ret == 0) {
+          if (!global || coding_strings != NULL) {
+            // don't display this if there were parsing errors in the variant 
+            // attribute, or if it didn't have encoding strings
+            swa->error("Variant attribute is not related to %s encoding",
+              get_encoding_name(coding));
+          }
+        }
+        if (new_ber && !ber_found) {
+          delete berattrib;
+          berattrib = NULL;
+        }
+        if (new_raw && !raw_found) {
+          delete rawattrib;
+          rawattrib = NULL;
+        }
+        if (new_text && !text_found) {
+          delete textattrib;
+          textattrib = NULL;
+        }
+        if (new_xer && !xer_found) {
+          delete xerattrib;
+          xerattrib = NULL;
+        }
+        if (new_json && !json_found) {
+          delete jsonattrib;
+          jsonattrib = NULL;
         }
-      }
-      if (new_ber && !ber_found) {
-        delete berattrib;
-        berattrib = NULL;
-      }
-      if (new_raw && !raw_found) {
-        delete rawattrib;
-        rawattrib = NULL;
-      }
-      if (new_text && !text_found) {
-        delete textattrib;
-        textattrib = NULL;
-      }
-      if (new_xer && !xer_found) {
-        delete xerattrib;
-        xerattrib = NULL;
-      }
-      if (new_json && !json_found) {
-        delete jsonattrib;
-        jsonattrib = NULL;
       }
     }
-    else if (!erroneous && !global) { // PER or custom encoding
-      swa->warning("Variant attributes related to %s encoding are ignored",
-        get_encoding_name(coding));
+    if (codings.size() != 0) {
+      for (size_t i = 0; i < codings.size(); ++i) {
+        delete codings[i];
+      }
+      codings.clear();
     }
   } // if t != NULL
   if (global) {
diff --git a/compiler2/ttcn3/Attributes.cc b/compiler2/ttcn3/Attributes.cc
index 7629ed47a2f80f3d360e3bec3dcd3d2100c30aaf..1ff202ceb5ea73679e5301c98a2f32758a101d5c 100644
--- a/compiler2/ttcn3/Attributes.cc
+++ b/compiler2/ttcn3/Attributes.cc
@@ -883,6 +883,17 @@ namespace Ttcn {
   }
 
   // ==== AttributeSpec ====
+  
+  AttributeSpec::~AttributeSpec()
+  {
+    if (encodings != NULL) {
+      for (size_t i = 0; i < encodings->size(); ++i) {
+        delete (*encodings)[i];
+      }
+      encodings->clear();
+      delete encodings;
+    }
+  }
 
   AttributeSpec* AttributeSpec::clone() const
   {
@@ -897,8 +908,15 @@ namespace Ttcn {
   void AttributeSpec::dump(unsigned level) const
   {
     DEBUG(level,"spec: %s", spec.c_str());
-    if (!encoding.empty()) {
-      DEBUG(level, "encoding: %s", encoding.c_str());
+    if (encodings != NULL) {
+      string res;
+      for (size_t i = 0; i < encodings->size(); ++i) {
+        if (i != 0) {
+          res += ", ";
+        }
+        res += *(*encodings)[i];
+      }
+      DEBUG(level, "encoding(s): %s", res.c_str());
     }
   }
 
@@ -1203,7 +1221,7 @@ namespace Ttcn {
             "attributes. Modifier ignored.");
         }
       }
-      if (!temp_attrib->get_attribSpec().get_encoding().empty() &&
+      if (temp_attrib->get_attribSpec().get_encodings() != NULL &&
           (legacy_codec_handling ||
            temp_attrib->get_attribKeyword() != SingleWithAttrib::AT_VARIANT)) {
         temp_attrib->error("Invalid attribute format. Dot notation is only "
diff --git a/compiler2/ttcn3/Attributes.hh b/compiler2/ttcn3/Attributes.hh
index 375383d1513385a4890ef83185e08c6341337284..700eb59f1ffc871265983f9cc95f318876e5628f 100644
--- a/compiler2/ttcn3/Attributes.hh
+++ b/compiler2/ttcn3/Attributes.hh
@@ -221,7 +221,7 @@ namespace Ttcn {
     void chk();
     ErroneousDescriptor* get_err_descr() const { return err_descr_tree; }    
   };
-
+  
   /**
    * Stores the attribute specification and its location
    */
@@ -230,20 +230,20 @@ namespace Ttcn {
     AttributeSpec& operator=(const AttributeSpec& p);
   private:
     string spec; ///< The attribute specification (free text)
-    string encoding; ///< Encoding specification for variant attributes (free text)
-    // TODO: check that the variant indeed belongs to the specified encoding
+    vector<string>* encodings; ///< Encoding specifications for variant attributes (free text)
     /// Copy constructor, for clone() only
     AttributeSpec(const AttributeSpec& p)
-      : Node(p), Location(p), spec(p.spec), encoding(p.encoding) { }
+      : Node(p), Location(p), spec(p.spec), encodings(p.encodings) { }
   public:
     AttributeSpec(const string& p_spec)
-      : Node(), Location(), spec(p_spec), encoding() { }
-    AttributeSpec(const string& p_spec, const string& p_encoding)
-      : Node(), Location(), spec(p_spec), encoding(p_encoding) { }
+      : Node(), Location(), spec(p_spec), encodings(NULL) { }
+    AttributeSpec(const string& p_spec, vector<string>* p_encodings)
+      : Node(), Location(), spec(p_spec), encodings(p_encodings) { }
+    ~AttributeSpec();
     virtual AttributeSpec* clone() const;
     virtual void set_fullname(const string& p_fullname);
     const string& get_spec() const { return spec; }
-    const string& get_encoding() const { return encoding; }
+    const vector<string>* get_encodings() const { return encodings; }
     virtual void dump(unsigned level) const;
   };
 
diff --git a/compiler2/ttcn3/compiler.y b/compiler2/ttcn3/compiler.y
index b91c77073f98faae76bd77af737854fc68482bd4..f396e1040ecaaecef9ef981f7dad69ef7e0ce5cc 100644
--- a/compiler2/ttcn3/compiler.y
+++ b/compiler2/ttcn3/compiler.y
@@ -217,6 +217,7 @@ static const string anyname("anytype");
   param_eval_t eval;
   TypeMappingTargets *typemappingtargets;
   attribute_modifier_t attrib_mod;
+  vector<string>* string_vector;
 
   struct {
     bool is_raw;
@@ -1130,6 +1131,7 @@ AllOrTypeListWithTo TypeListWithFrom TypeListWithTo
 %type <single_value_redirect_list> SingleValueSpecList
 %type <typemappingtargets> WithList
 %type <reference_list> PortTypeList
+%type <string_vector> AttribSpecEncodings
 
 /*********************************************************************
  * Destructors
@@ -1490,6 +1492,7 @@ Quadruple
 AllowedValues
 optSubTypeSpec
 seqValueOrRange
+AttribSpecEncodings
 
 %destructor {
   for(size_t i=0; i<$$.nElements; i++) delete $$.elements[i];
@@ -8331,11 +8334,34 @@ AttribSpec: // 542
   }
 | FreeText '.' FreeText
   {
-    $$ = new AttributeSpec(string($3), string($1));
+    vector<string>* v = new vector<string>;
+    v->add(new string($1));
+    $$ = new AttributeSpec(string($3), v);
     $$->set_location(infile, @$);
     Free($1);
     Free($3);
   }
+| '{' AttribSpecEncodings '}' '.' FreeText
+  {
+    $$ = new AttributeSpec(string($5), $2);
+    $$->set_location(infile, @$);
+    Free($5);
+  }
+;
+
+AttribSpecEncodings:
+  FreeText
+  {
+    $$ = new vector<string>;
+    $$->add(new string($1));
+    Free($1);
+  }
+| AttribSpecEncodings ',' FreeText
+  {
+    $$ = $1;
+    $$->add(new string($3));
+    Free($3);
+  }
 ;
 
 /* A.1.6.7 Behaviour statements */
diff --git a/compiler2/ttcn3/rawAST.y b/compiler2/ttcn3/rawAST.y
index 791b38b787ae4ff46a22fcf463a3b3ed24b466ca..94baf56fc181c788a64c42410e32dbf34d21c4d1 100644
--- a/compiler2/ttcn3/rawAST.y
+++ b/compiler2/ttcn3/rawAST.y
@@ -1364,7 +1364,7 @@ XERattribute:
         // this handles the "name as '...' " attributes for both the XER and
         // JSON codecs
         // (overwrites any previously set name)
-        if (selected_codec == Common::Type::CT_XER) {
+        if (selected_codec == Common::Type::CT_XER || legacy_codec_handling) {
           switch (xerstruct->name_.kw_) {
           case NamespaceSpecification::NO_MANGLING:
           case NamespaceSpecification::CAPITALIZED:
@@ -1377,7 +1377,7 @@ XERattribute:
           }
           xerstruct->name_.nn_ = $1;
         }
-        else {
+        if (selected_codec != Common::Type::CT_XER) {
           // treat XML special values and real strings separately
           XerAttributes::NameChange special;
           special.nn_ = $1;
@@ -1397,9 +1397,17 @@ XERattribute:
             }
             break;
           default: // it's a real string
-            if (selected_codec == Common::Type::CT_JSON) {
+            if (selected_codec == Common::Type::CT_JSON ||
+                legacy_codec_handling) {
               Free(jsonstruct->alias);
-              jsonstruct->alias = $1;
+              if (legacy_codec_handling) {
+                // in this case the string is saved in both the XML and JSON
+                // structs, so we can't use the same string
+                jsonstruct->alias = mcopystr($1);
+              }
+              else {
+                jsonstruct->alias = $1;
+              }
               json_f = true;
             }
             else {
diff --git a/regression_test/multipleEncodings/Testcases.ttcn b/regression_test/multipleEncodings/Testcases.ttcn
index 260a7dc05f8c3fc7eabb8e2afc554052fc1d9288..599527540f363cdd25de43ecff94f3514700725d 100644
--- a/regression_test/multipleEncodings/Testcases.ttcn
+++ b/regression_test/multipleEncodings/Testcases.ttcn
@@ -476,6 +476,38 @@ testcase tc_ttcn_codec_switch() runs on CT {
   setverdict(pass);
 }
 
+// Testing the 'name as ...' attribute applied to multiple codecs using only one variant attribute
+testcase tc_ttcn_multi_attrib() runs on CT {
+  var S x := { num := 12, str := "abc" };
+  
+  // JSON encoding & decoding
+  var universal charstring exp := "{\"int\":12,\"str\":\"abc\"}";
+  var universal charstring enc1 := encvalue_unichar(x, "UTF-8", "", "JSON");
+  if (exp != enc1) {
+    setverdict(fail, "JSON encoding failed. Expected: ", exp, ", got: ", enc1);
+  }
+  
+  var S dec1;
+  var integer res := decvalue_unichar(enc1, dec1, "UTF-8", "", "JSON");
+  if (x != dec1) {
+    setverdict(fail, "JSON decoding failed. Expected: ", x, ", got: ", dec1);
+  }
+  
+  // XML encoding & decoding
+  exp := "<S>\n\t<int>12</int>\n\t<str>abc</str>\n</S>\n\n";
+  var universal charstring enc2 := encvalue_unichar(x, "UTF-8", "", "XML");
+  if (exp != enc2) {
+    setverdict(fail, "XML encoding test failed. Expected: ", exp, ", got: ", enc2);
+  }
+  
+  var S dec2;
+  res := decvalue_unichar(enc2, dec2, "UTF-8", "", "XML");
+  if (x != dec2) {
+    setverdict(fail, "XML decoding test failed. Expected: ", x, ", got: ", dec2);
+  }
+  setverdict(pass);
+}
+
 control {
   execute(tc_ttcn_encvalue());
   execute(tc_ttcn_encvalue_negtest());
@@ -495,6 +527,7 @@ control {
   execute(tc_asn_setencode_per());
   execute(tc_asn_setencode_negtest());
   execute(tc_ttcn_codec_switch());
+  execute(tc_ttcn_multi_attrib());
 }
 
 }
diff --git a/regression_test/multipleEncodings/TtcnTypes.ttcn b/regression_test/multipleEncodings/TtcnTypes.ttcn
index cfee27c6ccc1c1e0b397c3c07dcbab10d24011fd..aa2b8cc34d526cc66c53293503a3f2257609e139 100644
--- a/regression_test/multipleEncodings/TtcnTypes.ttcn
+++ b/regression_test/multipleEncodings/TtcnTypes.ttcn
@@ -56,6 +56,16 @@ with {
   encode "JSON";
 }
 
+type set S {
+  integer num,
+  charstring str
+}
+with {
+  encode "JSON";
+  encode "XML";
+  variant (num) {"JSON", "XML"}."name as 'int'";
+}
+
 type record Msg {
   bitstring data
 }