Categories Displayed in Flash

Archive for the 'xml' Category

XHTML + E4X + Namespaces

Namespaces in flash are cool and...pretty pesky.

  • for unknown reasons, querying a E4X's queries in the same block apparently have to be individually namespaced. Neither putting the default namespace in the class or function worked.
  • anything that tries to get at the xml while it's being passed around has to have a copy of the namespace. This isn't particularly efficient when you are serializing between objects and XHTML.

Steven Sachs has a good tutorial on some of the issues faced when working with XHTML and Flash.  In particular the namespace.  However after losing about 2hrs I've come up with an alternate solution...just stripping the namespace out as it's introducing more code chaos than the namespace would have solved.

In the next rev of kidthing.com's website we are going to XHTML for SEO and CMS, deeplinking etc reasons.   In addition we are consuming Wordpress, initially as RSS and eventually as fully skinning the main pages in Wordpress.  Since Flash's support for HTML is limited we run things through a 'cleaner' that replaces quotes, superscript, some bullets with the appropriately embedded characters.  It was easy to add the following to strip it out on the complete load of the XHTML

res = res.split('xmlns="http://www.w3.org/1999/xhtml"').join('');

I switched over from String manipulation to XML manipulation to get at selective DIV's that get mapped to textfields in the flash templates (Flash is like CSS on steroids)  E4X here really shines.

AS3: Parsing XML with Nested Namespaces, SWF RDF metadata

Trying to parse the swf header to get at the metadata, which requires getting through nested namespaces in the RDF

The Flash Metadata embedded in the swf headers looks like:

<rdf:rdf xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:description xmlns:dc="http://purl.org/dc/1.1/">
<dc:title>A MetaData Example</dc:title>
<dc:description>This file has metadata embedded in it.</dc:description>
</rdf:description>
</rdf:rdf>

Namespaces are liked locked boxes, until you pass the key (e.g. setting default xml namespace = ns; or xml.ns::nodeName they are locked from opening anything beneath them, though it may appear otherwise when looking in the debugger.

So getting namespaces are required to parse the title and description. It would be easy to cheat and just hardcode the namespace, however it's bad form to hardcode the namespaces, as they change over different versions of the swf file format.

In addition the meta.namespaceDelcarations appears only to apply to the node it's associated with, meaning

  1.  
  2.    for (var i:uint = 0; i < meta.namespaceDeclarations().length; i++) {
  3.         var ns:Namespace = meta.namespaceDeclarations()[i];
  4.         trace(i + " ns " + ns.toString());
  5.         var prefix:String = ns.prefix;
  6.         if (prefix == "") {
  7.                 prefix = "(default)";
  8.         }
  9.         trace(prefix + ":" , ns.uri);
  10.  }

on the top level only returns the first name sapce of "http://www.w3.org/1999/02/22-rdf-syntax-ns#" when really we are after the dc namespace. But we need the first lock in order to open up the second.

Another approach is just parsing the string looking for the namespace prior to XML.

var rdfN:String = findXMLNS(nsr, 'xmlns:rdf="');
var dcN:String = findXMLNS(nsr, 'xmlns:dc="');
var rd:Namespace = new Namespace(rdfN);

  1.  
  2.   function findXMLNS(xmlS:String, nameSpace:String):String {
  3.      var a:Number = xmlS.indexOf(nameSpace);
  4.      var a2:Number = a + nameSpace.length;
  5.      var b:Number = xmlS.indexOf("\"", a2);
  6.      var res:String = xmlS.substring(a2,b);
  7.      return res;
  8.   }

Another warning is that namespaces var should be declared outside of a function if your else you'll get an error message of
VerifyError: Error #1025: An invalid register 13 was accessed.

Presumeably because namespaces as used by XML need to be scoped as non-temp local function scoped variables. So

  1.  
  2.  var dc:Namespace;
  3.  
  4.  function parseXML(Desc:XMLList){
  5.     //BAD! var ns = Desc.namespaceDeclarations()[0];
  6.     dc = Desc.namespaceDeclarations()[0]; //GOOD
  7.     //BAD         default xml namespace =  ns;
  8.     default xml namespace =  dc; //GOOD
  9.     trace("title:" + meta..title);
  10.  }

SEO with Flash

Iconara has a great post on SEO with Flash/Flex centric sites.

Sadly in many rush-rush design centric projects, web considerations are late in the development cycle, such as user experience during preloading (this has affected about 80% of the projects I've been apart of), and SEO. Tacking these features on after the fact is prohibitively expensive.
Part of the problem, is intrinsic to the high pressure, creative first, engineering second, testing/deployement only if time permits..of those who develop flash content, being first tier largely designers concerned with experience (pixels, movement, colors), they will embed fonts, or photoshop them to get the right Typography. so even if they could be straight pages easily indexable, and bots could open up the swf to see inside (which they can do, see them, after it's been ran through a dozen photoshop filters, collaged with a dozen , and spraypainted while it will look spectacular...you might as well be giving the bot a captchas.

Even engineering probably is more concerned about how to get it to work during development, than introducing another asset to load, and attaching links dynamically, as it's one more thing to go wrong and have to be tested. Though if considered early, a loadVars or an XML file for key value pairs, isn't particularly hard to load/parse, Danny has a simple utility to help for precisely http://www.communitymx.com/abstract.cfm?cid=C45CA,

Google can and does index swfs, but it's rare that the links are actually relelvant. Frequentlly when building data driven Flash, if there are a 100 products and links to follow e.g. www.amazon.com/buyme?product.id=2, the link will be normalized into ' www.amazon.com/buyme?product.id' and '2'., with a string replace e.g.

function onClick (){
linkURL = SITE +"/" + SECTION +"?" + product.id;

}
When past projects have faced this, we used XML as the data and do client detection via a jsp/asp/etc +XLST and render HTML or Flash as appropriate.