Filter data out of long string (vcard)

I'm scanning data from a vcard QR-code. The string I receive always looks something like this:

BEGIN:VCARD
VERSION:2.1
N:Lastname;Firstname
FN:Firstname Lastname
ORG:Lol Group
TITLE:Project Engineer
TEL;WORK:+32 (0)11 12 13 14
ADR;WORK:Industrielaan 1;2250 Olen;Belgium
EMAIL:link.com
URL:http://www.link.com
END:VCARD

I need some data to automatically fill in the form (I'm doing this in jQuery). I need the firstname, lastname, organisation and telephone number.

So I need the data after N, ORG and TEL. But I'm really stuck on how I could do this the best way. Any experience with this and maybe some tips for me?

UPDATE:

The data varies at times. These are the possibilities:

OPTION 1

BEGIN:VCARD
VERSION:3.0
N:lname;fname;;;
FN:fname lname
TITLE:Project manager
EMAIL;type=INTERNET;type=WORK:s.demesqdqs.be
TEL;type=WORK:+3812788105
END:VCARD

OPTION 2

BEGIN:VCARDFN:Barend VercauterenTEL:+32(0)9 329 93 06EMAIL:Barend.Vercauterenëesc.beURL:http://www.esc.beN:Vercauteren;BarendADR:Grote Steenweg 39;9840;De PinteORG:ESC bvbaROLE:sales consultantVERSION:3.0END:VCARD

OPTION 3

BEGIN:VCARDVERSION:2.1N:Deblieck;Tommy;;DhrFN:Tommy DeblieckTITLE:ZaakvoerderORG:QBMT bvbaADR:;;Kleine Pathoekweg 44;Brugge;West-Vlaanderen;8000;Belgi?A0171TEL;WORK;PREF:+32 479302972TEL;CELL:+32 479302972EMAIL:tdëqbmt.beURL:www.qbis.beEND:VCARD

As you can see it can happen that all the text is attached to each other .. .

My code for receiving the correct data with option 1:

var fname = /FN:(.*)/g;
var org = /ORG:(.*)/g;
var tel = /TEL;[^:]*:(.*)/g;

var fullname, firstname, morg, mtel;

fullname = fname.exec(qr_data);
fullname = fullname[1];
var array = fullname.split(' ');
firstname = array[0];
array.shift();

var lastname = '';

if(array.length > 1){
    $.each(array, function(index, item) {
        lastname += item ;
    });
}
else
{
    lastname = array[0];
}

morg = org.exec(qr_data);
mtel = tel.exec(qr_data);

if(firstname)
{
    $("#firstname").val(firstname);
}

if(lastname)
{
    $("#name").val(lastname);
}

if(morg)
{
    $("#company").val(morg[1]);
}

if(mtel)
{
    $("#number").val(mtel[1]);
}

But how can I get these data with the other 2 options?

Answers:

Answer

Use regex to extract the data.

For name = /FN:(.*)/g
For organization = /ORG:(.*)/g
For telephone = /TEL;[^:]*(.*)/g

Check out this fiddle.

var fname = /FN:(.*)/g;
var org = /ORG:(.*)/g;
var tel = /TEL;[^:]*:(.*)/g;
var str = 'BEGIN:VCARD\nVERSION:2.1\nN:Lastname;Firstname\nFN:Firstname Lastname\nORG:Lol Group\nTITLE:Project Engineer\nTEL;WORK:+32 (0)11 12 13 14\nADR;WORK:Industrielaan 1;2250 Olen;Belgium\nEMAIL:link.com\nURL:http://www.link.com\nEND:VCARD';
var mname, morg, mtel;

mname = fname.exec(str);
morg = org.exec(str);
mtel = tel.exec(str);

alert(mname[1]);
alert(morg[1]);
alert(mtel[1]);

Answer

In order to parse a vCard correctly, you cannot rely on a single regex expression. There are some vCard parsers that you can leverage.

Here is an example of using Nilclass vCardJS:

VCF.parse(input, function(vcard) {
  // this function is called with a VCard instance.
  // If the input contains more than one vCard, it is called multiple times.
  console.log("Names: ", JSON.stringify(vcard.n)); // Names
  console.log("Org: ", JSON.stringify(vcard.org)); // Org
  console.log("Tel: ", JSON.stringify(vcard.tel)); // Tel
});

Here are all defined fields:

VCard.allKeys = [
    'fn', 'n', 'nickname', 'photo', 'bday', 'anniversary', 'gender',
    'tel', 'email', 'impp', 'lang', 'tz', 'geo', 'title', 'role', 'logo',
    'org', 'member', 'related', 'categories', 'note', 'prodid', 'rev',
    'sound', 'uid'
];

UPDATE:

Here is a regex that you might try. However, it might not be complete, and you will have to adjust it as you get more different field names in the vCard:

(begin|end|version|cell|adr|nickname|photo|bday|anniversary|gender|tel|email|impp|lang|tz|geo|title|role|logo|org|member|related|categories|note|prodid|rev|sound|uid|fn|n):(.*?)(?=(?:begin|end|version|cell|adr|nickname|photo|bday|anniversary|gender|tel|email|impp|lang|tz|geo|title|role|logo|org|member|related|categories|note|prodid|rev|sound|uid|fn|n):|\n|$)

See demo

The first capturing group will contain a field name and the second will contain the field value. Again, you'd be safer with a dedicated parser.

var re = /(begin|end|version|cell|adr|nickname|photo|bday|anniversary|gender|tel|email|impp|lang|tz|geo|title|role|logo|org|member|related|categories|note|prodid|rev|sound|uid|fn|n):(.*?)(?=(?:begin|end|version|cell|adr|nickname|photo|bday|anniversary|gender|tel|email|impp|lang|tz|geo|title|role|logo|org|member|related|categories|note|prodid|rev|sound|uid|fn|n):|\n|$)/gi; 
var str = 'BEGIN:VCARDVERSION:2.1N:Deblieck;Tommy;;DhrFN:Tommy DeblieckTITLE:ZaakvoerderORG:QBMT bvbaADR:;;Kleine Pathoekweg 44;Brugge;West-Vlaanderen;8000;Belgi?A0171TEL;WORK;PREF:+32 479302972TEL;CELL:+32 479302972EMAIL:tdëqbmt.beURL:www.qbis.beEND:VCARD';
var m;
 
while ((m = re.exec(str)) !== null) {
    if (m.index === re.lastIndex) {
        re.lastIndex++;
    }
    if (m[1].toLowerCase() === "n") {
      document.write("Names: " + m[2] + "<br/>");
    }
    else if (m[1].toLowerCase() === "org") {
      document.write("Org: " + m[2] + "<br/>");
    }
    else if (m[1].toLowerCase().indexOf("tel") === 0 ||
            m[1].toLowerCase().indexOf("cell") === 0) {
      document.write("Tel.: : " + m[2]);
    }
}

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us Javascript

©2020 All rights reserved.