I actually had this regex lying around, I made it a while back as a competition with a friend of mine!
The following is my friend's, and about 20% faster:
^(?!00)((([0-2]\d|3[01])-(0[13578]|1[02])|([0-2]\d|30)-(0[469]|11)|([01]\d|2[0-8])-02)-\d{4}|([01]\d|2\d)-02-(([02468][048]|[13579][26])(?=00)|\d{2}(?!00))([02468][048]|[13579][26]))$
While this one is the shortest (fits on twitter, which was my challenge):
^(?!(00|30-02))(((?=.+(?!00)([02468](?=[048](00)?$)|[13579](?=[26](00)?$)))|(?!29-02))[012]\d|30|31(?!-(0[2469]|11)))-(0[1-9]|1[012])-\d{4}$
Note that both regexes will fail to validate for yyyy = 0000
, it's not a valid year, according to the gregorian calendar.
Both regexes are free of lookbehinds and conditionals, as it had to work in javascript.
EDIT:
Since you need this for XML, I've modified the first regex a bit, it only needed slight modification to get rid of the lookaround.
((0[1-9]|[1-2]\d|3[01])-(0[13578]|1[02])|([0-2]\d|30)-(0[469]|11)|(0[1-9]|1\d|2[0-8])-02)-\d{4}|(0[1-9]|[12]\d)-02-(([02468][048]|[13579][26])00|(\d{2}([02468][48]|[2468][048]|[13579][26])))
I hope this works for you.