blog.humaneguitarist.org

discoveries in digital audio, music notation, and information encoding

jAUs: trying to add a startTime attribute to the audio tag

leave a comment

I work up this morning feeling unwell, but I still went in to work for a few minutes to enable Remote Desktop as it had stopped working (was a Windows Firewall thing) …

Anyway, on the walk back home I started thinking about something I've wanted to play with for a while.

And that's seeing what it would take to add support for a "startTime" attribute for the HTML5 <audio> tag using a browser's built-in player. I think it's a real oversight that there isn't native support for passing the start and stop times in the <audio> and <video> tags themselves. Um, there isn't right?

Adding support for a "stopTime" attribute would, I think, require more than I'm willing to think about right now (I should be napping) because obviously that entails checking the current time against the point at which one would want the media to stop.

But adding a simple (and, yes, non-standard) "startTime" attribute inside the <audio> tag seems pretty easy – if you aren't using IE. Ugh.

As you can see in the code below there's an alert() that returns a null, but without it IE (version 9) won't set the audio players to the values in the "startTime" attributes. The other "major" browsers do fine without it. And, really, it can't be there because it's annoying as hell.

But I think this still points to the problem of each browser having its own player. Take Safari for instance. It doesn't natively show the current or total time of the track. Chrome doesn't show the total time.

Still think Flash is a bad thing?

:P

<!DOCTYPE html>
<html>
  <head>
    <title>jAUs</title>
    <script type="text/javascript">
      function jAUs(){
        var audioTag = document.getElementsByClassName('jAUs');
        for (i=0;i<=audioTag.length;i++){
          var audioTag_startTime = audioTag[i].getAttribute('startTime');
          alert('');
          audioTag[i].currentTime = audioTag_startTime;
        }
      }
    </script>
  </head>
<body onload="jAUs()">

  <audio class="jAUs" controls startTime="10">
    <source src="sonnet130_shakespeare_njm.mp3" type="audio/mp3" />
    <source src="sonnet130_shakespeare_njm.ogg" type="audio/ogg" />
    Your browser does not support the audio element.
  </audio>

  <br />

  <audio class="jAUs" controls startTime="25">
    <source src="sonnet130_shakespeare_njm.mp3" type="audio/mp3" />
    <source src="sonnet130_shakespeare_njm.ogg" type="audio/ogg" />
    Your browser does not support the audio element.
  </audio>

</body>
</html>

ps: If this ever turns into a little project of mine, it needs a decently cool name to keep my interest. "JS" for JavaScript and "AU" for audio mashed up equals "jAUs". I hope that isn't already taken within the JavaScript/HTML5 domain.

Update, January 09, 2012: Now that an hour has past and I finished watching "Thor & Loki: Blood Brothers", I figured out how to elegantly do the "stopTime" thing – well, at least I think it's better than what I was thinking earlier today!

So unlike in the code above, the JavaScript below only hits on one <audio> element (the one with an "id" value of "jAUs") and not all the ones with a "class" value of "jAUs". But the point is that this new code adds the "ontimeupdate" attribute to the <audio> tag and makes it run a function called stopper() that will stop the audio once the current time is greater than the designated stopping time.

Now, there's still work to do. For example, the code should test for the existence of the "stopTime" attribute before forcing the stopper() function to run, but that's no big deal. I also need to test doing this as above – i.e. hitting all <audio> tags with a "class" value of "jAUs" – and see how that works. And there's that pesky IE thing, too.

Anyway, this is working in the other "major" browsers 'far as I can tell.

<!DOCTYPE html>
<html>
  <head>
    <title>jAUs</title>
    <script type="text/javascript">
      function jAUs(){
        var audioTag = document.getElementById('jAUs');
        var audioTag_startTime = audioTag.getAttribute('startTime'); //returns "10"
        //alert(''); //no IE love this time, sorry!
        audioTag.currentTime = audioTag_startTime;
        var audioTag_stopTime = audioTag.getAttribute('stopTime');  //returns "20"
        var stopThis = "stopper(this.currentTime," + audioTag_stopTime + ");"; //returns "stopper(this.currentTime,20);"
        audioTag.setAttribute('ontimeupdate',stopThis); //sends current time and stopTime value to stopper()
      }
      function stopper(currentTime, stopTime){
        var audioTag = document.getElementById('jAUs');
        if (currentTime > stopTime){
          audioTag.pause(); //stops playback if the current time is greater than the stopTime value
        }
      }
    </script>
  </head>
  <body onload="jAUs()">

  <audio id="jAUs" controls startTime="10" stopTime="20">
    <source src="sonnet130_shakespeare_njm.mp3" type="audio/mp3" />
    <source src="sonnet130_shakespeare_njm.ogg" type="audio/ogg" />
    Your browser does not support the audio element.
  </audio>

</body>
</html>

Update, January 09, 2012: I still don't like it, but it seems that the alert() line can go at the top of the jAUs() function and still allow all this to work on IE 9. At least that prevents an alert message for each <audio> tag within the page.

Update, January 10, 2012: Ah. Now, we might be getting somewhere. I don't know if it's just a band-aid fix, but if I add an "onloadeddata" bit for IE9 this actually seems to be working just fine. The problem was that IE didn't consider the <audio> element's properties to be accessible, thus giving me an "Invalid State Error" with a code number of 11 which is this, more or less: "An attempt was made to use an object that is not, or is no longer, usable." So, IE9 is taking a little longer than the other browsers in realizing what's what.

<!DOCTYPE html>
<html>
  <head>
    <title>jAUs</title>
    <script type="text/javascript">
      function jAUs(){
        audioTag = document.getElementById('jAUs'); //this is a global variable
        var audioTag_startTime = audioTag.getAttribute('startTime'); //returns "10"
        //alert(audioTag.readyState); //IE returns "0", other browsers "4"
        //alert(audioTag.readyState); //IE and others return "4"

        //needs to be for IE9 only ... I guess it waits until the audioTag is ready to go.
        if (navigator.appName == 'Microsoft Internet Explorer')
        {
          audioTag.onloadeddata = function() {
            audioTag.currentTime = audioTag_startTime;
          }
        }
        else {
          audioTag.currentTime = audioTag_startTime;
        }

        var audioTag_stopTime = audioTag.getAttribute('stopTime');  //returns "13"
        var stopThis = "stopper(this.currentTime," + audioTag_stopTime + ");";
        //returns "stopper(this.currentTime, 13);"

        audioTag.setAttribute('ontimeupdate',stopThis);
      }

      function stopper(currentTime, stopTime){
        if (currentTime > stopTime){
          audioTag.pause();
        }
      }
    </script>
  </head>
  <body onload="jAUs()">

  <audio id="jAUs" controls startTime="10" stopTime="13">
    <source src="sonnet130_shakespeare_njm.mp3" type="audio/mp3" />
    <source src="sonnet130_shakespeare_njm.ogg" type="audio/ogg" />
    Your browser does not support the audio element.
  </audio>

</body>
</html>

Update, January 10, 2012: Hopefully (for you and me) this is the last update for a while. Hey, I'm still sick, jerk!

Anyway, this is a test for hitting on all <audio> tags with a class value of "jAUs".

<!DOCTYPE html>
<html>
  <head>
    <title>jAUs</title>
    <script type="text/javascript">
      function jAUs(){

        audioTagArray = document.getElementsByClassName('jAUs');

        for (i=0;i<=audioTagArray.length-1;i++){
          var thisAudioTag = audioTagArray[i];
          jAUs_2(audioTagArray,thisAudioTag);
        }
      }

      function jAUs_2(audioTagArray,thisAudioTag){
      //if this is placed directly into jAUs() - i.e. not a separate function,
      //then this whole thing doesn't seem to work.

        if (navigator.appName == 'Microsoft Internet Explorer'){
          thisAudioTag.onloadeddata = function(){
            var thisAudioTag_startTime = thisAudioTag.getAttribute('startTime');
            thisAudioTag.currentTime = thisAudioTag_startTime;
          }
        }

        else {
          var thisAudioTag_startTime = thisAudioTag.getAttribute('startTime');
          thisAudioTag.currentTime = thisAudioTag_startTime;
        }

        var thisAudioTag_stopTime = thisAudioTag.getAttribute('stopTime');
        var stopString = "jAUs_3(this.currentTime," + thisAudioTag_stopTime + "," + i + ");";
        //returns "jAUs_3(this.currentTime, 13, i);" where "i" is an int.

        thisAudioTag.setAttribute('ontimeupdate',stopString);
      }

      function jAUs_3(this_currentTime,thisAudioTag_stopTime,i){

        if (this_currentTime > thisAudioTag_stopTime){
          audioTagArray[i].pause();
        }
      }
    </script>
  </head>
  <body onload="jAUs()">

  <audio class="jAUs" controls startTime="10" stopTime="13">
    <source src="sonnet130_shakespeare_njm.mp3" type="audio/mp3" />
    <source src="sonnet130_shakespeare_njm.ogg" type="audio/ogg" />
    Your browser does not support the audio element.
  </audio>

  <br />

  <audio class="jAUs" controls startTime="25" stopTime="26">
    <source src="sonnet130_shakespeare_njm.mp3" type="audio/mp3" />
    <source src="sonnet130_shakespeare_njm.ogg" type="audio/ogg" />
    Your browser does not support the audio element.
  </audio>

</body>
</html>

By the way, using the HTML5 "data-" prefix a la "data-startTime" would make the attribute(s) valid, though still not part of a standard per the <audio> tag specifically. But I guess the "data-" prefix is an acknowledgment of reality.

--------------

Related Content:

Written by nitin

January 9th, 2012 at 12:29 pm

Posted in digital audio

Tagged with , ,

simple point and search with a maps API

leave a comment

I'm currently working with some folks on a pilot project to build a shared index of digital collection metadata from libraries in North Carolina. My part entails harvesting the metadata and indexing it with Solr.

Since most of the stuff is North Carolina centric, I thought it might be neat to use the API that the index will have to drag a marker on a map and then use the marker location to send a search to the index. My co-worker also wants to do something similar so people can search using a map marker for a project of hers. So, I thought I'd investigate.

I wanted to see how easy it was to do this with the Google Maps API and, well, it is pretty easy. Especially, since I found this marker dragging example.

There's lot of stuff that can be done, like dynamically populating the page with a set of results via AJAX but for now I'm just using the city name plus a pre-written string to create a search string that the user has to manually click.

In the little example I made (below), I'm using my home state of South Carolina. If you move the marker within SC and drop it, a simple search string is created for sending a search, ironically, to Bing Maps for the term "restaurants" and that city.

I think a search like this is really for fun, but it might be a nice way to search and learn a little geography along the way. I've also got an idea for a game using this kind of search that's sort of a spin on Concentration for digital collections, but I'll write that up later. I'm hungry and need to start enjoying my Saturday. Looking at these restaurants searches is making me even hungrier.

:/

    Written by nitin

    January 7th, 2012 at 11:29 am

    the serpent, the apple, and Joe

    leave a comment

    For better or worse, the one application of mine that people actually use is the one I wrote pretty casually with Python over a couple weekends from bed because I was too lazy or hungover to get moving on those days.

    That software, PubMed2XL, lets people do a few things with downloaded citations from PubMed.gov that isn't currently offered directly from the site. I've gotten some nice feedback from librarians, researchers, and information-y people at companies that have found it useful.

    This post isn't a plug though; it's more an acknowledgement of something that I didn't really realize in full at the time. And that is when one writes software that people go on to actually use, one better be prepared to support it. Now, the software's simple enough that there haven't been real bugs save one, but it does eat at me that I can't offer a simple way for it to work on multiple platforms.

    While the Windows version is really easy to setup – thanks to py2exe and Inno Setup – getting it running on Linux is a bit more work, given all the distro variations and dependency installation. But getting it running on a Mac – particularly with an easy to use installer – isn't going to be possible unless I can find someone to compile it for a Mac who will also test it and compile future versions. Sure, there's the possibility of using Wine, but that's still asking a lot from end users.

    Normally, I wouldn't care. Apple doesn't make it easy for people to develop for Macs unless you fork over the change for a Mac – and I ain't buying a copy of OSX and doing the Hackintosh bit. But, since the software is ultimately about health-related research, I do care.

    Unfortunately I made – with the advantage of hindsight – two coding decisions that create problems.

    First, I chose PyQT as the GUI toolkit for the software simply because it looks prettier than Python's native Tkinter. My reasoning at the time was the people were more likely to trust better looking software even though it's just a small window with some basic menu options. Eventually, I added a progress bar, too, so downgrading to Tkinter has become less of an option.

    Second (and this is the big one), I used lxml since the PubMed2XL setup files employ XSL to tell the software what data to put in a spreadsheet cell. Granted, lxml is freakin' fantastic, but since it's not a pure Python module I can't just distribute it in a folder and import the module locally. Not that I had much of a choice: there's no built in XSLT-capable module that ships with Python 'far as I know.

    So I've been asking myself how to make the serpent (Python) and the apple (OSX) get along.

    I've consider just making PubMed2XL a web-app, but that will entail expenses for me that simply offering people a desktop app doesn't entail.

    So, I think the solution lies in a cup of Joe. That's to say that a Java app is the obvious solution, specifically using Jython.

    That would leave me to replace PyQT with Swing. I'm fine with that. It's not like PyQT is all that Pythonic in the first place. There's a nice Jython/Swing tutorial here.

    And as for the XSLT component, this tutorial on XSLT with Jython and native Java libraries should help immensely.

    So, I should be able to use Jython to make a cross-platform version of PubMed2XL. I don't necessarily want to, but given the type of research I'd like to help facilitate (in a very small way, I know), I think I probably should.

    --------------

    Related Content:

    Written by nitin

    January 7th, 2012 at 10:22 am

    more evil please: the shocking state of Hammer Horror on Netflix

    leave a comment

    A few weeks ago I finally put HammerFlicks online. The project is a programmatic approach to learning which Hammer Horror titles are available for streaming on Netflix. And while there's always room for improvement, the thing actually works and I'm using it.

    Unfortunately, the true horror is that there just aren't that many titles that are available to "Watch Instantly". In fact, in the time I launched the project I've only become aware of one new title that I was able to watch online that I hadn't already seen …

    "Evil of Frankenstein" features Peter Cushing once again as the good Doctor Frankenstein. Unlike as in "Frankenstein Must be Destroyed", Cushing casts a sympathetic figure in this one, with the local authorities and a hypnotist named Zoltan as the true monsters. Frankenstein is kind to his loyal assistant (not his servant) Hans and even displays dashes of modesty about his scientific breakthroughs. It's not as grand a film as some of the other Cushing/Frankenstein Hammer films, but it's still fun.

    Evil of Frankenstein

    When I checked HammerFlicks today, both "Evil of Frankenstein" and "Frankenstein Must be Destroyed" are no longer available to stream on Netflix. In fact, 'Evil' is not available in any format from Netflix as of this writing. That's just, well, shocking!

    By the way, I just stumbled on this cool write-up on 'Evil'. Makes me want to watch it again. Oh wait, I can't.

    --------------

    Related Content:

    Written by nitin

    January 5th, 2012 at 9:36 pm

    Gmail, the Prince Frog

    leave a comment

    Gmail forced its new look on me today.

    It sucks.

    I can barely read the page. I can barely discern what constitutes a row per each email. And the color scheme truly hurts my eyes.

    Add to that: none of the other themes were better for me than the default. Forget the fact that I find most of them too playful (read: unprofessional), but I just can't look at the page long enough to read anything. The good old "classic" theme appears to be gone.

    I guess it's too much for me to remember that image is everything these days. I thought email was about content, but apparently it's about inducing seizures and catering to a world in which ideas come in 140-character, bite size pieces posing as entrees.

    Anyway, I was able to revert to the old-school HTML view by using Firefox's VIEW>PAGE STYLE>NO PAGE STYLE menu option. That forced Gmail to ask me if I wanted to use the HTML view because it couldn't show off its fancy pants to me anymore. After I set HTML as the default, I went back to Firefox's menu bar and chose VIEW>PAGE STYLE>BASIC PAGE STYLE.

    Now, I've got the HTML view as my default. It's not as nice as the missing "classic" view but it's way better than the hideous monstrosity I was being subjected to against my will.

    Does no one learn from Facebook's follies of forcing unnecessary UI changes on their users?

    Update, January 4, 2012: Silly me. Under the settings there's the "Revert to the old look temporarily" option that I couldn't find anymore as of yesterday. So I just am using that … for now.

      Written by nitin

      January 3rd, 2012 at 6:38 pm

      Posted in news

      Tagged with ,

      choose your own toppings: whatever code inside CDATA

      leave a comment

      I really should be packing for an overseas vacation that begins tomorrow, but I wanted to jot some stuff down before I forget – and I intend to forget a lot!

      Anywho, in a previous post I wrote about putting XSL inside a CDATA block inside an XML config file. I had the following example:

      <map name="LibriVox">
        <XSLT>./XSLT/LibriVox_to_Solr.xsl</XSLT>
        <nextXSL>
        <![CDATA[
        <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
          <xsl:output method="text"/>
          <xsl:template match="/">
            <xsl:variable name="baseURL" select="'%s'" />
            <xsl:variable name="URL_params" select="'%s'" />
            <xsl:variable name="offset_" select="substring-after($URL_params,'=')" />
            <xsl:variable name="offset" select="substring-before($offset_,'&amp;')" />
            <xsl:variable name="limit_" select="substring-after($URL_params,'&amp;')" />
            <xsl:variable name="limit" select="substring-after($limit_,'=')" />
            <xsl:variable name="output">
              <xsl:value-of select="$baseURL" />
              <xsl:text>?offset=</xsl:text>
              <xsl:value-of select="$offset+50" />
              <xsl:text>&amp;limit=</xsl:text>
              <xsl:value-of select="50" />
            </xsl:variable>
            <xsl:value-of select="$output" />
          </xsl:template>
        </xsl:stylesheet>
        ]]>
        </nextXSL>
      </map>
      

      This is part of this pOAIndexter script I'm working on for, well, work.

      The XML code above is from one of the config files where the <XSLT> element points to an XSL file used to process metadata retrieved from a website. In this case, the point is to make a Solr-compatible XML document that can be used for indexing purposes. The second element, <nextXSL>, is used to return to pOAIndexter the URL for the next batch of metadata for a given feed, i.e. the next page or the next set within a collection, etc.

      And as you can see there are two weird looking variables at the top:

            <xsl:variable name="baseURL" select="'%s'" />
            <xsl:variable name="URL_params" select="'%s'" />

      The reason being that the pOAIndexter script actually populates these with the actual base URL for the batch just retrieved and the parameters, respectively, before the XSL within the <nextXSL> element is run, returning the string of the next URL.

      I chose XSL because I think, as a librarian, it seems to be common to a lot of metadata and digital library folk and such people could extend the capabilities of pOAIndexter without having to know Python. But all along I wanted people to be able to process the metadata and return the next URL with whatever scripting language they want, provided the interpreter exists on their system.

      So, say for example you like PHP instead. Instead of the using XSL you could use something like this:

      <map name="LibriVox">
        <PHP>./PHP/LibriVox_to_Solr.php</PHP>
        <nextPHP>
        <![CDATA[
        <?php
        $baseURL=%s;
        $URL_params=%s;
      
        //some PHP code here
      
        echo $output; //where $output is the next URL ...
        ?>
        ]]>
        </nextPHP>
      </map>

      That way PHP could be used to make the Solr-XML file and to return to pOAIndexter the next URL string so that the next batch of metadata from a feed could be processed/transformed. Of course, you could mix and match, too – XSLT for making the Solr-XML file and PHP just for getting the next URL.

      That's actually pretty simply to do with the common scripting languages like Python, PHP, Perl, Ruby, etc. But what I really wanted to support was JavaScript because, well, it would just be cool, but also because that's another one of those common languages that a lot of people might know even though there might be great variation amongst the other scripting languages they know when compared to a lot of their colleagues.

      But I didn't know how to execute Javascript via the command line so that pOAIndexter can capture the next URL via the standard output stream.

      Well, enter PhantomJS.

      That is all. Time to pack.

      --------------

      Related Content:

      Written by nitin

      December 21st, 2011 at 11:03 pm

      layer cake: XML config files with XSL inside CDATA

      leave a comment

      Sometimes in life – or coding projects – there are regrets.

      But there is cake, too.

      yummy looking layer cake

      Anyway, for a current project I want to place some XSL inside an XML config file.

      But of course, you can't just drop XML inside XML without coating it in something.

      So for another project, PubMed2XL, I did something like this:

      <cell>{{?xml version="1.0" encoding="UTF-8"?}}
        {{xsl:stylesheet version="1.0" encoding="UTF-8" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"}}
        {{xsl:output method = "text" /}}
        {{xsl:template match="/"}}
          {{xsl:value-of select="//PMID" /}}
        {{/xsl:template}}
        {{/xsl:stylesheet}}
      </cell>
      

      Putting XSL inside double curly brackets works just fine, but now I know a better way: just put it inside a CDATA section!

      <map name="LibriVox">
        <XSLT>./XSLT/LibriVox_to_Solr.xsl</XSLT>
        <nextXSL>
        <![CDATA[
        <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
          <xsl:output method="text"/>
          <xsl:template match="/">
            <xsl:variable name="baseURL" select="'%s'" />
            <xsl:variable name="URL_params" select="'%s'" />
            <xsl:variable name="offset_" select="substring-after($URL_params,'=')" />
            <xsl:variable name="offset" select="substring-before($offset_,'&amp;')" />
            <xsl:variable name="limit_" select="substring-after($URL_params,'&amp;')" />
            <xsl:variable name="limit" select="substring-after($limit_,'=')" />
            <xsl:variable name="output">
              <xsl:value-of select="$baseURL" />
              <xsl:text>?offset=</xsl:text>
              <xsl:value-of select="$offset+50" />
              <xsl:text>&amp;limit=</xsl:text>
              <xsl:value-of select="50" />
            </xsl:variable>
            <xsl:value-of select="$output" />
          </xsl:template>
        </xsl:stylesheet>
        ]]>
        </nextXSL>
      </map>
      

      Duh. I guess like a good XML parser that I always just ignored anything inside a CDATA section. Never thought I'd need to use one.

      Putting the XSL inside a CDATA section worked like a charm in terms of being able to read it with a script and perform an XSLT with it.

      Luckily, the PubMed2XL script can use either the CDATA way of embedding XSL or my Curly solution – not that I knew that when I wrote it!

      It's certainly easier to cut/paste the XSL in the CDATA block without having to replace the brackets with curly quotes or vice versa. It's also just easier to read, which makes it easier to edit and troubleshoot. And it tastes better, too.

      --------------

      Related Content:

      Written by nitin

      November 12th, 2011 at 12:18 pm

      Posted in XML

      Tagged with , ,

      MXMLiszt article published

      leave a comment

      If anyone's truly bored, an article of mine about MXMLiszt has been published through OCLC Systems & Services.

      Here's the citation:

      Nitin Arora, (2011) "MXMLiszt: a preliminary MusicXML digital library platform built on available open-source technologies", OCLC Systems & Services, Vol. 27 Iss: 4, pp.298 – 316.

      I need to give a huge shout-out to Dr. Steven MacCall at the University of Alabama under whom I did the research for MXMLiszt which included delivering the software and a paper – that's much longer than the published one! – about libraries and digital sheet music. It was cool to finish up my library degree with stuff that meant more to me than just a means to, well, finishing up the degree.

      Update, November 26, 2011: I should have mentioned that this article is not openly available. If you want to read the article but can't access it through your institution or local library, please email me at "nitaro74 AT gmail DOT com". Under the publication rules, I am allowed to distribute the version of the article I submitted to the publisher. I don't have any problem doing so if someone is genuinely interested provided you agree not to openly distribute copies and provided you check with your local library first. Most libraries have access to more resources than most of their patrons know!

      --------------

      Related Content:

      Written by nitin

      November 12th, 2011 at 11:23 am

      pretty printing XML with Python, lxml, and XSLT

      leave a comment

      Last week or so I was doing some work with Python and lxml. And, it seems like a lot of people, using lxml's pretty printing wasn't really doing anything for me.

      I couldn't find any native lxml solutions to make my XML look pretty. All I found were some functions on various code sites written by people to pretty print the XML using a bunch of regular expressions. Yuck.

      So I thought, "Why not use XSLT to pretty print my XML?" and I found an XSL written by none other than Michael Kay on this page (see comment #4).

      And it seems to work just fine as a function to return pretty XML, not to mention it's super short and sweet.

      Anyway, here's an example of using the XSL for pretty printing.

      from lxml import etree
      from lxml.etree import XSLT
      
      def prettify(someXML):
        #for more on lxml/XSLT see: http://lxml.de/xpathxslt.html#xslt-result-objects
        xslt_tree = etree.XML('''\
          <!-- XSLT taken from Comment 4 by Michael Kay found here:
          http://www.dpawson.co.uk/xsl/sect2/pretty.html#d8621e19 -->
          <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
          <xsl:output method="xml" indent="yes" encoding="UTF-8"/>
            <xsl:strip-space elements="*"/>
            <xsl:template match="/">
              <xsl:copy-of select="."/>
            </xsl:template>
          </xsl:stylesheet>''')
        transform = etree.XSLT(xslt_tree)
        result = transform(someXML)
        return unicode(result)
      
      myXML = etree.XML('<a><b><c><d/></c></b></a>')
      print prettify(myXML)

      The example above would output the following:

      >>>
      <?xml version="1.0"?>
      <a>
        <b>
          <c>
            <d/>
          </c>
        </b>
      </a>

      By the way I don't even need to see the XML I'm processing most of the time, so why all the pretty printing fuss?

      Well, because it bothers me …

      And all good XML should look like an X-wing starfighter. If it doesn't your probably doing something wrong or your schema just sucks.

      It isn't called an X-wing for no reason.

      :P

      --------------

      Related Content:

      Written by nitin

      November 12th, 2011 at 11:05 am

      Posted in XML

      Tagged with , ,

      MakeMusic makes a great move in hiring Good

      leave a comment

      MakeMusic, the company behind Finale, has entered into an agreement to purchase Recordare. You can see the press release here but here's the really important part (hyperlinks mine):

      Under the terms of the agreement, MakeMusic is purchasing the MusicXML™ open format and Dolet® software technology, including copyrights, source code, and trademarks. MakeMusic also announced that the founder of Recordare and inventor of MusicXML, Michael Good, will be joining MakeMusic as the Director of Digital Sheet Music.

      A few people, myself included, were both excited for Recordare/Good but were also wondering what this means for the future of MusicXML in terms of remaining open so here's the scoop – posted on November 2, 2011 – from Michael Good himself on the MusicXML discussion list:

       … MusicXML will remain an open format. MusicXML will continue to be licensed under the same open, royalty-free terms it has today. MusicXML's value comes from being an open format that anybody can freely use in their products and services. That will not change. Community development of future versions of the MusicXML format will not change. What will change is that MusicXML will now be supported with a larger company with more resources. There are exciting possibilities ahead!

      Personally, I'm not worried.

      In terms of XML approaches to music encoding, there's MusicXML and then there's everything else. Mr. Good's known all along that building relationships that ensure software support is a key to success for the format. He's even been kind to the little guys: emailing me and commenting on this blog in regard to some of my work with MusicXML for digital libraries.

      So congratulations to Michael Good and MusicXML. I'm looking forward to hearing the next movement.

      --------------

      Related Content:

      Written by nitin

      November 6th, 2011 at 9:04 am

      Posted in music notation,news

      Tagged with , ,

      Switch to our mobile site