3

I would like to parse an .mxl file (MusicXML) with clojure

So far i've seen a lot of tools to work with .xml files but I can't find a way to work with .mxl, maybe i should convert mxl to xml first but i don't know how to do that neither.

szymanowski
  • 1,359
  • 1
  • 14
  • 25
  • Have you tried parsing the file as XML? Based on the Wikipedia example it looks like it could be done. – ponzao Jan 21 '14 at 11:54
  • i've got this exception: SAXParseException Content is not allowed in prolog. com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException (ErrorHandlerWrapper.java:195) – szymanowski Jan 21 '14 at 12:04
  • The exception has probably nothing to do with the XML parsing code but with the file, check [this](http://stackoverflow.com/questions/5138696/org-xml-sax-saxparseexception-content-is-not-allowed-in-prolog) SO question for possible solutions on the exception you're getting. – juan.facorro Jan 21 '14 at 12:20

3 Answers3

4

From the Wikipedia page on MusicXML:

The textual representation listed above is verbose; MusicXML v2.0 addresses this by adding a compressed zip format with a .mxl suffix that can make files roughly one-twentieth the size of the uncompressed version.[16]

I'm guessing that your .mxl file is an XML file which has been compressed, and this is why you're getting parse errors. As far I can gather, the compression algorithm is a zip algorithm, so you should be able to use java's zip functionality to get at it.

EDIT

I just had a go at this with a sample .mxl file I found online. The .mxl file, once unzipped contained the xml file within it. I was then able to use following (inspired by this answer) to get the raw XML...

 (defn extract-mxl [path]
   (let [[_ filename] (re-matches #"(.*)\.mxl$" (.getName (java.io.File. path)))
         zipfile (java.util.zip.ZipFile. path)
         zipentry (.getEntry zipfile (str filename ".xml"))
         in (.getInputStream zipfile zipentry)] 
     (slurp in)))
Community
  • 1
  • 1
Daniel Neal
  • 4,165
  • 2
  • 20
  • 34
  • it doesn't work... it seems that DeflaterInputStream (my edit) is for compress data , I should use InflaterInputStream for decompression but it doesn't work... – szymanowski Jan 22 '14 at 07:12
  • I've edited after testing with an .mxl I found...sorry about the previous code not working! – Daniel Neal Jan 22 '14 at 11:18
  • i've got this: java.util.zip.ZipFile.getInputStream (ZipFile.java:194) – szymanowski Jan 22 '14 at 11:31
  • filename => "inv1" zipfile => # zipentry => nil NullPointerException java.util.zip.ZipFile.getInputStream (ZipFile.java:194) – szymanowski Jan 23 '14 at 06:13
  • does the file .xml file is created or am i supposed to create manually? I am sorry but i don't understand much of Java Zip stuffs... – szymanowski Jan 23 '14 at 06:22
  • Try unzipping the file manually and seeing what's in there. The above code assumes that the .mxl, when unzipped contains .xml. – Daniel Neal Jan 24 '14 at 12:00
  • Ok I see... i've changed the filename before trying your code :) it works now! thank you for your patience – szymanowski Jan 24 '14 at 12:17
1

MusicXML's zip structure for .mxl files is similar to that of the EPUB format. See http://www.musicxml.com/tutorial/compressed-mxl-files/zip-archive-structure/ in the MusicXML tutorial for more information about where to find the XML score data within the MXL archive.

Michael
  • 733
  • 3
  • 8
0

if someone stumbles upon this, and can't figure out how to unzip the compressed mxl file:

on mac, I just renamed it to .zip and it worked out fine!