Implement interest Exclude to_ccnb and from_ccnb.
diff --git a/js/Interest.js b/js/Interest.js
index e01f600..3d91de5 100644
--- a/js/Interest.js
+++ b/js/Interest.js
@@ -118,90 +118,72 @@
     return this.name.match(name);
 }
 
-/**
- * Exclude
+/*
+ * Handle the interest Exclude element.
+ * _values is an array where each element is either Uint8Array component or Exclude.ANY.
  */
-var Exclude = function Exclude(_values){ 
-	this.OPTIMUM_FILTER_SIZE = 100;
-	this.values = _values; //array of elements
+var Exclude = function Exclude(_values) { 
+	this.values = (_values || []);
 }
 
+Exclude.ANY = "*";
+
 Exclude.prototype.from_ccnb = function(/*XMLDecoder*/ decoder) {
-		decoder.readStartElement(this.getElementLabel());
+	decoder.readStartElement(CCNProtocolDTags.Exclude);
 
-		//TODO APPLY FILTERS/EXCLUDE.  For now, just skip the element.
-        var structureDecoder = new BinaryXMLStructureDecoder();
-        structureDecoder.seek(decoder.offset);
-        if (!structureDecoder.findElementEnd(decoder.istream))
-            throw new ContentDecodingException(new Error("Cannot find the end of interest Exclude element"));
-        decoder.seek(structureDecoder.offset);
+	while (true) {
+        if (decoder.peekStartElement(CCNProtocolDTags.Component))
+            this.values.push(decoder.readBinaryElement(CCNProtocolDTags.Component));
+        else if (decoder.peekStartElement(CCNProtocolDTags.Any)) {
+            decoder.readStartElement(CCNProtocolDTags.Any);
+            decoder.readEndElement();
+            this.values.push(Exclude.ANY);
+        }
+        else if (decoder.peekStartElement(CCNProtocolDTags.Bloom)) {
+            // Skip the Bloom and treat it as Any.
+            decoder.readBinaryElement(CCNProtocolDTags.Bloom);
+            this.values.push(Exclude.ANY);
+        }
+        else
+            break;
+	}
+    
+    decoder.readEndElement();
+};
+
+Exclude.prototype.to_ccnb = function(/*XMLEncoder*/ encoder)  {
+	if (this.values == null || this.values.length == 0)
+		return;
+
+	encoder.writeStartElement(CCNProtocolDTags.Exclude);
+    
+    // TODO: Do we want to order the components (except for ANY)?
+    for (var i = 0; i < this.values.length; ++i) {
+        if (this.values[i] == Exclude.ANY) {
+            encoder.writeStartElement(CCNProtocolDTags.Any);
+            encoder.writeEndElement();
+        }
+        else
+            encoder.writeElement(CCNProtocolDTags.Component, this.values[i]);
+    }
+
+	encoder.writeEndElement();
+};
+
+// Return a string with elements separated by "," and Exclude.ANY shown as "*".
+Exclude.prototype.to_uri = function() {
+	if (this.values == null || this.values.length == 0)
+		return "";
+
+    var result = "";
+    for (var i = 0; i < this.values.length; ++i) {
+        if (i > 0)
+            result += ",";
         
-		//TODO 
-		/*var component;
-		var any = false;
-		while ((component = decoder.peekStartElement(CCNProtocolDTags.Component)) || 
-				(any = decoder.peekStartElement(CCNProtocolDTags.Any)) ||
-					decoder.peekStartElement(CCNProtocolDTags.Bloom)) {
-			var ee = component?new ExcludeComponent(): any ? new ExcludeAny() : new BloomFilter();
-			ee.decode(decoder);
-			_values.add(ee);
-		}*/
+        if (this.values[i] == Exclude.ANY)
+            result += "*";
+        else
+            result += Name.toEscapedString(this.values[i]);
+    }
+    return result;
 };
-
-Exclude.prototype.to_ccnb=function(/*XMLEncoder*/ encoder)  {
-		if (!validate()) {
-			throw new ContentEncodingException("Cannot encode " + this.getClass().getName() + ": field values missing.");
-		}
-
-		if (empty())
-			return;
-
-		encoder.writeStartElement(getElementLabel());
-
-		encoder.writeEndElement();
-		
-	};
-
-Exclude.prototype.getElementLabel = function() { return CCNProtocolDTags.Exclude; };
-
-
-/**
- * ExcludeAny
- */
-var ExcludeAny = function ExcludeAny() {
-
-};
-
-ExcludeAny.prototype.from_ccnb = function(decoder) {
-		decoder.readStartElement(this.getElementLabel());
-		decoder.readEndElement();
-};
-
-
-ExcludeAny.prototype.to_ccnb = function( encoder) {
-		encoder.writeStartElement(this.getElementLabel());
-		encoder.writeEndElement();
-};
-
-ExcludeAny.prototype.getElementLabel=function() { return CCNProtocolDTags.Any; };
-
-
-/**
- * ExcludeComponent
- */
-var ExcludeComponent = function ExcludeComponent(_body) {
-
-	//TODO Check BODY is an Array of componenets.
-	
-	this.body = _body
-};
-
-ExcludeComponent.prototype.from_ccnb = function( decoder)  {
-		this.body = decoder.readBinaryElement(this.getElementLabel());
-};
-
-ExcludeComponent.prototype.to_ccnb = function(encoder) {
-		encoder.writeElement(this.getElementLabel(), this.body);
-};
-
-ExcludeComponent.prototype.getElementLabel = function() { return CCNProtocolDTags.Component; };
diff --git a/js/ndnProtocol.xpi b/js/ndnProtocol.xpi
index 5e35f8b..cdb2110 100644
--- a/js/ndnProtocol.xpi
+++ b/js/ndnProtocol.xpi
Binary files differ
diff --git a/js/ndnProtocol/modules/ndn-js.jsm b/js/ndnProtocol/modules/ndn-js.jsm
index fd2e31f..35e47ba 100644
--- a/js/ndnProtocol/modules/ndn-js.jsm
+++ b/js/ndnProtocol/modules/ndn-js.jsm
@@ -48,7 +48,7 @@
 "WrappingKeyName","Action","FaceID","IPProto","Host","Port","MulticastInterface","ForwardingFlags","FaceInstance","ForwardingEntry","MulticastTTL","MinSuffixComponents","MaxSuffixComponents","ChildSelector","RepositoryInfo","Version","RepositoryVersion","GlobalPrefix","LocalName","Policy","Namespace","GlobalPrefixName","PolicyVersion","KeyValueSet","KeyValuePair","IntegerValue","DecimalValue","StringValue","BinaryValue","NameValue","Entry","ACL","ParameterizedName","Prefix","Suffix","Root","ProfileName",
 "Parameters","InfoString",null,"StatusResponse","StatusCode","StatusText","SyncNode","SyncNodeKind","SyncNodeElement","SyncVersion","SyncNodeElements","SyncContentHash","SyncLeafCount","SyncTreeDepth","SyncByteCount","ConfigSlice","ConfigSliceList","ConfigSliceOp"],CCNTime=function(a){this.NANOS_MAX=999877929;"number"==typeof a?this.msec=a:1<LOG&&console.log("UNRECOGNIZED TYPE FOR TIME")};CCNTime.prototype.getJavascriptDate=function(){var a=new Date;a.setTime(this.msec);return a};
 var Name=function Name(b){if("string"==typeof b)3<LOG&&console.log("Content Name String "+b),this.components=Name.createNameArray(b);else if("object"===typeof b){4<LOG&&console.log("Content Name Array "+b);this.components=[];for(var c=0;c<b.length;++c)this.add(b[c])}else null==b?this.components=[]:1<LOG&&console.log("NO CONTENT NAME GIVEN")};Name.prototype.getName=function(){return this.to_uri()};
-Name.createNameArray=function(a){a=a.trim();if(0>=a.length)return[];var b=a.indexOf(":");if(0<=b){var c=a.indexOf("/");if(0>c||b<c)a=a.substr(b+1,a.length-b-1).trim()}if("/"==a[0])if(2<=a.length&&"/"==a[1]){b=a.indexOf("/",2);if(0>b)return[];a=a.substr(b+1,a.length-b-1).trim()}else a=a.substr(1,a.length-1).trim();a=a.split("/");for(b=0;b<a.length;++b){c=unescape(a[b].trim());if(null==c.match(/[^.]/))if(2>=c.length){a.splice(b,1);--b;continue}else a[b]=c.substr(3,c.length-3);else a[b]=c;a[b]=DataUtils.toNumbersFromString(a[b])}return a};
+Name.createNameArray=function(a){a=a.trim();if(0>=a.length)return[];var b=a.indexOf(":");if(0<=b){var c=a.indexOf("/");if(0>c||b<c)a=a.substr(b+1,a.length-b-1).trim()}if("/"==a[0])if(2<=a.length&&"/"==a[1]){b=a.indexOf("/",2);if(0>b)return[];a=a.substr(b+1,a.length-b-1).trim()}else a=a.substr(1,a.length-1).trim();a=a.split("/");for(b=0;b<a.length;++b)c=Name.fromEscapedString(a[b]),null==c?(a.splice(b,1),--b):a[b]=c;return a};
 Name.prototype.from_ccnb=function(a){a.readStartElement(this.getElementLabel());for(this.components=[];a.peekStartElement(CCNProtocolDTags.Component);)this.add(a.readBinaryElement(CCNProtocolDTags.Component));a.readEndElement()};Name.prototype.to_ccnb=function(a){if(null==this.components)throw Error("CANNOT ENCODE EMPTY CONTENT NAME");a.writeStartElement(this.getElementLabel());for(var b=this.components.length,c=0;c<b;c++)a.writeElement(CCNProtocolDTags.Component,this.components[c]);a.writeEndElement()};
 Name.prototype.getElementLabel=function(){return CCNProtocolDTags.Name};
 Name.prototype.add=function(a){var b;if("string"==typeof a)b=DataUtils.stringToUtf8Array(a);else if("object"==typeof a&&a instanceof Uint8Array)b=new Uint8Array(a);else if("object"==typeof a&&a instanceof ArrayBuffer)b=new Uint8Array(new ArrayBuffer(a.byteLength)),b.set(new Uint8Array(a));else if("object"==typeof a)b=new Uint8Array(a);else throw Error("Cannot add Name element at index "+this.components.length+": Invalid type");return this.components.push(b)};
@@ -57,7 +57,8 @@
 Name.prototype.getContentDigestValue=function(){for(var a=this.components.length-1;0<=a;--a){var b=Name.getComponentContentDigestValue(this.components[a]);if(null!=b)return b}return null};
 Name.getComponentContentDigestValue=function(a){return a.length==Name.ContentDigestPrefix.length+32+Name.ContentDigestSuffix.length&&DataUtils.arraysEqual(a.subarray(0,Name.ContentDigestPrefix.length),Name.ContentDigestPrefix)&&DataUtils.arraysEqual(a.subarray(a.length-Name.ContentDigestSuffix.length,a.length),Name.ContentDigestSuffix)?a.subarray(Name.ContentDigestPrefix.length,Name.ContentDigestPrefix.length+32):null};Name.ContentDigestPrefix=new Uint8Array([193,46,77,46,71,193,1,170,2,133]);
 Name.ContentDigestSuffix=new Uint8Array([0]);Name.toEscapedString=function(a){for(var b="",c=!1,d=0;d<a.length;++d)if(46!=a[d]){c=!0;break}if(c)for(d=0;d<a.length;++d)c=a[d],b=48<=c&&57>=c||65<=c&&90>=c||97<=c&&122>=c||43==c||45==c||46==c||95==c?b+String.fromCharCode(c):b+("%"+(16>c?"0":"")+c.toString(16).toUpperCase());else{b="...";for(d=0;d<a.length;++d)b+="."}return b};
-Name.prototype.match=function(a){var b=this.components,a=a.components;if(b.length>a.length)return!1;for(var c=0;c<b.length;++c)if(!DataUtils.arraysEqual(b[c],a[c]))return!1;return!0};var ContentObject=function(a,b,c,d){this.name="string"==typeof a?new Name(a):a;this.signedInfo=b;this.content="string"==typeof c?DataUtils.toNumbersFromString(c):c;this.signature=d;this.rawSignatureData=this.endContent=this.endSIG=this.startSIG=null};
+Name.fromEscapedString=function(a){a=unescape(a.trim());return null==a.match(/[^.]/)?2>=a.length?null:DataUtils.toNumbersFromString(a.substr(3,a.length-3)):DataUtils.toNumbersFromString(a)};Name.prototype.match=function(a){var b=this.components,a=a.components;if(b.length>a.length)return!1;for(var c=0;c<b.length;++c)if(!DataUtils.arraysEqual(b[c],a[c]))return!1;return!0};
+var ContentObject=function(a,b,c,d){this.name="string"==typeof a?new Name(a):a;this.signedInfo=b;this.content="string"==typeof c?DataUtils.toNumbersFromString(c):c;this.signature=d;this.rawSignatureData=this.endContent=this.endSIG=this.startSIG=null};
 ContentObject.prototype.sign=function(){var a=this.encodeObject(this.name),b=this.encodeObject(this.signedInfo),c=this.encodeContent(),d=new ArrayBuffer(a.length+b.length+c.length),d=new Uint8Array(d);d.set(a,0);d.set(b,a.length);d.set(c,a.length+b.length);4<LOG&&console.log("Signature Data is (binary) "+d);4<LOG&&console.log("Signature Data is (RawString)");4<LOG&&console.log(DataUtils.toString(d));a=new RSAKey;a.readPrivateKeyFromPEMString(globalKeyManager.privateKey);a=a.signByteArrayWithSHA256(d);
 4<LOG&&console.log("SIGNATURE SAVED IS");4<LOG&&console.log(a);4<LOG&&console.log(DataUtils.toNumbers(a.trim()));this.signature.signature=DataUtils.toNumbers(a.trim())};ContentObject.prototype.encodeObject=function(a){var b=new BinaryXMLEncoder;a.to_ccnb(b);return b.getReducedOstream()};ContentObject.prototype.encodeContent=function(){var a=new BinaryXMLEncoder;a.writeElement(CCNProtocolDTags.Content,this.content);return a.getReducedOstream()};
 ContentObject.prototype.saveRawData=function(a){this.rawSignatureData=a.subarray(this.startSIG,this.endSIG)};
@@ -87,9 +88,10 @@
 a.peekStartElement(CCNProtocolDTags.InterestLifetime)&&(this.interestLifetime=1E3*DataUtils.bigEndianToUnsignedInt(a.readBinaryElement(CCNProtocolDTags.InterestLifetime))/4096);a.peekStartElement(CCNProtocolDTags.Nonce)&&(this.nonce=a.readBinaryElement(CCNProtocolDTags.Nonce));a.readEndElement()};
 Interest.prototype.to_ccnb=function(a){a.writeStartElement(CCNProtocolDTags.Interest);this.name.to_ccnb(a);null!=this.minSuffixComponents&&a.writeElement(CCNProtocolDTags.MinSuffixComponents,this.minSuffixComponents);null!=this.maxSuffixComponents&&a.writeElement(CCNProtocolDTags.MaxSuffixComponents,this.maxSuffixComponents);null!=this.publisherPublicKeyDigest&&this.publisherPublicKeyDigest.to_ccnb(a);null!=this.exclude&&this.exclude.to_ccnb(a);null!=this.childSelector&&a.writeElement(CCNProtocolDTags.ChildSelector,
 this.childSelector);this.DEFAULT_ANSWER_ORIGIN_KIND!=this.answerOriginKind&&null!=this.answerOriginKind&&a.writeElement(CCNProtocolDTags.AnswerOriginKind,this.answerOriginKind);null!=this.scope&&a.writeElement(CCNProtocolDTags.Scope,this.scope);null!=this.interestLifetime&&a.writeElement(CCNProtocolDTags.InterestLifetime,DataUtils.nonNegativeIntToBigEndian(4096*(this.interestLifetime/1E3)));null!=this.nonce&&a.writeElement(CCNProtocolDTags.Nonce,this.nonce);a.writeEndElement()};
-Interest.prototype.matches_name=function(a){return this.name.match(a)};var Exclude=function(a){this.OPTIMUM_FILTER_SIZE=100;this.values=a};Exclude.prototype.from_ccnb=function(a){a.readStartElement(this.getElementLabel());var b=new BinaryXMLStructureDecoder;b.seek(a.offset);if(!b.findElementEnd(a.istream))throw new ContentDecodingException(Error("Cannot find the end of interest Exclude element"));a.seek(b.offset)};
-Exclude.prototype.to_ccnb=function(a){if(!validate())throw new ContentEncodingException("Cannot encode "+this.getClass().getName()+": field values missing.");empty()||(a.writeStartElement(getElementLabel()),a.writeEndElement())};Exclude.prototype.getElementLabel=function(){return CCNProtocolDTags.Exclude};var ExcludeAny=function(){};ExcludeAny.prototype.from_ccnb=function(a){a.readStartElement(this.getElementLabel());a.readEndElement()};
-ExcludeAny.prototype.to_ccnb=function(a){a.writeStartElement(this.getElementLabel());a.writeEndElement()};ExcludeAny.prototype.getElementLabel=function(){return CCNProtocolDTags.Any};var ExcludeComponent=function(a){this.body=a};ExcludeComponent.prototype.from_ccnb=function(a){this.body=a.readBinaryElement(this.getElementLabel())};ExcludeComponent.prototype.to_ccnb=function(a){a.writeElement(this.getElementLabel(),this.body)};ExcludeComponent.prototype.getElementLabel=function(){return CCNProtocolDTags.Component};
+Interest.prototype.matches_name=function(a){return this.name.match(a)};var Exclude=function(a){this.values=a||[]};Exclude.ANY="*";
+Exclude.prototype.from_ccnb=function(a){for(a.readStartElement(CCNProtocolDTags.Exclude);;)if(a.peekStartElement(CCNProtocolDTags.Component))this.values.push(a.readBinaryElement(CCNProtocolDTags.Component));else if(a.peekStartElement(CCNProtocolDTags.Any))a.readStartElement(CCNProtocolDTags.Any),a.readEndElement(),this.values.push(Exclude.ANY);else if(a.peekStartElement(CCNProtocolDTags.Bloom))a.readBinaryElement(CCNProtocolDTags.Bloom),this.values.push(Exclude.ANY);else break;a.readEndElement()};
+Exclude.prototype.to_ccnb=function(a){if(!(null==this.values||0==this.values.length)){a.writeStartElement(CCNProtocolDTags.Exclude);for(var b=0;b<this.values.length;++b)this.values[b]==Exclude.ANY?(a.writeStartElement(CCNProtocolDTags.Any),a.writeEndElement()):a.writeElement(CCNProtocolDTags.Component,this.values[b]);a.writeEndElement()}};
+Exclude.prototype.to_uri=function(){if(null==this.values||0==this.values.length)return"";for(var a="",b=0;b<this.values.length;++b)0<b&&(a+=","),a=this.values[b]==Exclude.ANY?a+"*":a+Name.toEscapedString(this.values[b]);return a};
 var Key=function(){},KeyLocatorType={KEY:1,CERTIFICATE:2,KEYNAME:3},KeyLocator=function(a,b){this.type=b;b==KeyLocatorType.KEYNAME?(3<LOG&&console.log("KeyLocator: SET KEYNAME"),this.keyName=a):b==KeyLocatorType.KEY?(3<LOG&&console.log("KeyLocator: SET KEY"),this.publicKey=a):b==KeyLocatorType.CERTIFICATE&&(3<LOG&&console.log("KeyLocator: SET CERTIFICATE"),this.certificate=a)};
 KeyLocator.prototype.from_ccnb=function(a){a.readStartElement(this.getElementLabel());if(a.peekStartElement(CCNProtocolDTags.Key)){try{this.publicKey=encodedKey=a.readBinaryElement(CCNProtocolDTags.Key),this.type=KeyLocatorType.KEY,4<LOG&&console.log("PUBLIC KEY FOUND: "+this.publicKey)}catch(b){throw Error("Cannot parse key: ",b);}if(null==this.publicKey)throw Error("Cannot parse key: ");}else if(a.peekStartElement(CCNProtocolDTags.Certificate)){try{this.certificate=encodedCert=a.readBinaryElement(CCNProtocolDTags.Certificate),
 this.type=KeyLocatorType.CERTIFICATE,4<LOG&&console.log("CERTIFICATE FOUND: "+this.certificate)}catch(c){throw Error("Cannot decode certificate: "+c);}if(null==this.certificate)throw Error("Cannot parse certificate! ");}else this.type=KeyLocatorType.KEYNAME,this.keyName=new KeyName,this.keyName.from_ccnb(a);a.readEndElement()};
diff --git a/js/testing/test-encode-decode-Interest.html b/js/testing/test-encode-decode-Interest.html
index 050aaf7..b72aee5 100644
--- a/js/testing/test-encode-decode-Interest.html
+++ b/js/testing/test-encode-decode-Interest.html
@@ -27,6 +27,7 @@
             for (i = 0; i < 32; ++i)

                 pkd.push(i);

 			interest.publisherPublicKeyDigest = new PublisherPublicKeyDigest(new Uint8Array(pkd));

+            interest.exclude = new Exclude([Name.fromEscapedString("abc"), Exclude.ANY]);

                 

 			var output = encodeToHexInterest(interest);

 			

@@ -46,59 +47,27 @@
 			

 			var output ="";

 			

-			if (interest.name != null && interest.name.components != null) {

-				output += "Name: ";

-				output += interest.name.getName();

-				output += "<br/>";

-			}

-				

-			if (interest.minSuffixComponents != null ) {

-				output += "MinSuffixComponents : ";

-				output +=  interest.minSuffixComponents;

-				output += "<br/>";

-			}

-			

-			if (interest.maxSuffixComponents != null ) {

-				output += "MaxSuffixComponents : ";

-				output +=  interest.maxSuffixComponents;

-				output += "<br/>";

-			}

-	

-			if (interest.publisherPublicKeyDigest != null ) {

-				output += "PublisherPublicKeyDigest: ";

-				output +=  DataUtils.toHex(interest.publisherPublicKeyDigest.publisherPublicKeyDigest);

-				output += "<br/>";

-			}

-			

-			if (interest.childSelector != null ) {

-				output += "ChildSelector: ";

-				output +=  interest.childSelector;

-				output += "<br/>";

-			}

-			

-			if (interest.answerOriginKind != null ) {

-				output += "AnswerOriginKind: ";

-				output +=  interest.answerOriginKind;

-				output += "<br/>";

-			}

-			

-			if (interest.scope != null ) {

-				output += "Scope: ";

-				output +=  interest.scope;

-				output += "<br/>";

-			}

-			

-			if (interest.interestLifetime != null ) {

-				output += "InterestLifetime (milliseconds): ";

-				output +=  interest.interestLifetime;

-				output += "<br/>";

-			}

-	

-			if (interest.nonce != null ) {

-				output += "Nonce: ";

-				output +=  DataUtils.toHex(interest.nonce);

-				output += "<br/>";

-			}

+			if (interest.name != null && interest.name.components != null)

+				output += "Name: " + interest.name.getName() + "<br/>";

+			if (interest.minSuffixComponents != null )

+				output += "MinSuffixComponents : " + interest.minSuffixComponents + "<br/>";

+			if (interest.maxSuffixComponents != null )

+				output += "MaxSuffixComponents : " + interest.maxSuffixComponents + "<br/>";

+			if (interest.publisherPublicKeyDigest != null )

+				output += "PublisherPublicKeyDigest: " + 

+				  DataUtils.toHex(interest.publisherPublicKeyDigest.publisherPublicKeyDigest) + "<br/>";

+			if (interest.childSelector != null )

+				output += "ChildSelector: " + interest.childSelector + "<br/>";

+			if (interest.answerOriginKind != null )

+				output += "AnswerOriginKind: " + interest.answerOriginKind + "<br/>";

+			if (interest.scope != null )

+				output += "Scope: " + interest.scope + "<br/>";

+			if (interest.interestLifetime != null )

+				output += "InterestLifetime (milliseconds): " + interest.interestLifetime + "<br/>";

+			if (interest.nonce != null )

+				output += "Nonce: " + DataUtils.toHex(interest.nonce) + "<br/>";

+			if (interest.exclude != null )

+				output += "Exclude: " + interest.exclude.to_uri() + "<br/>";

 			

 			document.getElementById('result').innerHTML = output;

 		}

diff --git a/js/tools/build/ndn-js-uncomp.js b/js/tools/build/ndn-js-uncomp.js
index 04700e7..e9d4dc4 100644
--- a/js/tools/build/ndn-js-uncomp.js
+++ b/js/tools/build/ndn-js-uncomp.js
@@ -493,27 +493,16 @@
     
     // Unescape the components.
     for (var i = 0; i < array.length; ++i) {
-        var component = unescape(array[i].trim());
+        var component = Name.fromEscapedString(array[i]);
         
-        if (component.match(/[^.]/) == null) {
-            // Special case for component of only periods.  
-            if (component.length <= 2) {
-                // Zero, one or two periods is illegal.  Ignore this componenent to be
-                //   consistent with the C implmentation.
-                // This also gets rid of a trailing '/'.
-                array.splice(i, 1);
-                --i;  
-                continue;
-            }
-            else
-                // Remove 3 periods.
-                array[i] = component.substr(3, component.length - 3);
+        if (component == null) {
+            // Ignore the illegal componenent.  This also gets rid of a trailing '/'.
+            array.splice(i, 1);
+            --i;  
+            continue;
         }
         else
             array[i] = component;
-        
-        // Change the component to Uint8Array now.
-        array[i] = DataUtils.toNumbersFromString(array[i]);
     }
 
 	return array;
@@ -681,7 +670,7 @@
 Name.ContentDigestPrefix = new Uint8Array([0xc1, 0x2e, 0x4d, 0x2e, 0x47, 0xc1, 0x01, 0xaa, 0x02, 0x85]);
 Name.ContentDigestSuffix = new Uint8Array([0x00]);
 
-/**
+/*
  * Return component as an escaped string according to "CCNx URI Scheme".
  * We can't use encodeURIComponent because that doesn't encode all the characters we want to.
  */
@@ -715,6 +704,27 @@
     return result;
 };
 
+/*
+ * Return component as a Uint8Array by decoding the escapedString according to "CCNx URI Scheme".
+ * If escapedString is "", "." or ".." then return null, which means to skip the component in the name.
+ */
+Name.fromEscapedString = function(escapedString) {
+    var component = unescape(escapedString.trim());
+        
+    if (component.match(/[^.]/) == null) {
+        // Special case for component of only periods.  
+        if (component.length <= 2)
+            // Zero, one or two periods is illegal.  Ignore this componenent to be
+            //   consistent with the C implementation.
+            return null;
+        else
+            // Remove 3 periods.
+            return DataUtils.toNumbersFromString(component.substr(3, component.length - 3));
+    }
+    else
+        return DataUtils.toNumbersFromString(component);
+}
+
 Name.prototype.match = function(/*Name*/ name) {
 	var i_name = this.components;
 	var o_name = name.components;
@@ -1425,93 +1435,75 @@
     return this.name.match(name);
 }
 
-/**
- * Exclude
+/*
+ * Handle the interest Exclude element.
+ * _values is an array where each element is either Uint8Array component or Exclude.ANY.
  */
-var Exclude = function Exclude(_values){ 
-	this.OPTIMUM_FILTER_SIZE = 100;
-	this.values = _values; //array of elements
+var Exclude = function Exclude(_values) { 
+	this.values = (_values || []);
 }
 
+Exclude.ANY = "*";
+
 Exclude.prototype.from_ccnb = function(/*XMLDecoder*/ decoder) {
-		decoder.readStartElement(this.getElementLabel());
+	decoder.readStartElement(CCNProtocolDTags.Exclude);
 
-		//TODO APPLY FILTERS/EXCLUDE.  For now, just skip the element.
-        var structureDecoder = new BinaryXMLStructureDecoder();
-        structureDecoder.seek(decoder.offset);
-        if (!structureDecoder.findElementEnd(decoder.istream))
-            throw new ContentDecodingException(new Error("Cannot find the end of interest Exclude element"));
-        decoder.seek(structureDecoder.offset);
+	while (true) {
+        if (decoder.peekStartElement(CCNProtocolDTags.Component))
+            this.values.push(decoder.readBinaryElement(CCNProtocolDTags.Component));
+        else if (decoder.peekStartElement(CCNProtocolDTags.Any)) {
+            decoder.readStartElement(CCNProtocolDTags.Any);
+            decoder.readEndElement();
+            this.values.push(Exclude.ANY);
+        }
+        else if (decoder.peekStartElement(CCNProtocolDTags.Bloom)) {
+            // Skip the Bloom and treat it as Any.
+            decoder.readBinaryElement(CCNProtocolDTags.Bloom);
+            this.values.push(Exclude.ANY);
+        }
+        else
+            break;
+	}
+    
+    decoder.readEndElement();
+};
+
+Exclude.prototype.to_ccnb = function(/*XMLEncoder*/ encoder)  {
+	if (this.values == null || this.values.length == 0)
+		return;
+
+	encoder.writeStartElement(CCNProtocolDTags.Exclude);
+    
+    // TODO: Do we want to order the components (except for ANY)?
+    for (var i = 0; i < this.values.length; ++i) {
+        if (this.values[i] == Exclude.ANY) {
+            encoder.writeStartElement(CCNProtocolDTags.Any);
+            encoder.writeEndElement();
+        }
+        else
+            encoder.writeElement(CCNProtocolDTags.Component, this.values[i]);
+    }
+
+	encoder.writeEndElement();
+};
+
+// Return a string with elements separated by "," and Exclude.ANY shown as "*".
+Exclude.prototype.to_uri = function() {
+	if (this.values == null || this.values.length == 0)
+		return "";
+
+    var result = "";
+    for (var i = 0; i < this.values.length; ++i) {
+        if (i > 0)
+            result += ",";
         
-		//TODO 
-		/*var component;
-		var any = false;
-		while ((component = decoder.peekStartElement(CCNProtocolDTags.Component)) || 
-				(any = decoder.peekStartElement(CCNProtocolDTags.Any)) ||
-					decoder.peekStartElement(CCNProtocolDTags.Bloom)) {
-			var ee = component?new ExcludeComponent(): any ? new ExcludeAny() : new BloomFilter();
-			ee.decode(decoder);
-			_values.add(ee);
-		}*/
+        if (this.values[i] == Exclude.ANY)
+            result += "*";
+        else
+            result += Name.toEscapedString(this.values[i]);
+    }
+    return result;
 };
-
-Exclude.prototype.to_ccnb=function(/*XMLEncoder*/ encoder)  {
-		if (!validate()) {
-			throw new ContentEncodingException("Cannot encode " + this.getClass().getName() + ": field values missing.");
-		}
-
-		if (empty())
-			return;
-
-		encoder.writeStartElement(getElementLabel());
-
-		encoder.writeEndElement();
-		
-	};
-
-Exclude.prototype.getElementLabel = function() { return CCNProtocolDTags.Exclude; };
-
-
-/**
- * ExcludeAny
- */
-var ExcludeAny = function ExcludeAny() {
-
-};
-
-ExcludeAny.prototype.from_ccnb = function(decoder) {
-		decoder.readStartElement(this.getElementLabel());
-		decoder.readEndElement();
-};
-
-
-ExcludeAny.prototype.to_ccnb = function( encoder) {
-		encoder.writeStartElement(this.getElementLabel());
-		encoder.writeEndElement();
-};
-
-ExcludeAny.prototype.getElementLabel=function() { return CCNProtocolDTags.Any; };
-
-
-/**
- * ExcludeComponent
- */
-var ExcludeComponent = function ExcludeComponent(_body) {
-
-	//TODO Check BODY is an Array of componenets.
-	
-	this.body = _body
-};
-
-ExcludeComponent.prototype.from_ccnb = function( decoder)  {
-		this.body = decoder.readBinaryElement(this.getElementLabel());
-};
-
-ExcludeComponent.prototype.to_ccnb = function(encoder) {
-		encoder.writeElement(this.getElementLabel(), this.body);
-};
-
-ExcludeComponent.prototype.getElementLabel = function() { return CCNProtocolDTags.Component; };
 /**
  * @author: Meki Cheraoui
  * See COPYING for copyright and distribution information.
diff --git a/js/tools/build/ndn-js.js b/js/tools/build/ndn-js.js
index 6ffeb88..3fa6ee5 100644
--- a/js/tools/build/ndn-js.js
+++ b/js/tools/build/ndn-js.js
@@ -12,7 +12,7 @@
 "WrappingKeyName","Action","FaceID","IPProto","Host","Port","MulticastInterface","ForwardingFlags","FaceInstance","ForwardingEntry","MulticastTTL","MinSuffixComponents","MaxSuffixComponents","ChildSelector","RepositoryInfo","Version","RepositoryVersion","GlobalPrefix","LocalName","Policy","Namespace","GlobalPrefixName","PolicyVersion","KeyValueSet","KeyValuePair","IntegerValue","DecimalValue","StringValue","BinaryValue","NameValue","Entry","ACL","ParameterizedName","Prefix","Suffix","Root","ProfileName",
 "Parameters","InfoString",null,"StatusResponse","StatusCode","StatusText","SyncNode","SyncNodeKind","SyncNodeElement","SyncVersion","SyncNodeElements","SyncContentHash","SyncLeafCount","SyncTreeDepth","SyncByteCount","ConfigSlice","ConfigSliceList","ConfigSliceOp"],CCNTime=function(a){this.NANOS_MAX=999877929;"number"==typeof a?this.msec=a:1<LOG&&console.log("UNRECOGNIZED TYPE FOR TIME")};CCNTime.prototype.getJavascriptDate=function(){var a=new Date;a.setTime(this.msec);return a};
 var Name=function Name(b){if("string"==typeof b)3<LOG&&console.log("Content Name String "+b),this.components=Name.createNameArray(b);else if("object"===typeof b){4<LOG&&console.log("Content Name Array "+b);this.components=[];for(var c=0;c<b.length;++c)this.add(b[c])}else null==b?this.components=[]:1<LOG&&console.log("NO CONTENT NAME GIVEN")};Name.prototype.getName=function(){return this.to_uri()};
-Name.createNameArray=function(a){a=a.trim();if(0>=a.length)return[];var b=a.indexOf(":");if(0<=b){var c=a.indexOf("/");if(0>c||b<c)a=a.substr(b+1,a.length-b-1).trim()}if("/"==a[0])if(2<=a.length&&"/"==a[1]){b=a.indexOf("/",2);if(0>b)return[];a=a.substr(b+1,a.length-b-1).trim()}else a=a.substr(1,a.length-1).trim();a=a.split("/");for(b=0;b<a.length;++b){c=unescape(a[b].trim());if(null==c.match(/[^.]/))if(2>=c.length){a.splice(b,1);--b;continue}else a[b]=c.substr(3,c.length-3);else a[b]=c;a[b]=DataUtils.toNumbersFromString(a[b])}return a};
+Name.createNameArray=function(a){a=a.trim();if(0>=a.length)return[];var b=a.indexOf(":");if(0<=b){var c=a.indexOf("/");if(0>c||b<c)a=a.substr(b+1,a.length-b-1).trim()}if("/"==a[0])if(2<=a.length&&"/"==a[1]){b=a.indexOf("/",2);if(0>b)return[];a=a.substr(b+1,a.length-b-1).trim()}else a=a.substr(1,a.length-1).trim();a=a.split("/");for(b=0;b<a.length;++b)c=Name.fromEscapedString(a[b]),null==c?(a.splice(b,1),--b):a[b]=c;return a};
 Name.prototype.from_ccnb=function(a){a.readStartElement(this.getElementLabel());for(this.components=[];a.peekStartElement(CCNProtocolDTags.Component);)this.add(a.readBinaryElement(CCNProtocolDTags.Component));a.readEndElement()};Name.prototype.to_ccnb=function(a){if(null==this.components)throw Error("CANNOT ENCODE EMPTY CONTENT NAME");a.writeStartElement(this.getElementLabel());for(var b=this.components.length,c=0;c<b;c++)a.writeElement(CCNProtocolDTags.Component,this.components[c]);a.writeEndElement()};
 Name.prototype.getElementLabel=function(){return CCNProtocolDTags.Name};
 Name.prototype.add=function(a){var b;if("string"==typeof a)b=DataUtils.stringToUtf8Array(a);else if("object"==typeof a&&a instanceof Uint8Array)b=new Uint8Array(a);else if("object"==typeof a&&a instanceof ArrayBuffer)b=new Uint8Array(new ArrayBuffer(a.byteLength)),b.set(new Uint8Array(a));else if("object"==typeof a)b=new Uint8Array(a);else throw Error("Cannot add Name element at index "+this.components.length+": Invalid type");return this.components.push(b)};
@@ -21,7 +21,8 @@
 Name.prototype.getContentDigestValue=function(){for(var a=this.components.length-1;0<=a;--a){var b=Name.getComponentContentDigestValue(this.components[a]);if(null!=b)return b}return null};
 Name.getComponentContentDigestValue=function(a){return a.length==Name.ContentDigestPrefix.length+32+Name.ContentDigestSuffix.length&&DataUtils.arraysEqual(a.subarray(0,Name.ContentDigestPrefix.length),Name.ContentDigestPrefix)&&DataUtils.arraysEqual(a.subarray(a.length-Name.ContentDigestSuffix.length,a.length),Name.ContentDigestSuffix)?a.subarray(Name.ContentDigestPrefix.length,Name.ContentDigestPrefix.length+32):null};Name.ContentDigestPrefix=new Uint8Array([193,46,77,46,71,193,1,170,2,133]);
 Name.ContentDigestSuffix=new Uint8Array([0]);Name.toEscapedString=function(a){for(var b="",c=!1,d=0;d<a.length;++d)if(46!=a[d]){c=!0;break}if(c)for(d=0;d<a.length;++d)c=a[d],b=48<=c&&57>=c||65<=c&&90>=c||97<=c&&122>=c||43==c||45==c||46==c||95==c?b+String.fromCharCode(c):b+("%"+(16>c?"0":"")+c.toString(16).toUpperCase());else{b="...";for(d=0;d<a.length;++d)b+="."}return b};
-Name.prototype.match=function(a){var b=this.components,a=a.components;if(b.length>a.length)return!1;for(var c=0;c<b.length;++c)if(!DataUtils.arraysEqual(b[c],a[c]))return!1;return!0};var ContentObject=function(a,b,c,d){this.name="string"==typeof a?new Name(a):a;this.signedInfo=b;this.content="string"==typeof c?DataUtils.toNumbersFromString(c):c;this.signature=d;this.rawSignatureData=this.endContent=this.endSIG=this.startSIG=null};
+Name.fromEscapedString=function(a){a=unescape(a.trim());return null==a.match(/[^.]/)?2>=a.length?null:DataUtils.toNumbersFromString(a.substr(3,a.length-3)):DataUtils.toNumbersFromString(a)};Name.prototype.match=function(a){var b=this.components,a=a.components;if(b.length>a.length)return!1;for(var c=0;c<b.length;++c)if(!DataUtils.arraysEqual(b[c],a[c]))return!1;return!0};
+var ContentObject=function(a,b,c,d){this.name="string"==typeof a?new Name(a):a;this.signedInfo=b;this.content="string"==typeof c?DataUtils.toNumbersFromString(c):c;this.signature=d;this.rawSignatureData=this.endContent=this.endSIG=this.startSIG=null};
 ContentObject.prototype.sign=function(){var a=this.encodeObject(this.name),b=this.encodeObject(this.signedInfo),c=this.encodeContent(),d=new ArrayBuffer(a.length+b.length+c.length),d=new Uint8Array(d);d.set(a,0);d.set(b,a.length);d.set(c,a.length+b.length);4<LOG&&console.log("Signature Data is (binary) "+d);4<LOG&&console.log("Signature Data is (RawString)");4<LOG&&console.log(DataUtils.toString(d));a=new RSAKey;a.readPrivateKeyFromPEMString(globalKeyManager.privateKey);a=a.signByteArrayWithSHA256(d);
 4<LOG&&console.log("SIGNATURE SAVED IS");4<LOG&&console.log(a);4<LOG&&console.log(DataUtils.toNumbers(a.trim()));this.signature.signature=DataUtils.toNumbers(a.trim())};ContentObject.prototype.encodeObject=function(a){var b=new BinaryXMLEncoder;a.to_ccnb(b);return b.getReducedOstream()};ContentObject.prototype.encodeContent=function(){var a=new BinaryXMLEncoder;a.writeElement(CCNProtocolDTags.Content,this.content);return a.getReducedOstream()};
 ContentObject.prototype.saveRawData=function(a){this.rawSignatureData=a.subarray(this.startSIG,this.endSIG)};
@@ -51,9 +52,10 @@
 a.peekStartElement(CCNProtocolDTags.InterestLifetime)&&(this.interestLifetime=1E3*DataUtils.bigEndianToUnsignedInt(a.readBinaryElement(CCNProtocolDTags.InterestLifetime))/4096);a.peekStartElement(CCNProtocolDTags.Nonce)&&(this.nonce=a.readBinaryElement(CCNProtocolDTags.Nonce));a.readEndElement()};
 Interest.prototype.to_ccnb=function(a){a.writeStartElement(CCNProtocolDTags.Interest);this.name.to_ccnb(a);null!=this.minSuffixComponents&&a.writeElement(CCNProtocolDTags.MinSuffixComponents,this.minSuffixComponents);null!=this.maxSuffixComponents&&a.writeElement(CCNProtocolDTags.MaxSuffixComponents,this.maxSuffixComponents);null!=this.publisherPublicKeyDigest&&this.publisherPublicKeyDigest.to_ccnb(a);null!=this.exclude&&this.exclude.to_ccnb(a);null!=this.childSelector&&a.writeElement(CCNProtocolDTags.ChildSelector,
 this.childSelector);this.DEFAULT_ANSWER_ORIGIN_KIND!=this.answerOriginKind&&null!=this.answerOriginKind&&a.writeElement(CCNProtocolDTags.AnswerOriginKind,this.answerOriginKind);null!=this.scope&&a.writeElement(CCNProtocolDTags.Scope,this.scope);null!=this.interestLifetime&&a.writeElement(CCNProtocolDTags.InterestLifetime,DataUtils.nonNegativeIntToBigEndian(4096*(this.interestLifetime/1E3)));null!=this.nonce&&a.writeElement(CCNProtocolDTags.Nonce,this.nonce);a.writeEndElement()};
-Interest.prototype.matches_name=function(a){return this.name.match(a)};var Exclude=function(a){this.OPTIMUM_FILTER_SIZE=100;this.values=a};Exclude.prototype.from_ccnb=function(a){a.readStartElement(this.getElementLabel());var b=new BinaryXMLStructureDecoder;b.seek(a.offset);if(!b.findElementEnd(a.istream))throw new ContentDecodingException(Error("Cannot find the end of interest Exclude element"));a.seek(b.offset)};
-Exclude.prototype.to_ccnb=function(a){if(!validate())throw new ContentEncodingException("Cannot encode "+this.getClass().getName()+": field values missing.");empty()||(a.writeStartElement(getElementLabel()),a.writeEndElement())};Exclude.prototype.getElementLabel=function(){return CCNProtocolDTags.Exclude};var ExcludeAny=function(){};ExcludeAny.prototype.from_ccnb=function(a){a.readStartElement(this.getElementLabel());a.readEndElement()};
-ExcludeAny.prototype.to_ccnb=function(a){a.writeStartElement(this.getElementLabel());a.writeEndElement()};ExcludeAny.prototype.getElementLabel=function(){return CCNProtocolDTags.Any};var ExcludeComponent=function(a){this.body=a};ExcludeComponent.prototype.from_ccnb=function(a){this.body=a.readBinaryElement(this.getElementLabel())};ExcludeComponent.prototype.to_ccnb=function(a){a.writeElement(this.getElementLabel(),this.body)};ExcludeComponent.prototype.getElementLabel=function(){return CCNProtocolDTags.Component};
+Interest.prototype.matches_name=function(a){return this.name.match(a)};var Exclude=function(a){this.values=a||[]};Exclude.ANY="*";
+Exclude.prototype.from_ccnb=function(a){for(a.readStartElement(CCNProtocolDTags.Exclude);;)if(a.peekStartElement(CCNProtocolDTags.Component))this.values.push(a.readBinaryElement(CCNProtocolDTags.Component));else if(a.peekStartElement(CCNProtocolDTags.Any))a.readStartElement(CCNProtocolDTags.Any),a.readEndElement(),this.values.push(Exclude.ANY);else if(a.peekStartElement(CCNProtocolDTags.Bloom))a.readBinaryElement(CCNProtocolDTags.Bloom),this.values.push(Exclude.ANY);else break;a.readEndElement()};
+Exclude.prototype.to_ccnb=function(a){if(!(null==this.values||0==this.values.length)){a.writeStartElement(CCNProtocolDTags.Exclude);for(var b=0;b<this.values.length;++b)this.values[b]==Exclude.ANY?(a.writeStartElement(CCNProtocolDTags.Any),a.writeEndElement()):a.writeElement(CCNProtocolDTags.Component,this.values[b]);a.writeEndElement()}};
+Exclude.prototype.to_uri=function(){if(null==this.values||0==this.values.length)return"";for(var a="",b=0;b<this.values.length;++b)0<b&&(a+=","),a=this.values[b]==Exclude.ANY?a+"*":a+Name.toEscapedString(this.values[b]);return a};
 var Key=function(){},KeyLocatorType={KEY:1,CERTIFICATE:2,KEYNAME:3},KeyLocator=function(a,b){this.type=b;b==KeyLocatorType.KEYNAME?(3<LOG&&console.log("KeyLocator: SET KEYNAME"),this.keyName=a):b==KeyLocatorType.KEY?(3<LOG&&console.log("KeyLocator: SET KEY"),this.publicKey=a):b==KeyLocatorType.CERTIFICATE&&(3<LOG&&console.log("KeyLocator: SET CERTIFICATE"),this.certificate=a)};
 KeyLocator.prototype.from_ccnb=function(a){a.readStartElement(this.getElementLabel());if(a.peekStartElement(CCNProtocolDTags.Key)){try{this.publicKey=encodedKey=a.readBinaryElement(CCNProtocolDTags.Key),this.type=KeyLocatorType.KEY,4<LOG&&console.log("PUBLIC KEY FOUND: "+this.publicKey)}catch(b){throw Error("Cannot parse key: ",b);}if(null==this.publicKey)throw Error("Cannot parse key: ");}else if(a.peekStartElement(CCNProtocolDTags.Certificate)){try{this.certificate=encodedCert=a.readBinaryElement(CCNProtocolDTags.Certificate),
 this.type=KeyLocatorType.CERTIFICATE,4<LOG&&console.log("CERTIFICATE FOUND: "+this.certificate)}catch(c){throw Error("Cannot decode certificate: "+c);}if(null==this.certificate)throw Error("Cannot parse certificate! ");}else this.type=KeyLocatorType.KEYNAME,this.keyName=new KeyName,this.keyName.from_ccnb(a);a.readEndElement()};