Escaping Reserved Characters

One very important thing that you should be aware of when working with SSML is that SSML is an XML-based language. As such, certain characters have special meaning and are reserved. Specifically, the characters in the following table cannot be used in the content of an SSML without escaping them first:

Name

Character

Escape Code

Less than

<

&lt;

Greater than

>

&gt;

Ampersand

&

&amp;

Quote

"

&quot;

Apostrophe

&apos;

For example, the following SSML is invalid due to three unescaped reserved characters:

 <speak>
  When she entered the five ​&​ dime, she noted that the sale price was < the
 regular​ ​price,​ ​but​ ​still​ > than the discount store across town.
 </speak>

By replacing the reserved characters with their escaped equivalents, we get the following valid SSML:

 <speak>
  When she entered the five &amp; dime, she noted that the sale price was &lt;
  the regular price, but still &gt; than the discount store across town.
 </speak>

This is especially important to realize when your skill injects values it receives from a database or some external service into the SSML. There’s no way to trust that the data you receive won’t include reserved characters, so you’ll need to escape those values before applying them to SSML.

For example, suppose that instead of Star Port 75, you are creating a skill that locates nearby restaurants. In that case, you might have a string in languageStrings.js with the following SSML:

 FOUND_RESTAURANT: ​'<speak>You should have dinner at '​ +
 '<audio src="soundbank://soundlibrary/musical/amzn_sfx_bell_timer_01"/>'​ +
 '{{restaurant}}</speak>'​,

Meanwhile, in your intent handler, you might have the following snippet to inject a found restaurant name into the text:

 const​ restaurantName = ...; ​// get restaurant from database or some service
 const​ speakOutput = handlerInput.t(​'FOUND_RESTAURANT'​,
  {restaurant: restaurantName});

This will work fine if the restaurant name is something like “Burger Barn”. But suppose that the found restaurant’s name is something like “Burgers & Brews”. The resulting SSML will look like this:

 <speak>
  You should have dinner at
  <audio src=​"soundbank://soundlibrary/musical/amzn_sfx_bell_timer_01"​/>
  Burgers ​&​ Brews
 </speak>

The ampersand makes the SSML invalid. To fix this, you can add the following function to your fulfillment code:

 const​ escapeForSsml = (inString) => {
 return​ inString.replace(​/&/g​, ​'&amp;'​)
  .replace(​/</g​, ​'&lt;'​)
  .replace(​/>/g​, ​'&gt;'​)
  .replace(​/"/g​, ​'&quot;'​)
  .replace(​/'/g​, ​'&apos;'​);
 };

And then, change the call to handlerInput.t() to call the escapeForSsml() function as it creates the SSML parameter object:

 const​ restaurantName = ...; ​// get restaurant from database or some service
 const​ speakOutput = handlerInput.t(​'FOUND_RESTAURANT'​,
  {restaurant: escapeForSsml(restaurantName)});

This will ensure that any special characters in the parameters are escaped before being injected into the SSML. The resulting SSML will now look like this:

 <speak>
  You should have dinner at
  <audio src=​"soundbank://soundlibrary/musical/amzn_sfx_bell_timer_01"​/>
  Burgers &amp; Brews
 </speak>

SSML is a very powerful way to give character and a unique sound to Alexa’s responses. But as we’ve seen, SSML markup can result in lengthy string values. Let’s take a look at a way to simplify SSML markup by using Speech Markdown.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset