Skip to content
This repository has been archived by the owner on Sep 6, 2023. It is now read-only.

Handling of NS prefixes #10

Open
raffazizzi opened this issue Mar 1, 2014 · 9 comments
Open

Handling of NS prefixes #10

raffazizzi opened this issue Mar 1, 2014 · 9 comments

Comments

@raffazizzi
Copy link

aerhard said: "Can jQuery handle namespace prefixes at all (in a way other than 'find score or mei:score')? Obviously, everything would work if we replaced all jQuery.find()s etc. by getElementByTagNameNS. Do you think this would be a good solution or do you have other plans (for example, transform the MEI files before sending them to MEItoVexFlow)?"

jQuery can match most prefixes using prefix\\:element but it's not very reliable. Perhaps getElementByTagNameNS is a good idea.

@aerhard
Copy link

aerhard commented Mar 2, 2014

getElementsByTagNameNS('*', localName) seems to work very well in mei2vf, I just did a test. At least in Firefox, it even performs better than jQuery.find(localName). I'll send a pull request when your changes are on the master branch, so you can have a look.

@zolaemil
Copy link

zolaemil commented Mar 2, 2014

Currently, the way we deal with XML namespaces is this:

  1. select the root element (whichever element you consider root for your application) from the XML DOM object using getElementsByTagNameNS(), then
  2. pass on the resulting node list to render_notation (see https://github.com/TEI-Music-SIG/MEItoVexFlow/blob/master/tests/runtest.js#L22 ).

This practice eliminates the need of prefix\\:element in JQuery.find() calls; and as long as the root element doesn't have descendants that belong to other namespaces, $.find() will work just fine (it will return any element regardless whether it's spelled with or without the prefix in the xml document)

It's true, $.find('tagname') searches only for the localName property, so it will return any element, regardless of what namespace it belongs to. However, as far as I am aware, MEI elements can only contain elements that belong to the MEI namespace ("http://www.music-encoding.org/ns/mei"), therefore using $.find() isn't really a problem.

If this is not the case, then we do need more precise control over namespaces, and then replacing JQuery.find() with getElementsByTagNameNS() would be necessary. But then there are some further things to consider: there are a couple of instances of JQuery.find() that use attribute constraints $.find('elem[attr_name="attr_value"]'), so that will need some extra code to implement; and JQuery.children() needs to be replaced too, because at the moment the assumption is that all children of an mei:element will be mei:element as well.

I wouldn't be surprised if the native function was faster, but I think we should do a a comprehensive profiling before starting to optimise on performance - should this be the primary reasons for some changes.

@raffazizzi
Copy link
Author

I agree with Zoltan: being able to use JQuery's functions to traverse the tree is essential.

Also, I've tried to change one of test XML files to include prefixes and all works as expected. So the only thing that one needs to do is loading the XML file as @zolaemil indicated. Perhaps we need to add a section about that in the README.

@aerhard
Copy link

aerhard commented Mar 2, 2014

i agree -- performance isn't crucial now -- I mentioned that only to point out that you wouldn't have to worry about getelementsbytagnameNS being too slow (before the test, I wasn't sure how it would perform). In my setup, data is already passed to render_notation the way you describe it (for example, when I run tests.html which uses runtest.js), but the prokofiev test with the prefixes on all elements fails -- does this particular test work with your setup? I would be great if you found a way to get jQuery's find('note') to match 'mei:note'.

@raffazizzi
Copy link
Author

I commented this line out to restore the prokofiev test and it works for me:

https://github.com/TEI-Music-SIG/MEItoVexFlow/blob/master/tests/tests.html#L28

@aerhard
Copy link

aerhard commented Mar 2, 2014

Thank you, Raffaele. It seems to be a cross-browser issue. I've been testing with Firefox, where the tests failed, but now in Chrome, everything's working fine... So, what do you think? Should we skip this issue and postpone working on compatibility?

@raffazizzi
Copy link
Author

You're right. This is a tricky problem that will have to be addressed at some point.
If we need to replace $.find() and other functions that need a tag name with getElementByTagNameNS, we could always pass the result to jQuery to be able to keep relying on functions like children(), parent(), etc. This is maybe not so pretty, though...
Reading this helpful (but old) post: http://www.zachleat.com/web/selecting-xml-with-javascript/ I've come across Sarissa, a js library that offers cross-browser XML tree parsing functions (and more). http://dev.abiss.gr/sarissa/
But it's heavy! 40KB+

@zolaemil
Copy link

zolaemil commented Mar 2, 2014

I can confirm the same behaviour in Firefox. Strangely enough, there are some elements that can be spelled both with or without prefix and they are rendered correctly in Firefox, but others can only be spelled without prefix. Here's the summary of my little experiment with TC.Prokofiev.xml (Firefox 26.0):

Elements agnostic to prefix: music, body, mdiv, score, staffGrp, note, beam, rest, and the two staffDefs inside the inner most staffGrp (but not the one of the vocal part)

All other elements seem to be retrieved by $.find('tagname') only if they are spelled without the prefix.

@aerhard
Copy link

aerhard commented Mar 3, 2014

a provisional, 'quick and dirty' way of providing cross-browser support could be to just get rid of the prefixes before they are passed to render_notation. As @zolaemil said, meitovexflow only has to deal with MEI, and I don't see a use case where it would be necessary to distinguish between 'note' and 'mei:note'. In order to avoid slowing down the good browsers, you could check the browser and write something like this in loadXMLDoc:
var result = (isChrome) ? xmlhttp.responseXML : $.parseXML(xmlhttp.responseText.replace(/(<[/]?)[\w]+:/g, '$1'));
well, that's not elegant and goes to the cost of perfomance, but at least it's not an effort and it seems to work well in Firefox (IE 9 can't cope with the extension of the node prototype).

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants